lisp: Move to plugin
[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
5625         break;
5626     }
5627
5628   if (pci_addr == 0)
5629     {
5630       errmsg ("pci address must be non zero. ");
5631       return -99;
5632     }
5633
5634   /* Construct the API message */
5635   M (VIRTIO_PCI_CREATE_V2, mp);
5636
5637   mp->use_random_mac = random_mac;
5638
5639   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
5640   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
5641   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
5642   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
5643
5644   mp->features = clib_host_to_net_u64 (features);
5645   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
5646
5647   if (random_mac == 0)
5648     clib_memcpy (mp->mac_address, mac_address, 6);
5649
5650   /* send it... */
5651   S (mp);
5652
5653   /* Wait for a reply... */
5654   W (ret);
5655   return ret;
5656 }
5657
5658 static int
5659 api_virtio_pci_delete (vat_main_t * vam)
5660 {
5661   unformat_input_t *i = vam->input;
5662   vl_api_virtio_pci_delete_t *mp;
5663   u32 sw_if_index = ~0;
5664   u8 sw_if_index_set = 0;
5665   int ret;
5666
5667   /* Parse args required to build the message */
5668   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5669     {
5670       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5671         sw_if_index_set = 1;
5672       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5673         sw_if_index_set = 1;
5674       else
5675         break;
5676     }
5677
5678   if (sw_if_index_set == 0)
5679     {
5680       errmsg ("missing vpp interface name. ");
5681       return -99;
5682     }
5683
5684   /* Construct the API message */
5685   M (VIRTIO_PCI_DELETE, mp);
5686
5687   mp->sw_if_index = htonl (sw_if_index);
5688
5689   /* send it... */
5690   S (mp);
5691
5692   /* Wait for a reply... */
5693   W (ret);
5694   return ret;
5695 }
5696
5697 static int
5698 api_bond_create (vat_main_t * vam)
5699 {
5700   unformat_input_t *i = vam->input;
5701   vl_api_bond_create_t *mp;
5702   u8 mac_address[6];
5703   u8 custom_mac = 0;
5704   int ret;
5705   u8 mode;
5706   u8 lb;
5707   u8 mode_is_set = 0;
5708   u32 id = ~0;
5709   u8 numa_only = 0;
5710
5711   clib_memset (mac_address, 0, sizeof (mac_address));
5712   lb = BOND_LB_L2;
5713
5714   /* Parse args required to build the message */
5715   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5716     {
5717       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5718         mode_is_set = 1;
5719       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5720                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5721         ;
5722       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5723                          mac_address))
5724         custom_mac = 1;
5725       else if (unformat (i, "numa-only"))
5726         numa_only = 1;
5727       else if (unformat (i, "id %u", &id))
5728         ;
5729       else
5730         break;
5731     }
5732
5733   if (mode_is_set == 0)
5734     {
5735       errmsg ("Missing bond mode. ");
5736       return -99;
5737     }
5738
5739   /* Construct the API message */
5740   M (BOND_CREATE, mp);
5741
5742   mp->use_custom_mac = custom_mac;
5743
5744   mp->mode = htonl (mode);
5745   mp->lb = htonl (lb);
5746   mp->id = htonl (id);
5747   mp->numa_only = numa_only;
5748
5749   if (custom_mac)
5750     clib_memcpy (mp->mac_address, mac_address, 6);
5751
5752   /* send it... */
5753   S (mp);
5754
5755   /* Wait for a reply... */
5756   W (ret);
5757   return ret;
5758 }
5759
5760 static int
5761 api_bond_create2 (vat_main_t * vam)
5762 {
5763   unformat_input_t *i = vam->input;
5764   vl_api_bond_create2_t *mp;
5765   u8 mac_address[6];
5766   u8 custom_mac = 0;
5767   int ret;
5768   u8 mode;
5769   u8 lb;
5770   u8 mode_is_set = 0;
5771   u32 id = ~0;
5772   u8 numa_only = 0;
5773   u8 gso = 0;
5774
5775   clib_memset (mac_address, 0, sizeof (mac_address));
5776   lb = BOND_LB_L2;
5777
5778   /* Parse args required to build the message */
5779   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5780     {
5781       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5782         mode_is_set = 1;
5783       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5784                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5785         ;
5786       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5787                          mac_address))
5788         custom_mac = 1;
5789       else if (unformat (i, "numa-only"))
5790         numa_only = 1;
5791       else if (unformat (i, "gso"))
5792         gso = 1;
5793       else if (unformat (i, "id %u", &id))
5794         ;
5795       else
5796         break;
5797     }
5798
5799   if (mode_is_set == 0)
5800     {
5801       errmsg ("Missing bond mode. ");
5802       return -99;
5803     }
5804
5805   /* Construct the API message */
5806   M (BOND_CREATE2, mp);
5807
5808   mp->use_custom_mac = custom_mac;
5809
5810   mp->mode = htonl (mode);
5811   mp->lb = htonl (lb);
5812   mp->id = htonl (id);
5813   mp->numa_only = numa_only;
5814   mp->enable_gso = gso;
5815
5816   if (custom_mac)
5817     clib_memcpy (mp->mac_address, mac_address, 6);
5818
5819   /* send it... */
5820   S (mp);
5821
5822   /* Wait for a reply... */
5823   W (ret);
5824   return ret;
5825 }
5826
5827 static int
5828 api_bond_delete (vat_main_t * vam)
5829 {
5830   unformat_input_t *i = vam->input;
5831   vl_api_bond_delete_t *mp;
5832   u32 sw_if_index = ~0;
5833   u8 sw_if_index_set = 0;
5834   int ret;
5835
5836   /* Parse args required to build the message */
5837   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5838     {
5839       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5840         sw_if_index_set = 1;
5841       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5842         sw_if_index_set = 1;
5843       else
5844         break;
5845     }
5846
5847   if (sw_if_index_set == 0)
5848     {
5849       errmsg ("missing vpp interface name. ");
5850       return -99;
5851     }
5852
5853   /* Construct the API message */
5854   M (BOND_DELETE, mp);
5855
5856   mp->sw_if_index = ntohl (sw_if_index);
5857
5858   /* send it... */
5859   S (mp);
5860
5861   /* Wait for a reply... */
5862   W (ret);
5863   return ret;
5864 }
5865
5866 static int
5867 api_bond_add_member (vat_main_t * vam)
5868 {
5869   unformat_input_t *i = vam->input;
5870   vl_api_bond_add_member_t *mp;
5871   u32 bond_sw_if_index;
5872   int ret;
5873   u8 is_passive;
5874   u8 is_long_timeout;
5875   u32 bond_sw_if_index_is_set = 0;
5876   u32 sw_if_index;
5877   u8 sw_if_index_is_set = 0;
5878
5879   /* Parse args required to build the message */
5880   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5881     {
5882       if (unformat (i, "sw_if_index %d", &sw_if_index))
5883         sw_if_index_is_set = 1;
5884       else if (unformat (i, "bond %u", &bond_sw_if_index))
5885         bond_sw_if_index_is_set = 1;
5886       else if (unformat (i, "passive %d", &is_passive))
5887         ;
5888       else if (unformat (i, "long-timeout %d", &is_long_timeout))
5889         ;
5890       else
5891         break;
5892     }
5893
5894   if (bond_sw_if_index_is_set == 0)
5895     {
5896       errmsg ("Missing bond sw_if_index. ");
5897       return -99;
5898     }
5899   if (sw_if_index_is_set == 0)
5900     {
5901       errmsg ("Missing member sw_if_index. ");
5902       return -99;
5903     }
5904
5905   /* Construct the API message */
5906   M (BOND_ADD_MEMBER, mp);
5907
5908   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
5909   mp->sw_if_index = ntohl (sw_if_index);
5910   mp->is_long_timeout = is_long_timeout;
5911   mp->is_passive = is_passive;
5912
5913   /* send it... */
5914   S (mp);
5915
5916   /* Wait for a reply... */
5917   W (ret);
5918   return ret;
5919 }
5920
5921 static int
5922 api_bond_detach_member (vat_main_t * vam)
5923 {
5924   unformat_input_t *i = vam->input;
5925   vl_api_bond_detach_member_t *mp;
5926   u32 sw_if_index = ~0;
5927   u8 sw_if_index_set = 0;
5928   int ret;
5929
5930   /* Parse args required to build the message */
5931   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5932     {
5933       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5934         sw_if_index_set = 1;
5935       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5936         sw_if_index_set = 1;
5937       else
5938         break;
5939     }
5940
5941   if (sw_if_index_set == 0)
5942     {
5943       errmsg ("missing vpp interface name. ");
5944       return -99;
5945     }
5946
5947   /* Construct the API message */
5948   M (BOND_DETACH_MEMBER, mp);
5949
5950   mp->sw_if_index = ntohl (sw_if_index);
5951
5952   /* send it... */
5953   S (mp);
5954
5955   /* Wait for a reply... */
5956   W (ret);
5957   return ret;
5958 }
5959
5960 static int
5961 api_ip_table_add_del (vat_main_t * vam)
5962 {
5963   unformat_input_t *i = vam->input;
5964   vl_api_ip_table_add_del_t *mp;
5965   u32 table_id = ~0;
5966   u8 is_ipv6 = 0;
5967   u8 is_add = 1;
5968   int ret = 0;
5969
5970   /* Parse args required to build the message */
5971   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5972     {
5973       if (unformat (i, "ipv6"))
5974         is_ipv6 = 1;
5975       else if (unformat (i, "del"))
5976         is_add = 0;
5977       else if (unformat (i, "add"))
5978         is_add = 1;
5979       else if (unformat (i, "table %d", &table_id))
5980         ;
5981       else
5982         {
5983           clib_warning ("parse error '%U'", format_unformat_error, i);
5984           return -99;
5985         }
5986     }
5987
5988   if (~0 == table_id)
5989     {
5990       errmsg ("missing table-ID");
5991       return -99;
5992     }
5993
5994   /* Construct the API message */
5995   M (IP_TABLE_ADD_DEL, mp);
5996
5997   mp->table.table_id = ntohl (table_id);
5998   mp->table.is_ip6 = is_ipv6;
5999   mp->is_add = is_add;
6000
6001   /* send it... */
6002   S (mp);
6003
6004   /* Wait for a reply... */
6005   W (ret);
6006
6007   return ret;
6008 }
6009
6010 uword
6011 unformat_fib_path (unformat_input_t * input, va_list * args)
6012 {
6013   vat_main_t *vam = va_arg (*args, vat_main_t *);
6014   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
6015   u32 weight, preference;
6016   mpls_label_t out_label;
6017
6018   clib_memset (path, 0, sizeof (*path));
6019   path->weight = 1;
6020   path->sw_if_index = ~0;
6021   path->rpf_id = ~0;
6022   path->n_labels = 0;
6023
6024   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6025     {
6026       if (unformat (input, "%U %U",
6027                     unformat_vl_api_ip4_address,
6028                     &path->nh.address.ip4,
6029                     api_unformat_sw_if_index, vam, &path->sw_if_index))
6030         {
6031           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6032         }
6033       else if (unformat (input, "%U %U",
6034                          unformat_vl_api_ip6_address,
6035                          &path->nh.address.ip6,
6036                          api_unformat_sw_if_index, vam, &path->sw_if_index))
6037         {
6038           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6039         }
6040       else if (unformat (input, "weight %u", &weight))
6041         {
6042           path->weight = weight;
6043         }
6044       else if (unformat (input, "preference %u", &preference))
6045         {
6046           path->preference = preference;
6047         }
6048       else if (unformat (input, "%U next-hop-table %d",
6049                          unformat_vl_api_ip4_address,
6050                          &path->nh.address.ip4, &path->table_id))
6051         {
6052           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6053         }
6054       else if (unformat (input, "%U next-hop-table %d",
6055                          unformat_vl_api_ip6_address,
6056                          &path->nh.address.ip6, &path->table_id))
6057         {
6058           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6059         }
6060       else if (unformat (input, "%U",
6061                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
6062         {
6063           /*
6064            * the recursive next-hops are by default in the default table
6065            */
6066           path->table_id = 0;
6067           path->sw_if_index = ~0;
6068           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6069         }
6070       else if (unformat (input, "%U",
6071                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
6072         {
6073           /*
6074            * the recursive next-hops are by default in the default table
6075            */
6076           path->table_id = 0;
6077           path->sw_if_index = ~0;
6078           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6079         }
6080       else if (unformat (input, "resolve-via-host"))
6081         {
6082           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
6083         }
6084       else if (unformat (input, "resolve-via-attached"))
6085         {
6086           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
6087         }
6088       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
6089         {
6090           path->type = FIB_API_PATH_TYPE_LOCAL;
6091           path->sw_if_index = ~0;
6092           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6093         }
6094       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
6095         {
6096           path->type = FIB_API_PATH_TYPE_LOCAL;
6097           path->sw_if_index = ~0;
6098           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6099         }
6100       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
6101         ;
6102       else if (unformat (input, "via-label %d", &path->nh.via_label))
6103         {
6104           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
6105           path->sw_if_index = ~0;
6106         }
6107       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
6108         {
6109           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
6110           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
6111         }
6112       else if (unformat (input, "local"))
6113         {
6114           path->type = FIB_API_PATH_TYPE_LOCAL;
6115         }
6116       else if (unformat (input, "out-labels"))
6117         {
6118           while (unformat (input, "%d", &out_label))
6119             {
6120               path->label_stack[path->n_labels].label = out_label;
6121               path->label_stack[path->n_labels].is_uniform = 0;
6122               path->label_stack[path->n_labels].ttl = 64;
6123               path->n_labels++;
6124             }
6125         }
6126       else if (unformat (input, "via"))
6127         {
6128           /* new path, back up and return */
6129           unformat_put_input (input);
6130           unformat_put_input (input);
6131           unformat_put_input (input);
6132           unformat_put_input (input);
6133           break;
6134         }
6135       else
6136         {
6137           return (0);
6138         }
6139     }
6140
6141   path->proto = ntohl (path->proto);
6142   path->type = ntohl (path->type);
6143   path->flags = ntohl (path->flags);
6144   path->table_id = ntohl (path->table_id);
6145   path->sw_if_index = ntohl (path->sw_if_index);
6146
6147   return (1);
6148 }
6149
6150 static int
6151 api_ip_route_add_del (vat_main_t * vam)
6152 {
6153   unformat_input_t *i = vam->input;
6154   vl_api_ip_route_add_del_t *mp;
6155   u32 vrf_id = 0;
6156   u8 is_add = 1;
6157   u8 is_multipath = 0;
6158   u8 prefix_set = 0;
6159   u8 path_count = 0;
6160   vl_api_prefix_t pfx = { };
6161   vl_api_fib_path_t paths[8];
6162   int count = 1;
6163   int j;
6164   f64 before = 0;
6165   u32 random_add_del = 0;
6166   u32 *random_vector = 0;
6167   u32 random_seed = 0xdeaddabe;
6168
6169   /* Parse args required to build the message */
6170   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6171     {
6172       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6173         prefix_set = 1;
6174       else if (unformat (i, "del"))
6175         is_add = 0;
6176       else if (unformat (i, "add"))
6177         is_add = 1;
6178       else if (unformat (i, "vrf %d", &vrf_id))
6179         ;
6180       else if (unformat (i, "count %d", &count))
6181         ;
6182       else if (unformat (i, "random"))
6183         random_add_del = 1;
6184       else if (unformat (i, "multipath"))
6185         is_multipath = 1;
6186       else if (unformat (i, "seed %d", &random_seed))
6187         ;
6188       else
6189         if (unformat
6190             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6191         {
6192           path_count++;
6193           if (8 == path_count)
6194             {
6195               errmsg ("max 8 paths");
6196               return -99;
6197             }
6198         }
6199       else
6200         {
6201           clib_warning ("parse error '%U'", format_unformat_error, i);
6202           return -99;
6203         }
6204     }
6205
6206   if (!path_count)
6207     {
6208       errmsg ("specify a path; via ...");
6209       return -99;
6210     }
6211   if (prefix_set == 0)
6212     {
6213       errmsg ("missing prefix");
6214       return -99;
6215     }
6216
6217   /* Generate a pile of unique, random routes */
6218   if (random_add_del)
6219     {
6220       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
6221       u32 this_random_address;
6222       uword *random_hash;
6223
6224       random_hash = hash_create (count, sizeof (uword));
6225
6226       hash_set (random_hash, i->as_u32, 1);
6227       for (j = 0; j <= count; j++)
6228         {
6229           do
6230             {
6231               this_random_address = random_u32 (&random_seed);
6232               this_random_address =
6233                 clib_host_to_net_u32 (this_random_address);
6234             }
6235           while (hash_get (random_hash, this_random_address));
6236           vec_add1 (random_vector, this_random_address);
6237           hash_set (random_hash, this_random_address, 1);
6238         }
6239       hash_free (random_hash);
6240       set_ip4_address (&pfx.address, random_vector[0]);
6241     }
6242
6243   if (count > 1)
6244     {
6245       /* Turn on async mode */
6246       vam->async_mode = 1;
6247       vam->async_errors = 0;
6248       before = vat_time_now (vam);
6249     }
6250
6251   for (j = 0; j < count; j++)
6252     {
6253       /* Construct the API message */
6254       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6255
6256       mp->is_add = is_add;
6257       mp->is_multipath = is_multipath;
6258
6259       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6260       mp->route.table_id = ntohl (vrf_id);
6261       mp->route.n_paths = path_count;
6262
6263       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
6264
6265       if (random_add_del)
6266         set_ip4_address (&pfx.address, random_vector[j + 1]);
6267       else
6268         increment_address (&pfx.address);
6269       /* send it... */
6270       S (mp);
6271       /* If we receive SIGTERM, stop now... */
6272       if (vam->do_exit)
6273         break;
6274     }
6275
6276   /* When testing multiple add/del ops, use a control-ping to sync */
6277   if (count > 1)
6278     {
6279       vl_api_control_ping_t *mp_ping;
6280       f64 after;
6281       f64 timeout;
6282
6283       /* Shut off async mode */
6284       vam->async_mode = 0;
6285
6286       MPING (CONTROL_PING, mp_ping);
6287       S (mp_ping);
6288
6289       timeout = vat_time_now (vam) + 1.0;
6290       while (vat_time_now (vam) < timeout)
6291         if (vam->result_ready == 1)
6292           goto out;
6293       vam->retval = -99;
6294
6295     out:
6296       if (vam->retval == -99)
6297         errmsg ("timeout");
6298
6299       if (vam->async_errors > 0)
6300         {
6301           errmsg ("%d asynchronous errors", vam->async_errors);
6302           vam->retval = -98;
6303         }
6304       vam->async_errors = 0;
6305       after = vat_time_now (vam);
6306
6307       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6308       if (j > 0)
6309         count = j;
6310
6311       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6312              count, after - before, count / (after - before));
6313     }
6314   else
6315     {
6316       int ret;
6317
6318       /* Wait for a reply... */
6319       W (ret);
6320       return ret;
6321     }
6322
6323   /* Return the good/bad news */
6324   return (vam->retval);
6325 }
6326
6327 static int
6328 api_ip_mroute_add_del (vat_main_t * vam)
6329 {
6330   unformat_input_t *i = vam->input;
6331   u8 path_set = 0, prefix_set = 0, is_add = 1;
6332   vl_api_ip_mroute_add_del_t *mp;
6333   mfib_entry_flags_t eflags = 0;
6334   vl_api_mfib_path_t path;
6335   vl_api_mprefix_t pfx = { };
6336   u32 vrf_id = 0;
6337   int ret;
6338
6339   /* Parse args required to build the message */
6340   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6341     {
6342       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
6343         {
6344           prefix_set = 1;
6345           pfx.grp_address_length = htons (pfx.grp_address_length);
6346         }
6347       else if (unformat (i, "del"))
6348         is_add = 0;
6349       else if (unformat (i, "add"))
6350         is_add = 1;
6351       else if (unformat (i, "vrf %d", &vrf_id))
6352         ;
6353       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
6354         path.itf_flags = htonl (path.itf_flags);
6355       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
6356         ;
6357       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
6358         path_set = 1;
6359       else
6360         {
6361           clib_warning ("parse error '%U'", format_unformat_error, i);
6362           return -99;
6363         }
6364     }
6365
6366   if (prefix_set == 0)
6367     {
6368       errmsg ("missing addresses\n");
6369       return -99;
6370     }
6371   if (path_set == 0)
6372     {
6373       errmsg ("missing path\n");
6374       return -99;
6375     }
6376
6377   /* Construct the API message */
6378   M (IP_MROUTE_ADD_DEL, mp);
6379
6380   mp->is_add = is_add;
6381   mp->is_multipath = 1;
6382
6383   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6384   mp->route.table_id = htonl (vrf_id);
6385   mp->route.n_paths = 1;
6386   mp->route.entry_flags = htonl (eflags);
6387
6388   clib_memcpy (&mp->route.paths, &path, sizeof (path));
6389
6390   /* send it... */
6391   S (mp);
6392   /* Wait for a reply... */
6393   W (ret);
6394   return ret;
6395 }
6396
6397 static int
6398 api_mpls_table_add_del (vat_main_t * vam)
6399 {
6400   unformat_input_t *i = vam->input;
6401   vl_api_mpls_table_add_del_t *mp;
6402   u32 table_id = ~0;
6403   u8 is_add = 1;
6404   int ret = 0;
6405
6406   /* Parse args required to build the message */
6407   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6408     {
6409       if (unformat (i, "table %d", &table_id))
6410         ;
6411       else if (unformat (i, "del"))
6412         is_add = 0;
6413       else if (unformat (i, "add"))
6414         is_add = 1;
6415       else
6416         {
6417           clib_warning ("parse error '%U'", format_unformat_error, i);
6418           return -99;
6419         }
6420     }
6421
6422   if (~0 == table_id)
6423     {
6424       errmsg ("missing table-ID");
6425       return -99;
6426     }
6427
6428   /* Construct the API message */
6429   M (MPLS_TABLE_ADD_DEL, mp);
6430
6431   mp->mt_table.mt_table_id = ntohl (table_id);
6432   mp->mt_is_add = is_add;
6433
6434   /* send it... */
6435   S (mp);
6436
6437   /* Wait for a reply... */
6438   W (ret);
6439
6440   return ret;
6441 }
6442
6443 static int
6444 api_mpls_route_add_del (vat_main_t * vam)
6445 {
6446   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
6447   mpls_label_t local_label = MPLS_LABEL_INVALID;
6448   unformat_input_t *i = vam->input;
6449   vl_api_mpls_route_add_del_t *mp;
6450   vl_api_fib_path_t paths[8];
6451   int count = 1, j;
6452   f64 before = 0;
6453
6454   /* Parse args required to build the message */
6455   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6456     {
6457       if (unformat (i, "%d", &local_label))
6458         ;
6459       else if (unformat (i, "eos"))
6460         is_eos = 1;
6461       else if (unformat (i, "non-eos"))
6462         is_eos = 0;
6463       else if (unformat (i, "del"))
6464         is_add = 0;
6465       else if (unformat (i, "add"))
6466         is_add = 1;
6467       else if (unformat (i, "multipath"))
6468         is_multipath = 1;
6469       else if (unformat (i, "count %d", &count))
6470         ;
6471       else
6472         if (unformat
6473             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6474         {
6475           path_count++;
6476           if (8 == path_count)
6477             {
6478               errmsg ("max 8 paths");
6479               return -99;
6480             }
6481         }
6482       else
6483         {
6484           clib_warning ("parse error '%U'", format_unformat_error, i);
6485           return -99;
6486         }
6487     }
6488
6489   if (!path_count)
6490     {
6491       errmsg ("specify a path; via ...");
6492       return -99;
6493     }
6494
6495   if (MPLS_LABEL_INVALID == local_label)
6496     {
6497       errmsg ("missing label");
6498       return -99;
6499     }
6500
6501   if (count > 1)
6502     {
6503       /* Turn on async mode */
6504       vam->async_mode = 1;
6505       vam->async_errors = 0;
6506       before = vat_time_now (vam);
6507     }
6508
6509   for (j = 0; j < count; j++)
6510     {
6511       /* Construct the API message */
6512       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6513
6514       mp->mr_is_add = is_add;
6515       mp->mr_is_multipath = is_multipath;
6516
6517       mp->mr_route.mr_label = local_label;
6518       mp->mr_route.mr_eos = is_eos;
6519       mp->mr_route.mr_table_id = 0;
6520       mp->mr_route.mr_n_paths = path_count;
6521
6522       clib_memcpy (&mp->mr_route.mr_paths, paths,
6523                    sizeof (paths[0]) * path_count);
6524
6525       local_label++;
6526
6527       /* send it... */
6528       S (mp);
6529       /* If we receive SIGTERM, stop now... */
6530       if (vam->do_exit)
6531         break;
6532     }
6533
6534   /* When testing multiple add/del ops, use a control-ping to sync */
6535   if (count > 1)
6536     {
6537       vl_api_control_ping_t *mp_ping;
6538       f64 after;
6539       f64 timeout;
6540
6541       /* Shut off async mode */
6542       vam->async_mode = 0;
6543
6544       MPING (CONTROL_PING, mp_ping);
6545       S (mp_ping);
6546
6547       timeout = vat_time_now (vam) + 1.0;
6548       while (vat_time_now (vam) < timeout)
6549         if (vam->result_ready == 1)
6550           goto out;
6551       vam->retval = -99;
6552
6553     out:
6554       if (vam->retval == -99)
6555         errmsg ("timeout");
6556
6557       if (vam->async_errors > 0)
6558         {
6559           errmsg ("%d asynchronous errors", vam->async_errors);
6560           vam->retval = -98;
6561         }
6562       vam->async_errors = 0;
6563       after = vat_time_now (vam);
6564
6565       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6566       if (j > 0)
6567         count = j;
6568
6569       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6570              count, after - before, count / (after - before));
6571     }
6572   else
6573     {
6574       int ret;
6575
6576       /* Wait for a reply... */
6577       W (ret);
6578       return ret;
6579     }
6580
6581   /* Return the good/bad news */
6582   return (vam->retval);
6583   return (0);
6584 }
6585
6586 static int
6587 api_mpls_ip_bind_unbind (vat_main_t * vam)
6588 {
6589   unformat_input_t *i = vam->input;
6590   vl_api_mpls_ip_bind_unbind_t *mp;
6591   u32 ip_table_id = 0;
6592   u8 is_bind = 1;
6593   vl_api_prefix_t pfx;
6594   u8 prefix_set = 0;
6595   mpls_label_t local_label = MPLS_LABEL_INVALID;
6596   int ret;
6597
6598   /* Parse args required to build the message */
6599   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6600     {
6601       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6602         prefix_set = 1;
6603       else if (unformat (i, "%d", &local_label))
6604         ;
6605       else if (unformat (i, "table-id %d", &ip_table_id))
6606         ;
6607       else if (unformat (i, "unbind"))
6608         is_bind = 0;
6609       else if (unformat (i, "bind"))
6610         is_bind = 1;
6611       else
6612         {
6613           clib_warning ("parse error '%U'", format_unformat_error, i);
6614           return -99;
6615         }
6616     }
6617
6618   if (!prefix_set)
6619     {
6620       errmsg ("IP prefix not set");
6621       return -99;
6622     }
6623
6624   if (MPLS_LABEL_INVALID == local_label)
6625     {
6626       errmsg ("missing label");
6627       return -99;
6628     }
6629
6630   /* Construct the API message */
6631   M (MPLS_IP_BIND_UNBIND, mp);
6632
6633   mp->mb_is_bind = is_bind;
6634   mp->mb_ip_table_id = ntohl (ip_table_id);
6635   mp->mb_mpls_table_id = 0;
6636   mp->mb_label = ntohl (local_label);
6637   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
6638
6639   /* send it... */
6640   S (mp);
6641
6642   /* Wait for a reply... */
6643   W (ret);
6644   return ret;
6645   return (0);
6646 }
6647
6648 static int
6649 api_sr_mpls_policy_add (vat_main_t * vam)
6650 {
6651   unformat_input_t *i = vam->input;
6652   vl_api_sr_mpls_policy_add_t *mp;
6653   u32 bsid = 0;
6654   u32 weight = 1;
6655   u8 type = 0;
6656   u8 n_segments = 0;
6657   u32 sid;
6658   u32 *segments = NULL;
6659   int ret;
6660
6661   /* Parse args required to build the message */
6662   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6663     {
6664       if (unformat (i, "bsid %d", &bsid))
6665         ;
6666       else if (unformat (i, "weight %d", &weight))
6667         ;
6668       else if (unformat (i, "spray"))
6669         type = 1;
6670       else if (unformat (i, "next %d", &sid))
6671         {
6672           n_segments += 1;
6673           vec_add1 (segments, htonl (sid));
6674         }
6675       else
6676         {
6677           clib_warning ("parse error '%U'", format_unformat_error, i);
6678           return -99;
6679         }
6680     }
6681
6682   if (bsid == 0)
6683     {
6684       errmsg ("bsid not set");
6685       return -99;
6686     }
6687
6688   if (n_segments == 0)
6689     {
6690       errmsg ("no sid in segment stack");
6691       return -99;
6692     }
6693
6694   /* Construct the API message */
6695   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
6696
6697   mp->bsid = htonl (bsid);
6698   mp->weight = htonl (weight);
6699   mp->is_spray = type;
6700   mp->n_segments = n_segments;
6701   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
6702   vec_free (segments);
6703
6704   /* send it... */
6705   S (mp);
6706
6707   /* Wait for a reply... */
6708   W (ret);
6709   return ret;
6710 }
6711
6712 static int
6713 api_sr_mpls_policy_del (vat_main_t * vam)
6714 {
6715   unformat_input_t *i = vam->input;
6716   vl_api_sr_mpls_policy_del_t *mp;
6717   u32 bsid = 0;
6718   int ret;
6719
6720   /* Parse args required to build the message */
6721   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6722     {
6723       if (unformat (i, "bsid %d", &bsid))
6724         ;
6725       else
6726         {
6727           clib_warning ("parse error '%U'", format_unformat_error, i);
6728           return -99;
6729         }
6730     }
6731
6732   if (bsid == 0)
6733     {
6734       errmsg ("bsid not set");
6735       return -99;
6736     }
6737
6738   /* Construct the API message */
6739   M (SR_MPLS_POLICY_DEL, mp);
6740
6741   mp->bsid = htonl (bsid);
6742
6743   /* send it... */
6744   S (mp);
6745
6746   /* Wait for a reply... */
6747   W (ret);
6748   return ret;
6749 }
6750
6751 static int
6752 api_bier_table_add_del (vat_main_t * vam)
6753 {
6754   unformat_input_t *i = vam->input;
6755   vl_api_bier_table_add_del_t *mp;
6756   u8 is_add = 1;
6757   u32 set = 0, sub_domain = 0, hdr_len = 3;
6758   mpls_label_t local_label = MPLS_LABEL_INVALID;
6759   int ret;
6760
6761   /* Parse args required to build the message */
6762   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6763     {
6764       if (unformat (i, "sub-domain %d", &sub_domain))
6765         ;
6766       else if (unformat (i, "set %d", &set))
6767         ;
6768       else if (unformat (i, "label %d", &local_label))
6769         ;
6770       else if (unformat (i, "hdr-len %d", &hdr_len))
6771         ;
6772       else if (unformat (i, "add"))
6773         is_add = 1;
6774       else if (unformat (i, "del"))
6775         is_add = 0;
6776       else
6777         {
6778           clib_warning ("parse error '%U'", format_unformat_error, i);
6779           return -99;
6780         }
6781     }
6782
6783   if (MPLS_LABEL_INVALID == local_label)
6784     {
6785       errmsg ("missing label\n");
6786       return -99;
6787     }
6788
6789   /* Construct the API message */
6790   M (BIER_TABLE_ADD_DEL, mp);
6791
6792   mp->bt_is_add = is_add;
6793   mp->bt_label = ntohl (local_label);
6794   mp->bt_tbl_id.bt_set = set;
6795   mp->bt_tbl_id.bt_sub_domain = sub_domain;
6796   mp->bt_tbl_id.bt_hdr_len_id = hdr_len;
6797
6798   /* send it... */
6799   S (mp);
6800
6801   /* Wait for a reply... */
6802   W (ret);
6803
6804   return (ret);
6805 }
6806
6807 static int
6808 api_bier_route_add_del (vat_main_t * vam)
6809 {
6810   unformat_input_t *i = vam->input;
6811   vl_api_bier_route_add_del_t *mp;
6812   u8 is_add = 1;
6813   u32 set = 0, sub_domain = 0, hdr_len = 3, bp = 0;
6814   ip4_address_t v4_next_hop_address;
6815   ip6_address_t v6_next_hop_address;
6816   u8 next_hop_set = 0;
6817   u8 next_hop_proto_is_ip4 = 1;
6818   mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID;
6819   int ret;
6820
6821   /* Parse args required to build the message */
6822   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6823     {
6824       if (unformat (i, "%U", unformat_ip4_address, &v4_next_hop_address))
6825         {
6826           next_hop_proto_is_ip4 = 1;
6827           next_hop_set = 1;
6828         }
6829       else if (unformat (i, "%U", unformat_ip6_address, &v6_next_hop_address))
6830         {
6831           next_hop_proto_is_ip4 = 0;
6832           next_hop_set = 1;
6833         }
6834       if (unformat (i, "sub-domain %d", &sub_domain))
6835         ;
6836       else if (unformat (i, "set %d", &set))
6837         ;
6838       else if (unformat (i, "hdr-len %d", &hdr_len))
6839         ;
6840       else if (unformat (i, "bp %d", &bp))
6841         ;
6842       else if (unformat (i, "add"))
6843         is_add = 1;
6844       else if (unformat (i, "del"))
6845         is_add = 0;
6846       else if (unformat (i, "out-label %d", &next_hop_out_label))
6847         ;
6848       else
6849         {
6850           clib_warning ("parse error '%U'", format_unformat_error, i);
6851           return -99;
6852         }
6853     }
6854
6855   if (!next_hop_set || (MPLS_LABEL_INVALID == next_hop_out_label))
6856     {
6857       errmsg ("next hop / label set\n");
6858       return -99;
6859     }
6860   if (0 == bp)
6861     {
6862       errmsg ("bit=position not set\n");
6863       return -99;
6864     }
6865
6866   /* Construct the API message */
6867   M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t));
6868
6869   mp->br_is_add = is_add;
6870   mp->br_route.br_tbl_id.bt_set = set;
6871   mp->br_route.br_tbl_id.bt_sub_domain = sub_domain;
6872   mp->br_route.br_tbl_id.bt_hdr_len_id = hdr_len;
6873   mp->br_route.br_bp = ntohs (bp);
6874   mp->br_route.br_n_paths = 1;
6875   mp->br_route.br_paths[0].n_labels = 1;
6876   mp->br_route.br_paths[0].label_stack[0].label = ntohl (next_hop_out_label);
6877   mp->br_route.br_paths[0].proto = (next_hop_proto_is_ip4 ?
6878                                     FIB_API_PATH_NH_PROTO_IP4 :
6879                                     FIB_API_PATH_NH_PROTO_IP6);
6880
6881   if (next_hop_proto_is_ip4)
6882     {
6883       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip4,
6884                    &v4_next_hop_address, sizeof (v4_next_hop_address));
6885     }
6886   else
6887     {
6888       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip6,
6889                    &v6_next_hop_address, sizeof (v6_next_hop_address));
6890     }
6891
6892   /* send it... */
6893   S (mp);
6894
6895   /* Wait for a reply... */
6896   W (ret);
6897
6898   return (ret);
6899 }
6900
6901 static int
6902 api_mpls_tunnel_add_del (vat_main_t * vam)
6903 {
6904   unformat_input_t *i = vam->input;
6905   vl_api_mpls_tunnel_add_del_t *mp;
6906
6907   vl_api_fib_path_t paths[8];
6908   u32 sw_if_index = ~0;
6909   u8 path_count = 0;
6910   u8 l2_only = 0;
6911   u8 is_add = 1;
6912   int ret;
6913
6914   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6915     {
6916       if (unformat (i, "add"))
6917         is_add = 1;
6918       else
6919         if (unformat
6920             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
6921         is_add = 0;
6922       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
6923         is_add = 0;
6924       else if (unformat (i, "l2-only"))
6925         l2_only = 1;
6926       else
6927         if (unformat
6928             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6929         {
6930           path_count++;
6931           if (8 == path_count)
6932             {
6933               errmsg ("max 8 paths");
6934               return -99;
6935             }
6936         }
6937       else
6938         {
6939           clib_warning ("parse error '%U'", format_unformat_error, i);
6940           return -99;
6941         }
6942     }
6943
6944   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6945
6946   mp->mt_is_add = is_add;
6947   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
6948   mp->mt_tunnel.mt_l2_only = l2_only;
6949   mp->mt_tunnel.mt_is_multicast = 0;
6950   mp->mt_tunnel.mt_n_paths = path_count;
6951
6952   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
6953                sizeof (paths[0]) * path_count);
6954
6955   S (mp);
6956   W (ret);
6957   return ret;
6958 }
6959
6960 static int
6961 api_sw_interface_set_unnumbered (vat_main_t * vam)
6962 {
6963   unformat_input_t *i = vam->input;
6964   vl_api_sw_interface_set_unnumbered_t *mp;
6965   u32 sw_if_index;
6966   u32 unnum_sw_index = ~0;
6967   u8 is_add = 1;
6968   u8 sw_if_index_set = 0;
6969   int ret;
6970
6971   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6972     {
6973       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6974         sw_if_index_set = 1;
6975       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6976         sw_if_index_set = 1;
6977       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
6978         ;
6979       else if (unformat (i, "del"))
6980         is_add = 0;
6981       else
6982         {
6983           clib_warning ("parse error '%U'", format_unformat_error, i);
6984           return -99;
6985         }
6986     }
6987
6988   if (sw_if_index_set == 0)
6989     {
6990       errmsg ("missing interface name or sw_if_index");
6991       return -99;
6992     }
6993
6994   M (SW_INTERFACE_SET_UNNUMBERED, mp);
6995
6996   mp->sw_if_index = ntohl (sw_if_index);
6997   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
6998   mp->is_add = is_add;
6999
7000   S (mp);
7001   W (ret);
7002   return ret;
7003 }
7004
7005
7006 static int
7007 api_create_vlan_subif (vat_main_t * vam)
7008 {
7009   unformat_input_t *i = vam->input;
7010   vl_api_create_vlan_subif_t *mp;
7011   u32 sw_if_index;
7012   u8 sw_if_index_set = 0;
7013   u32 vlan_id;
7014   u8 vlan_id_set = 0;
7015   int ret;
7016
7017   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7018     {
7019       if (unformat (i, "sw_if_index %d", &sw_if_index))
7020         sw_if_index_set = 1;
7021       else
7022         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7023         sw_if_index_set = 1;
7024       else if (unformat (i, "vlan %d", &vlan_id))
7025         vlan_id_set = 1;
7026       else
7027         {
7028           clib_warning ("parse error '%U'", format_unformat_error, i);
7029           return -99;
7030         }
7031     }
7032
7033   if (sw_if_index_set == 0)
7034     {
7035       errmsg ("missing interface name or sw_if_index");
7036       return -99;
7037     }
7038
7039   if (vlan_id_set == 0)
7040     {
7041       errmsg ("missing vlan_id");
7042       return -99;
7043     }
7044   M (CREATE_VLAN_SUBIF, mp);
7045
7046   mp->sw_if_index = ntohl (sw_if_index);
7047   mp->vlan_id = ntohl (vlan_id);
7048
7049   S (mp);
7050   W (ret);
7051   return ret;
7052 }
7053
7054 #define foreach_create_subif_bit                \
7055 _(no_tags)                                      \
7056 _(one_tag)                                      \
7057 _(two_tags)                                     \
7058 _(dot1ad)                                       \
7059 _(exact_match)                                  \
7060 _(default_sub)                                  \
7061 _(outer_vlan_id_any)                            \
7062 _(inner_vlan_id_any)
7063
7064 #define foreach_create_subif_flag               \
7065 _(0, "no_tags")                                 \
7066 _(1, "one_tag")                                 \
7067 _(2, "two_tags")                                \
7068 _(3, "dot1ad")                                  \
7069 _(4, "exact_match")                             \
7070 _(5, "default_sub")                             \
7071 _(6, "outer_vlan_id_any")                       \
7072 _(7, "inner_vlan_id_any")
7073
7074 static int
7075 api_create_subif (vat_main_t * vam)
7076 {
7077   unformat_input_t *i = vam->input;
7078   vl_api_create_subif_t *mp;
7079   u32 sw_if_index;
7080   u8 sw_if_index_set = 0;
7081   u32 sub_id;
7082   u8 sub_id_set = 0;
7083   u32 __attribute__ ((unused)) no_tags = 0;
7084   u32 __attribute__ ((unused)) one_tag = 0;
7085   u32 __attribute__ ((unused)) two_tags = 0;
7086   u32 __attribute__ ((unused)) dot1ad = 0;
7087   u32 __attribute__ ((unused)) exact_match = 0;
7088   u32 __attribute__ ((unused)) default_sub = 0;
7089   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
7090   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
7091   u32 tmp;
7092   u16 outer_vlan_id = 0;
7093   u16 inner_vlan_id = 0;
7094   int ret;
7095
7096   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7097     {
7098       if (unformat (i, "sw_if_index %d", &sw_if_index))
7099         sw_if_index_set = 1;
7100       else
7101         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7102         sw_if_index_set = 1;
7103       else if (unformat (i, "sub_id %d", &sub_id))
7104         sub_id_set = 1;
7105       else if (unformat (i, "outer_vlan_id %d", &tmp))
7106         outer_vlan_id = tmp;
7107       else if (unformat (i, "inner_vlan_id %d", &tmp))
7108         inner_vlan_id = tmp;
7109
7110 #define _(a) else if (unformat (i, #a)) a = 1 ;
7111       foreach_create_subif_bit
7112 #undef _
7113         else
7114         {
7115           clib_warning ("parse error '%U'", format_unformat_error, i);
7116           return -99;
7117         }
7118     }
7119
7120   if (sw_if_index_set == 0)
7121     {
7122       errmsg ("missing interface name or sw_if_index");
7123       return -99;
7124     }
7125
7126   if (sub_id_set == 0)
7127     {
7128       errmsg ("missing sub_id");
7129       return -99;
7130     }
7131   M (CREATE_SUBIF, mp);
7132
7133   mp->sw_if_index = ntohl (sw_if_index);
7134   mp->sub_id = ntohl (sub_id);
7135
7136 #define _(a,b) mp->sub_if_flags |= (1 << a);
7137   foreach_create_subif_flag;
7138 #undef _
7139
7140   mp->outer_vlan_id = ntohs (outer_vlan_id);
7141   mp->inner_vlan_id = ntohs (inner_vlan_id);
7142
7143   S (mp);
7144   W (ret);
7145   return ret;
7146 }
7147
7148 static int
7149 api_ip_table_replace_begin (vat_main_t * vam)
7150 {
7151   unformat_input_t *i = vam->input;
7152   vl_api_ip_table_replace_begin_t *mp;
7153   u32 table_id = 0;
7154   u8 is_ipv6 = 0;
7155
7156   int ret;
7157   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7158     {
7159       if (unformat (i, "table %d", &table_id))
7160         ;
7161       else if (unformat (i, "ipv6"))
7162         is_ipv6 = 1;
7163       else
7164         {
7165           clib_warning ("parse error '%U'", format_unformat_error, i);
7166           return -99;
7167         }
7168     }
7169
7170   M (IP_TABLE_REPLACE_BEGIN, mp);
7171
7172   mp->table.table_id = ntohl (table_id);
7173   mp->table.is_ip6 = is_ipv6;
7174
7175   S (mp);
7176   W (ret);
7177   return ret;
7178 }
7179
7180 static int
7181 api_ip_table_flush (vat_main_t * vam)
7182 {
7183   unformat_input_t *i = vam->input;
7184   vl_api_ip_table_flush_t *mp;
7185   u32 table_id = 0;
7186   u8 is_ipv6 = 0;
7187
7188   int ret;
7189   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7190     {
7191       if (unformat (i, "table %d", &table_id))
7192         ;
7193       else if (unformat (i, "ipv6"))
7194         is_ipv6 = 1;
7195       else
7196         {
7197           clib_warning ("parse error '%U'", format_unformat_error, i);
7198           return -99;
7199         }
7200     }
7201
7202   M (IP_TABLE_FLUSH, mp);
7203
7204   mp->table.table_id = ntohl (table_id);
7205   mp->table.is_ip6 = is_ipv6;
7206
7207   S (mp);
7208   W (ret);
7209   return ret;
7210 }
7211
7212 static int
7213 api_ip_table_replace_end (vat_main_t * vam)
7214 {
7215   unformat_input_t *i = vam->input;
7216   vl_api_ip_table_replace_end_t *mp;
7217   u32 table_id = 0;
7218   u8 is_ipv6 = 0;
7219
7220   int ret;
7221   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7222     {
7223       if (unformat (i, "table %d", &table_id))
7224         ;
7225       else if (unformat (i, "ipv6"))
7226         is_ipv6 = 1;
7227       else
7228         {
7229           clib_warning ("parse error '%U'", format_unformat_error, i);
7230           return -99;
7231         }
7232     }
7233
7234   M (IP_TABLE_REPLACE_END, mp);
7235
7236   mp->table.table_id = ntohl (table_id);
7237   mp->table.is_ip6 = is_ipv6;
7238
7239   S (mp);
7240   W (ret);
7241   return ret;
7242 }
7243
7244 static int
7245 api_set_ip_flow_hash (vat_main_t * vam)
7246 {
7247   unformat_input_t *i = vam->input;
7248   vl_api_set_ip_flow_hash_t *mp;
7249   u32 vrf_id = 0;
7250   u8 is_ipv6 = 0;
7251   u8 vrf_id_set = 0;
7252   u8 src = 0;
7253   u8 dst = 0;
7254   u8 sport = 0;
7255   u8 dport = 0;
7256   u8 proto = 0;
7257   u8 reverse = 0;
7258   int ret;
7259
7260   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7261     {
7262       if (unformat (i, "vrf %d", &vrf_id))
7263         vrf_id_set = 1;
7264       else if (unformat (i, "ipv6"))
7265         is_ipv6 = 1;
7266       else if (unformat (i, "src"))
7267         src = 1;
7268       else if (unformat (i, "dst"))
7269         dst = 1;
7270       else if (unformat (i, "sport"))
7271         sport = 1;
7272       else if (unformat (i, "dport"))
7273         dport = 1;
7274       else if (unformat (i, "proto"))
7275         proto = 1;
7276       else if (unformat (i, "reverse"))
7277         reverse = 1;
7278
7279       else
7280         {
7281           clib_warning ("parse error '%U'", format_unformat_error, i);
7282           return -99;
7283         }
7284     }
7285
7286   if (vrf_id_set == 0)
7287     {
7288       errmsg ("missing vrf id");
7289       return -99;
7290     }
7291
7292   M (SET_IP_FLOW_HASH, mp);
7293   mp->src = src;
7294   mp->dst = dst;
7295   mp->sport = sport;
7296   mp->dport = dport;
7297   mp->proto = proto;
7298   mp->reverse = reverse;
7299   mp->vrf_id = ntohl (vrf_id);
7300   mp->is_ipv6 = is_ipv6;
7301
7302   S (mp);
7303   W (ret);
7304   return ret;
7305 }
7306
7307 static int
7308 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
7309 {
7310   unformat_input_t *i = vam->input;
7311   vl_api_sw_interface_ip6_enable_disable_t *mp;
7312   u32 sw_if_index;
7313   u8 sw_if_index_set = 0;
7314   u8 enable = 0;
7315   int ret;
7316
7317   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7318     {
7319       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7320         sw_if_index_set = 1;
7321       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7322         sw_if_index_set = 1;
7323       else if (unformat (i, "enable"))
7324         enable = 1;
7325       else if (unformat (i, "disable"))
7326         enable = 0;
7327       else
7328         {
7329           clib_warning ("parse error '%U'", format_unformat_error, i);
7330           return -99;
7331         }
7332     }
7333
7334   if (sw_if_index_set == 0)
7335     {
7336       errmsg ("missing interface name or sw_if_index");
7337       return -99;
7338     }
7339
7340   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
7341
7342   mp->sw_if_index = ntohl (sw_if_index);
7343   mp->enable = enable;
7344
7345   S (mp);
7346   W (ret);
7347   return ret;
7348 }
7349
7350
7351 static int
7352 api_l2_patch_add_del (vat_main_t * vam)
7353 {
7354   unformat_input_t *i = vam->input;
7355   vl_api_l2_patch_add_del_t *mp;
7356   u32 rx_sw_if_index;
7357   u8 rx_sw_if_index_set = 0;
7358   u32 tx_sw_if_index;
7359   u8 tx_sw_if_index_set = 0;
7360   u8 is_add = 1;
7361   int ret;
7362
7363   /* Parse args required to build the message */
7364   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7365     {
7366       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
7367         rx_sw_if_index_set = 1;
7368       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
7369         tx_sw_if_index_set = 1;
7370       else if (unformat (i, "rx"))
7371         {
7372           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7373             {
7374               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7375                             &rx_sw_if_index))
7376                 rx_sw_if_index_set = 1;
7377             }
7378           else
7379             break;
7380         }
7381       else if (unformat (i, "tx"))
7382         {
7383           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7384             {
7385               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7386                             &tx_sw_if_index))
7387                 tx_sw_if_index_set = 1;
7388             }
7389           else
7390             break;
7391         }
7392       else if (unformat (i, "del"))
7393         is_add = 0;
7394       else
7395         break;
7396     }
7397
7398   if (rx_sw_if_index_set == 0)
7399     {
7400       errmsg ("missing rx interface name or rx_sw_if_index");
7401       return -99;
7402     }
7403
7404   if (tx_sw_if_index_set == 0)
7405     {
7406       errmsg ("missing tx interface name or tx_sw_if_index");
7407       return -99;
7408     }
7409
7410   M (L2_PATCH_ADD_DEL, mp);
7411
7412   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
7413   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
7414   mp->is_add = is_add;
7415
7416   S (mp);
7417   W (ret);
7418   return ret;
7419 }
7420
7421 u8 is_del;
7422 u8 localsid_addr[16];
7423 u8 end_psp;
7424 u8 behavior;
7425 u32 sw_if_index;
7426 u32 vlan_index;
7427 u32 fib_table;
7428 u8 nh_addr[16];
7429
7430 static int
7431 api_sr_localsid_add_del (vat_main_t * vam)
7432 {
7433   unformat_input_t *i = vam->input;
7434   vl_api_sr_localsid_add_del_t *mp;
7435
7436   u8 is_del;
7437   ip6_address_t localsid;
7438   u8 end_psp = 0;
7439   u8 behavior = ~0;
7440   u32 sw_if_index;
7441   u32 fib_table = ~(u32) 0;
7442   ip46_address_t nh_addr;
7443   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
7444
7445   bool nexthop_set = 0;
7446
7447   int ret;
7448
7449   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7450     {
7451       if (unformat (i, "del"))
7452         is_del = 1;
7453       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
7454       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
7455         nexthop_set = 1;
7456       else if (unformat (i, "behavior %u", &behavior));
7457       else if (unformat (i, "sw_if_index %u", &sw_if_index));
7458       else if (unformat (i, "fib-table %u", &fib_table));
7459       else if (unformat (i, "end.psp %u", &behavior));
7460       else
7461         break;
7462     }
7463
7464   M (SR_LOCALSID_ADD_DEL, mp);
7465
7466   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
7467
7468   if (nexthop_set)
7469     {
7470       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
7471     }
7472   mp->behavior = behavior;
7473   mp->sw_if_index = ntohl (sw_if_index);
7474   mp->fib_table = ntohl (fib_table);
7475   mp->end_psp = end_psp;
7476   mp->is_del = is_del;
7477
7478   S (mp);
7479   W (ret);
7480   return ret;
7481 }
7482
7483 static int
7484 api_ioam_enable (vat_main_t * vam)
7485 {
7486   unformat_input_t *input = vam->input;
7487   vl_api_ioam_enable_t *mp;
7488   u32 id = 0;
7489   int has_trace_option = 0;
7490   int has_pot_option = 0;
7491   int has_seqno_option = 0;
7492   int has_analyse_option = 0;
7493   int ret;
7494
7495   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7496     {
7497       if (unformat (input, "trace"))
7498         has_trace_option = 1;
7499       else if (unformat (input, "pot"))
7500         has_pot_option = 1;
7501       else if (unformat (input, "seqno"))
7502         has_seqno_option = 1;
7503       else if (unformat (input, "analyse"))
7504         has_analyse_option = 1;
7505       else
7506         break;
7507     }
7508   M (IOAM_ENABLE, mp);
7509   mp->id = htons (id);
7510   mp->seqno = has_seqno_option;
7511   mp->analyse = has_analyse_option;
7512   mp->pot_enable = has_pot_option;
7513   mp->trace_enable = has_trace_option;
7514
7515   S (mp);
7516   W (ret);
7517   return ret;
7518 }
7519
7520
7521 static int
7522 api_ioam_disable (vat_main_t * vam)
7523 {
7524   vl_api_ioam_disable_t *mp;
7525   int ret;
7526
7527   M (IOAM_DISABLE, mp);
7528   S (mp);
7529   W (ret);
7530   return ret;
7531 }
7532
7533 #define foreach_tcp_proto_field                 \
7534 _(src_port)                                     \
7535 _(dst_port)
7536
7537 #define foreach_udp_proto_field                 \
7538 _(src_port)                                     \
7539 _(dst_port)
7540
7541 #define foreach_ip4_proto_field                 \
7542 _(src_address)                                  \
7543 _(dst_address)                                  \
7544 _(tos)                                          \
7545 _(length)                                       \
7546 _(fragment_id)                                  \
7547 _(ttl)                                          \
7548 _(protocol)                                     \
7549 _(checksum)
7550
7551 typedef struct
7552 {
7553   u16 src_port, dst_port;
7554 } tcpudp_header_t;
7555
7556 #if VPP_API_TEST_BUILTIN == 0
7557 uword
7558 unformat_tcp_mask (unformat_input_t * input, va_list * args)
7559 {
7560   u8 **maskp = va_arg (*args, u8 **);
7561   u8 *mask = 0;
7562   u8 found_something = 0;
7563   tcp_header_t *tcp;
7564
7565 #define _(a) u8 a=0;
7566   foreach_tcp_proto_field;
7567 #undef _
7568
7569   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7570     {
7571       if (0);
7572 #define _(a) else if (unformat (input, #a)) a=1;
7573       foreach_tcp_proto_field
7574 #undef _
7575         else
7576         break;
7577     }
7578
7579 #define _(a) found_something += a;
7580   foreach_tcp_proto_field;
7581 #undef _
7582
7583   if (found_something == 0)
7584     return 0;
7585
7586   vec_validate (mask, sizeof (*tcp) - 1);
7587
7588   tcp = (tcp_header_t *) mask;
7589
7590 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
7591   foreach_tcp_proto_field;
7592 #undef _
7593
7594   *maskp = mask;
7595   return 1;
7596 }
7597
7598 uword
7599 unformat_udp_mask (unformat_input_t * input, va_list * args)
7600 {
7601   u8 **maskp = va_arg (*args, u8 **);
7602   u8 *mask = 0;
7603   u8 found_something = 0;
7604   udp_header_t *udp;
7605
7606 #define _(a) u8 a=0;
7607   foreach_udp_proto_field;
7608 #undef _
7609
7610   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7611     {
7612       if (0);
7613 #define _(a) else if (unformat (input, #a)) a=1;
7614       foreach_udp_proto_field
7615 #undef _
7616         else
7617         break;
7618     }
7619
7620 #define _(a) found_something += a;
7621   foreach_udp_proto_field;
7622 #undef _
7623
7624   if (found_something == 0)
7625     return 0;
7626
7627   vec_validate (mask, sizeof (*udp) - 1);
7628
7629   udp = (udp_header_t *) mask;
7630
7631 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
7632   foreach_udp_proto_field;
7633 #undef _
7634
7635   *maskp = mask;
7636   return 1;
7637 }
7638
7639 uword
7640 unformat_l4_mask (unformat_input_t * input, va_list * args)
7641 {
7642   u8 **maskp = va_arg (*args, u8 **);
7643   u16 src_port = 0, dst_port = 0;
7644   tcpudp_header_t *tcpudp;
7645
7646   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7647     {
7648       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
7649         return 1;
7650       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
7651         return 1;
7652       else if (unformat (input, "src_port"))
7653         src_port = 0xFFFF;
7654       else if (unformat (input, "dst_port"))
7655         dst_port = 0xFFFF;
7656       else
7657         return 0;
7658     }
7659
7660   if (!src_port && !dst_port)
7661     return 0;
7662
7663   u8 *mask = 0;
7664   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
7665
7666   tcpudp = (tcpudp_header_t *) mask;
7667   tcpudp->src_port = src_port;
7668   tcpudp->dst_port = dst_port;
7669
7670   *maskp = mask;
7671
7672   return 1;
7673 }
7674
7675 uword
7676 unformat_ip4_mask (unformat_input_t * input, va_list * args)
7677 {
7678   u8 **maskp = va_arg (*args, u8 **);
7679   u8 *mask = 0;
7680   u8 found_something = 0;
7681   ip4_header_t *ip;
7682
7683 #define _(a) u8 a=0;
7684   foreach_ip4_proto_field;
7685 #undef _
7686   u8 version = 0;
7687   u8 hdr_length = 0;
7688
7689
7690   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7691     {
7692       if (unformat (input, "version"))
7693         version = 1;
7694       else if (unformat (input, "hdr_length"))
7695         hdr_length = 1;
7696       else if (unformat (input, "src"))
7697         src_address = 1;
7698       else if (unformat (input, "dst"))
7699         dst_address = 1;
7700       else if (unformat (input, "proto"))
7701         protocol = 1;
7702
7703 #define _(a) else if (unformat (input, #a)) a=1;
7704       foreach_ip4_proto_field
7705 #undef _
7706         else
7707         break;
7708     }
7709
7710 #define _(a) found_something += a;
7711   foreach_ip4_proto_field;
7712 #undef _
7713
7714   if (found_something == 0)
7715     return 0;
7716
7717   vec_validate (mask, sizeof (*ip) - 1);
7718
7719   ip = (ip4_header_t *) mask;
7720
7721 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7722   foreach_ip4_proto_field;
7723 #undef _
7724
7725   ip->ip_version_and_header_length = 0;
7726
7727   if (version)
7728     ip->ip_version_and_header_length |= 0xF0;
7729
7730   if (hdr_length)
7731     ip->ip_version_and_header_length |= 0x0F;
7732
7733   *maskp = mask;
7734   return 1;
7735 }
7736
7737 #define foreach_ip6_proto_field                 \
7738 _(src_address)                                  \
7739 _(dst_address)                                  \
7740 _(payload_length)                               \
7741 _(hop_limit)                                    \
7742 _(protocol)
7743
7744 uword
7745 unformat_ip6_mask (unformat_input_t * input, va_list * args)
7746 {
7747   u8 **maskp = va_arg (*args, u8 **);
7748   u8 *mask = 0;
7749   u8 found_something = 0;
7750   ip6_header_t *ip;
7751   u32 ip_version_traffic_class_and_flow_label;
7752
7753 #define _(a) u8 a=0;
7754   foreach_ip6_proto_field;
7755 #undef _
7756   u8 version = 0;
7757   u8 traffic_class = 0;
7758   u8 flow_label = 0;
7759
7760   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7761     {
7762       if (unformat (input, "version"))
7763         version = 1;
7764       else if (unformat (input, "traffic-class"))
7765         traffic_class = 1;
7766       else if (unformat (input, "flow-label"))
7767         flow_label = 1;
7768       else if (unformat (input, "src"))
7769         src_address = 1;
7770       else if (unformat (input, "dst"))
7771         dst_address = 1;
7772       else if (unformat (input, "proto"))
7773         protocol = 1;
7774
7775 #define _(a) else if (unformat (input, #a)) a=1;
7776       foreach_ip6_proto_field
7777 #undef _
7778         else
7779         break;
7780     }
7781
7782 #define _(a) found_something += a;
7783   foreach_ip6_proto_field;
7784 #undef _
7785
7786   if (found_something == 0)
7787     return 0;
7788
7789   vec_validate (mask, sizeof (*ip) - 1);
7790
7791   ip = (ip6_header_t *) mask;
7792
7793 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7794   foreach_ip6_proto_field;
7795 #undef _
7796
7797   ip_version_traffic_class_and_flow_label = 0;
7798
7799   if (version)
7800     ip_version_traffic_class_and_flow_label |= 0xF0000000;
7801
7802   if (traffic_class)
7803     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
7804
7805   if (flow_label)
7806     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
7807
7808   ip->ip_version_traffic_class_and_flow_label =
7809     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7810
7811   *maskp = mask;
7812   return 1;
7813 }
7814
7815 uword
7816 unformat_l3_mask (unformat_input_t * input, va_list * args)
7817 {
7818   u8 **maskp = va_arg (*args, u8 **);
7819
7820   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7821     {
7822       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
7823         return 1;
7824       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
7825         return 1;
7826       else
7827         break;
7828     }
7829   return 0;
7830 }
7831
7832 uword
7833 unformat_l2_mask (unformat_input_t * input, va_list * args)
7834 {
7835   u8 **maskp = va_arg (*args, u8 **);
7836   u8 *mask = 0;
7837   u8 src = 0;
7838   u8 dst = 0;
7839   u8 proto = 0;
7840   u8 tag1 = 0;
7841   u8 tag2 = 0;
7842   u8 ignore_tag1 = 0;
7843   u8 ignore_tag2 = 0;
7844   u8 cos1 = 0;
7845   u8 cos2 = 0;
7846   u8 dot1q = 0;
7847   u8 dot1ad = 0;
7848   int len = 14;
7849
7850   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7851     {
7852       if (unformat (input, "src"))
7853         src = 1;
7854       else if (unformat (input, "dst"))
7855         dst = 1;
7856       else if (unformat (input, "proto"))
7857         proto = 1;
7858       else if (unformat (input, "tag1"))
7859         tag1 = 1;
7860       else if (unformat (input, "tag2"))
7861         tag2 = 1;
7862       else if (unformat (input, "ignore-tag1"))
7863         ignore_tag1 = 1;
7864       else if (unformat (input, "ignore-tag2"))
7865         ignore_tag2 = 1;
7866       else if (unformat (input, "cos1"))
7867         cos1 = 1;
7868       else if (unformat (input, "cos2"))
7869         cos2 = 1;
7870       else if (unformat (input, "dot1q"))
7871         dot1q = 1;
7872       else if (unformat (input, "dot1ad"))
7873         dot1ad = 1;
7874       else
7875         break;
7876     }
7877   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7878        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7879     return 0;
7880
7881   if (tag1 || ignore_tag1 || cos1 || dot1q)
7882     len = 18;
7883   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7884     len = 22;
7885
7886   vec_validate (mask, len - 1);
7887
7888   if (dst)
7889     clib_memset (mask, 0xff, 6);
7890
7891   if (src)
7892     clib_memset (mask + 6, 0xff, 6);
7893
7894   if (tag2 || dot1ad)
7895     {
7896       /* inner vlan tag */
7897       if (tag2)
7898         {
7899           mask[19] = 0xff;
7900           mask[18] = 0x0f;
7901         }
7902       if (cos2)
7903         mask[18] |= 0xe0;
7904       if (proto)
7905         mask[21] = mask[20] = 0xff;
7906       if (tag1)
7907         {
7908           mask[15] = 0xff;
7909           mask[14] = 0x0f;
7910         }
7911       if (cos1)
7912         mask[14] |= 0xe0;
7913       *maskp = mask;
7914       return 1;
7915     }
7916   if (tag1 | dot1q)
7917     {
7918       if (tag1)
7919         {
7920           mask[15] = 0xff;
7921           mask[14] = 0x0f;
7922         }
7923       if (cos1)
7924         mask[14] |= 0xe0;
7925       if (proto)
7926         mask[16] = mask[17] = 0xff;
7927
7928       *maskp = mask;
7929       return 1;
7930     }
7931   if (cos2)
7932     mask[18] |= 0xe0;
7933   if (cos1)
7934     mask[14] |= 0xe0;
7935   if (proto)
7936     mask[12] = mask[13] = 0xff;
7937
7938   *maskp = mask;
7939   return 1;
7940 }
7941
7942 uword
7943 unformat_classify_mask (unformat_input_t * input, va_list * args)
7944 {
7945   u8 **maskp = va_arg (*args, u8 **);
7946   u32 *skipp = va_arg (*args, u32 *);
7947   u32 *matchp = va_arg (*args, u32 *);
7948   u32 match;
7949   u8 *mask = 0;
7950   u8 *l2 = 0;
7951   u8 *l3 = 0;
7952   u8 *l4 = 0;
7953   int i;
7954
7955   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7956     {
7957       if (unformat (input, "hex %U", unformat_hex_string, &mask))
7958         ;
7959       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7960         ;
7961       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7962         ;
7963       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
7964         ;
7965       else
7966         break;
7967     }
7968
7969   if (l4 && !l3)
7970     {
7971       vec_free (mask);
7972       vec_free (l2);
7973       vec_free (l4);
7974       return 0;
7975     }
7976
7977   if (mask || l2 || l3 || l4)
7978     {
7979       if (l2 || l3 || l4)
7980         {
7981           /* "With a free Ethernet header in every package" */
7982           if (l2 == 0)
7983             vec_validate (l2, 13);
7984           mask = l2;
7985           if (vec_len (l3))
7986             {
7987               vec_append (mask, l3);
7988               vec_free (l3);
7989             }
7990           if (vec_len (l4))
7991             {
7992               vec_append (mask, l4);
7993               vec_free (l4);
7994             }
7995         }
7996
7997       /* Scan forward looking for the first significant mask octet */
7998       for (i = 0; i < vec_len (mask); i++)
7999         if (mask[i])
8000           break;
8001
8002       /* compute (skip, match) params */
8003       *skipp = i / sizeof (u32x4);
8004       vec_delete (mask, *skipp * sizeof (u32x4), 0);
8005
8006       /* Pad mask to an even multiple of the vector size */
8007       while (vec_len (mask) % sizeof (u32x4))
8008         vec_add1 (mask, 0);
8009
8010       match = vec_len (mask) / sizeof (u32x4);
8011
8012       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
8013         {
8014           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
8015           if (*tmp || *(tmp + 1))
8016             break;
8017           match--;
8018         }
8019       if (match == 0)
8020         clib_warning ("BUG: match 0");
8021
8022       _vec_len (mask) = match * sizeof (u32x4);
8023
8024       *matchp = match;
8025       *maskp = mask;
8026
8027       return 1;
8028     }
8029
8030   return 0;
8031 }
8032 #endif /* VPP_API_TEST_BUILTIN */
8033
8034 #define foreach_l2_next                         \
8035 _(drop, DROP)                                   \
8036 _(ethernet, ETHERNET_INPUT)                     \
8037 _(ip4, IP4_INPUT)                               \
8038 _(ip6, IP6_INPUT)
8039
8040 uword
8041 unformat_l2_next_index (unformat_input_t * input, va_list * args)
8042 {
8043   u32 *miss_next_indexp = va_arg (*args, u32 *);
8044   u32 next_index = 0;
8045   u32 tmp;
8046
8047 #define _(n,N) \
8048   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
8049   foreach_l2_next;
8050 #undef _
8051
8052   if (unformat (input, "%d", &tmp))
8053     {
8054       next_index = tmp;
8055       goto out;
8056     }
8057
8058   return 0;
8059
8060 out:
8061   *miss_next_indexp = next_index;
8062   return 1;
8063 }
8064
8065 #define foreach_ip_next                         \
8066 _(drop, DROP)                                   \
8067 _(local, LOCAL)                                 \
8068 _(rewrite, REWRITE)
8069
8070 uword
8071 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
8072 {
8073   u32 *miss_next_indexp = va_arg (*args, u32 *);
8074   u32 next_index = 0;
8075   u32 tmp;
8076
8077 #define _(n,N) \
8078   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
8079   foreach_ip_next;
8080 #undef _
8081
8082   if (unformat (input, "%d", &tmp))
8083     {
8084       next_index = tmp;
8085       goto out;
8086     }
8087
8088   return 0;
8089
8090 out:
8091   *miss_next_indexp = next_index;
8092   return 1;
8093 }
8094
8095 #define foreach_acl_next                        \
8096 _(deny, DENY)
8097
8098 uword
8099 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
8100 {
8101   u32 *miss_next_indexp = va_arg (*args, u32 *);
8102   u32 next_index = 0;
8103   u32 tmp;
8104
8105 #define _(n,N) \
8106   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
8107   foreach_acl_next;
8108 #undef _
8109
8110   if (unformat (input, "permit"))
8111     {
8112       next_index = ~0;
8113       goto out;
8114     }
8115   else if (unformat (input, "%d", &tmp))
8116     {
8117       next_index = tmp;
8118       goto out;
8119     }
8120
8121   return 0;
8122
8123 out:
8124   *miss_next_indexp = next_index;
8125   return 1;
8126 }
8127
8128 uword
8129 unformat_policer_precolor (unformat_input_t * input, va_list * args)
8130 {
8131   u32 *r = va_arg (*args, u32 *);
8132
8133   if (unformat (input, "conform-color"))
8134     *r = POLICE_CONFORM;
8135   else if (unformat (input, "exceed-color"))
8136     *r = POLICE_EXCEED;
8137   else
8138     return 0;
8139
8140   return 1;
8141 }
8142
8143 static int
8144 api_classify_add_del_table (vat_main_t * vam)
8145 {
8146   unformat_input_t *i = vam->input;
8147   vl_api_classify_add_del_table_t *mp;
8148
8149   u32 nbuckets = 2;
8150   u32 skip = ~0;
8151   u32 match = ~0;
8152   int is_add = 1;
8153   int del_chain = 0;
8154   u32 table_index = ~0;
8155   u32 next_table_index = ~0;
8156   u32 miss_next_index = ~0;
8157   u32 memory_size = 32 << 20;
8158   u8 *mask = 0;
8159   u32 current_data_flag = 0;
8160   int current_data_offset = 0;
8161   int ret;
8162
8163   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8164     {
8165       if (unformat (i, "del"))
8166         is_add = 0;
8167       else if (unformat (i, "del-chain"))
8168         {
8169           is_add = 0;
8170           del_chain = 1;
8171         }
8172       else if (unformat (i, "buckets %d", &nbuckets))
8173         ;
8174       else if (unformat (i, "memory_size %d", &memory_size))
8175         ;
8176       else if (unformat (i, "skip %d", &skip))
8177         ;
8178       else if (unformat (i, "match %d", &match))
8179         ;
8180       else if (unformat (i, "table %d", &table_index))
8181         ;
8182       else if (unformat (i, "mask %U", unformat_classify_mask,
8183                          &mask, &skip, &match))
8184         ;
8185       else if (unformat (i, "next-table %d", &next_table_index))
8186         ;
8187       else if (unformat (i, "miss-next %U", api_unformat_ip_next_index,
8188                          &miss_next_index))
8189         ;
8190       else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
8191                          &miss_next_index))
8192         ;
8193       else if (unformat (i, "acl-miss-next %U", api_unformat_acl_next_index,
8194                          &miss_next_index))
8195         ;
8196       else if (unformat (i, "current-data-flag %d", &current_data_flag))
8197         ;
8198       else if (unformat (i, "current-data-offset %d", &current_data_offset))
8199         ;
8200       else
8201         break;
8202     }
8203
8204   if (is_add && mask == 0)
8205     {
8206       errmsg ("Mask required");
8207       return -99;
8208     }
8209
8210   if (is_add && skip == ~0)
8211     {
8212       errmsg ("skip count required");
8213       return -99;
8214     }
8215
8216   if (is_add && match == ~0)
8217     {
8218       errmsg ("match count required");
8219       return -99;
8220     }
8221
8222   if (!is_add && table_index == ~0)
8223     {
8224       errmsg ("table index required for delete");
8225       return -99;
8226     }
8227
8228   M2 (CLASSIFY_ADD_DEL_TABLE, mp, vec_len (mask));
8229
8230   mp->is_add = is_add;
8231   mp->del_chain = del_chain;
8232   mp->table_index = ntohl (table_index);
8233   mp->nbuckets = ntohl (nbuckets);
8234   mp->memory_size = ntohl (memory_size);
8235   mp->skip_n_vectors = ntohl (skip);
8236   mp->match_n_vectors = ntohl (match);
8237   mp->next_table_index = ntohl (next_table_index);
8238   mp->miss_next_index = ntohl (miss_next_index);
8239   mp->current_data_flag = ntohl (current_data_flag);
8240   mp->current_data_offset = ntohl (current_data_offset);
8241   mp->mask_len = ntohl (vec_len (mask));
8242   clib_memcpy (mp->mask, mask, vec_len (mask));
8243
8244   vec_free (mask);
8245
8246   S (mp);
8247   W (ret);
8248   return ret;
8249 }
8250
8251 #if VPP_API_TEST_BUILTIN == 0
8252 uword
8253 unformat_l4_match (unformat_input_t * input, va_list * args)
8254 {
8255   u8 **matchp = va_arg (*args, u8 **);
8256
8257   u8 *proto_header = 0;
8258   int src_port = 0;
8259   int dst_port = 0;
8260
8261   tcpudp_header_t h;
8262
8263   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8264     {
8265       if (unformat (input, "src_port %d", &src_port))
8266         ;
8267       else if (unformat (input, "dst_port %d", &dst_port))
8268         ;
8269       else
8270         return 0;
8271     }
8272
8273   h.src_port = clib_host_to_net_u16 (src_port);
8274   h.dst_port = clib_host_to_net_u16 (dst_port);
8275   vec_validate (proto_header, sizeof (h) - 1);
8276   memcpy (proto_header, &h, sizeof (h));
8277
8278   *matchp = proto_header;
8279
8280   return 1;
8281 }
8282
8283 uword
8284 unformat_ip4_match (unformat_input_t * input, va_list * args)
8285 {
8286   u8 **matchp = va_arg (*args, u8 **);
8287   u8 *match = 0;
8288   ip4_header_t *ip;
8289   int version = 0;
8290   u32 version_val;
8291   int hdr_length = 0;
8292   u32 hdr_length_val;
8293   int src = 0, dst = 0;
8294   ip4_address_t src_val, dst_val;
8295   int proto = 0;
8296   u32 proto_val;
8297   int tos = 0;
8298   u32 tos_val;
8299   int length = 0;
8300   u32 length_val;
8301   int fragment_id = 0;
8302   u32 fragment_id_val;
8303   int ttl = 0;
8304   int ttl_val;
8305   int checksum = 0;
8306   u32 checksum_val;
8307
8308   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8309     {
8310       if (unformat (input, "version %d", &version_val))
8311         version = 1;
8312       else if (unformat (input, "hdr_length %d", &hdr_length_val))
8313         hdr_length = 1;
8314       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
8315         src = 1;
8316       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
8317         dst = 1;
8318       else if (unformat (input, "proto %d", &proto_val))
8319         proto = 1;
8320       else if (unformat (input, "tos %d", &tos_val))
8321         tos = 1;
8322       else if (unformat (input, "length %d", &length_val))
8323         length = 1;
8324       else if (unformat (input, "fragment_id %d", &fragment_id_val))
8325         fragment_id = 1;
8326       else if (unformat (input, "ttl %d", &ttl_val))
8327         ttl = 1;
8328       else if (unformat (input, "checksum %d", &checksum_val))
8329         checksum = 1;
8330       else
8331         break;
8332     }
8333
8334   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
8335       + ttl + checksum == 0)
8336     return 0;
8337
8338   /*
8339    * Aligned because we use the real comparison functions
8340    */
8341   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8342
8343   ip = (ip4_header_t *) match;
8344
8345   /* These are realistically matched in practice */
8346   if (src)
8347     ip->src_address.as_u32 = src_val.as_u32;
8348
8349   if (dst)
8350     ip->dst_address.as_u32 = dst_val.as_u32;
8351
8352   if (proto)
8353     ip->protocol = proto_val;
8354
8355
8356   /* These are not, but they're included for completeness */
8357   if (version)
8358     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
8359
8360   if (hdr_length)
8361     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
8362
8363   if (tos)
8364     ip->tos = tos_val;
8365
8366   if (length)
8367     ip->length = clib_host_to_net_u16 (length_val);
8368
8369   if (ttl)
8370     ip->ttl = ttl_val;
8371
8372   if (checksum)
8373     ip->checksum = clib_host_to_net_u16 (checksum_val);
8374
8375   *matchp = match;
8376   return 1;
8377 }
8378
8379 uword
8380 unformat_ip6_match (unformat_input_t * input, va_list * args)
8381 {
8382   u8 **matchp = va_arg (*args, u8 **);
8383   u8 *match = 0;
8384   ip6_header_t *ip;
8385   int version = 0;
8386   u32 version_val;
8387   u8 traffic_class = 0;
8388   u32 traffic_class_val = 0;
8389   u8 flow_label = 0;
8390   u8 flow_label_val;
8391   int src = 0, dst = 0;
8392   ip6_address_t src_val, dst_val;
8393   int proto = 0;
8394   u32 proto_val;
8395   int payload_length = 0;
8396   u32 payload_length_val;
8397   int hop_limit = 0;
8398   int hop_limit_val;
8399   u32 ip_version_traffic_class_and_flow_label;
8400
8401   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8402     {
8403       if (unformat (input, "version %d", &version_val))
8404         version = 1;
8405       else if (unformat (input, "traffic_class %d", &traffic_class_val))
8406         traffic_class = 1;
8407       else if (unformat (input, "flow_label %d", &flow_label_val))
8408         flow_label = 1;
8409       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
8410         src = 1;
8411       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
8412         dst = 1;
8413       else if (unformat (input, "proto %d", &proto_val))
8414         proto = 1;
8415       else if (unformat (input, "payload_length %d", &payload_length_val))
8416         payload_length = 1;
8417       else if (unformat (input, "hop_limit %d", &hop_limit_val))
8418         hop_limit = 1;
8419       else
8420         break;
8421     }
8422
8423   if (version + traffic_class + flow_label + src + dst + proto +
8424       payload_length + hop_limit == 0)
8425     return 0;
8426
8427   /*
8428    * Aligned because we use the real comparison functions
8429    */
8430   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8431
8432   ip = (ip6_header_t *) match;
8433
8434   if (src)
8435     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
8436
8437   if (dst)
8438     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
8439
8440   if (proto)
8441     ip->protocol = proto_val;
8442
8443   ip_version_traffic_class_and_flow_label = 0;
8444
8445   if (version)
8446     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
8447
8448   if (traffic_class)
8449     ip_version_traffic_class_and_flow_label |=
8450       (traffic_class_val & 0xFF) << 20;
8451
8452   if (flow_label)
8453     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
8454
8455   ip->ip_version_traffic_class_and_flow_label =
8456     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
8457
8458   if (payload_length)
8459     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
8460
8461   if (hop_limit)
8462     ip->hop_limit = hop_limit_val;
8463
8464   *matchp = match;
8465   return 1;
8466 }
8467
8468 uword
8469 unformat_l3_match (unformat_input_t * input, va_list * args)
8470 {
8471   u8 **matchp = va_arg (*args, u8 **);
8472
8473   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8474     {
8475       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
8476         return 1;
8477       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
8478         return 1;
8479       else
8480         break;
8481     }
8482   return 0;
8483 }
8484
8485 uword
8486 unformat_vlan_tag (unformat_input_t * input, va_list * args)
8487 {
8488   u8 *tagp = va_arg (*args, u8 *);
8489   u32 tag;
8490
8491   if (unformat (input, "%d", &tag))
8492     {
8493       tagp[0] = (tag >> 8) & 0x0F;
8494       tagp[1] = tag & 0xFF;
8495       return 1;
8496     }
8497
8498   return 0;
8499 }
8500
8501 uword
8502 unformat_l2_match (unformat_input_t * input, va_list * args)
8503 {
8504   u8 **matchp = va_arg (*args, u8 **);
8505   u8 *match = 0;
8506   u8 src = 0;
8507   u8 src_val[6];
8508   u8 dst = 0;
8509   u8 dst_val[6];
8510   u8 proto = 0;
8511   u16 proto_val;
8512   u8 tag1 = 0;
8513   u8 tag1_val[2];
8514   u8 tag2 = 0;
8515   u8 tag2_val[2];
8516   int len = 14;
8517   u8 ignore_tag1 = 0;
8518   u8 ignore_tag2 = 0;
8519   u8 cos1 = 0;
8520   u8 cos2 = 0;
8521   u32 cos1_val = 0;
8522   u32 cos2_val = 0;
8523
8524   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8525     {
8526       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
8527         src = 1;
8528       else
8529         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
8530         dst = 1;
8531       else if (unformat (input, "proto %U",
8532                          unformat_ethernet_type_host_byte_order, &proto_val))
8533         proto = 1;
8534       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
8535         tag1 = 1;
8536       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
8537         tag2 = 1;
8538       else if (unformat (input, "ignore-tag1"))
8539         ignore_tag1 = 1;
8540       else if (unformat (input, "ignore-tag2"))
8541         ignore_tag2 = 1;
8542       else if (unformat (input, "cos1 %d", &cos1_val))
8543         cos1 = 1;
8544       else if (unformat (input, "cos2 %d", &cos2_val))
8545         cos2 = 1;
8546       else
8547         break;
8548     }
8549   if ((src + dst + proto + tag1 + tag2 +
8550        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
8551     return 0;
8552
8553   if (tag1 || ignore_tag1 || cos1)
8554     len = 18;
8555   if (tag2 || ignore_tag2 || cos2)
8556     len = 22;
8557
8558   vec_validate_aligned (match, len - 1, sizeof (u32x4));
8559
8560   if (dst)
8561     clib_memcpy (match, dst_val, 6);
8562
8563   if (src)
8564     clib_memcpy (match + 6, src_val, 6);
8565
8566   if (tag2)
8567     {
8568       /* inner vlan tag */
8569       match[19] = tag2_val[1];
8570       match[18] = tag2_val[0];
8571       if (cos2)
8572         match[18] |= (cos2_val & 0x7) << 5;
8573       if (proto)
8574         {
8575           match[21] = proto_val & 0xff;
8576           match[20] = proto_val >> 8;
8577         }
8578       if (tag1)
8579         {
8580           match[15] = tag1_val[1];
8581           match[14] = tag1_val[0];
8582         }
8583       if (cos1)
8584         match[14] |= (cos1_val & 0x7) << 5;
8585       *matchp = match;
8586       return 1;
8587     }
8588   if (tag1)
8589     {
8590       match[15] = tag1_val[1];
8591       match[14] = tag1_val[0];
8592       if (proto)
8593         {
8594           match[17] = proto_val & 0xff;
8595           match[16] = proto_val >> 8;
8596         }
8597       if (cos1)
8598         match[14] |= (cos1_val & 0x7) << 5;
8599
8600       *matchp = match;
8601       return 1;
8602     }
8603   if (cos2)
8604     match[18] |= (cos2_val & 0x7) << 5;
8605   if (cos1)
8606     match[14] |= (cos1_val & 0x7) << 5;
8607   if (proto)
8608     {
8609       match[13] = proto_val & 0xff;
8610       match[12] = proto_val >> 8;
8611     }
8612
8613   *matchp = match;
8614   return 1;
8615 }
8616
8617 uword
8618 unformat_qos_source (unformat_input_t * input, va_list * args)
8619 {
8620   int *qs = va_arg (*args, int *);
8621
8622   if (unformat (input, "ip"))
8623     *qs = QOS_SOURCE_IP;
8624   else if (unformat (input, "mpls"))
8625     *qs = QOS_SOURCE_MPLS;
8626   else if (unformat (input, "ext"))
8627     *qs = QOS_SOURCE_EXT;
8628   else if (unformat (input, "vlan"))
8629     *qs = QOS_SOURCE_VLAN;
8630   else
8631     return 0;
8632
8633   return 1;
8634 }
8635 #endif
8636
8637 uword
8638 api_unformat_classify_match (unformat_input_t * input, va_list * args)
8639 {
8640   u8 **matchp = va_arg (*args, u8 **);
8641   u32 skip_n_vectors = va_arg (*args, u32);
8642   u32 match_n_vectors = va_arg (*args, u32);
8643
8644   u8 *match = 0;
8645   u8 *l2 = 0;
8646   u8 *l3 = 0;
8647   u8 *l4 = 0;
8648
8649   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8650     {
8651       if (unformat (input, "hex %U", unformat_hex_string, &match))
8652         ;
8653       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
8654         ;
8655       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
8656         ;
8657       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
8658         ;
8659       else
8660         break;
8661     }
8662
8663   if (l4 && !l3)
8664     {
8665       vec_free (match);
8666       vec_free (l2);
8667       vec_free (l4);
8668       return 0;
8669     }
8670
8671   if (match || l2 || l3 || l4)
8672     {
8673       if (l2 || l3 || l4)
8674         {
8675           /* "Win a free Ethernet header in every packet" */
8676           if (l2 == 0)
8677             vec_validate_aligned (l2, 13, sizeof (u32x4));
8678           match = l2;
8679           if (vec_len (l3))
8680             {
8681               vec_append_aligned (match, l3, sizeof (u32x4));
8682               vec_free (l3);
8683             }
8684           if (vec_len (l4))
8685             {
8686               vec_append_aligned (match, l4, sizeof (u32x4));
8687               vec_free (l4);
8688             }
8689         }
8690
8691       /* Make sure the vector is big enough even if key is all 0's */
8692       vec_validate_aligned
8693         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
8694          sizeof (u32x4));
8695
8696       /* Set size, include skipped vectors */
8697       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
8698
8699       *matchp = match;
8700
8701       return 1;
8702     }
8703
8704   return 0;
8705 }
8706
8707 static int
8708 api_classify_add_del_session (vat_main_t * vam)
8709 {
8710   unformat_input_t *i = vam->input;
8711   vl_api_classify_add_del_session_t *mp;
8712   int is_add = 1;
8713   u32 table_index = ~0;
8714   u32 hit_next_index = ~0;
8715   u32 opaque_index = ~0;
8716   u8 *match = 0;
8717   i32 advance = 0;
8718   u32 skip_n_vectors = 0;
8719   u32 match_n_vectors = 0;
8720   u32 action = 0;
8721   u32 metadata = 0;
8722   int ret;
8723
8724   /*
8725    * Warning: you have to supply skip_n and match_n
8726    * because the API client cant simply look at the classify
8727    * table object.
8728    */
8729
8730   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8731     {
8732       if (unformat (i, "del"))
8733         is_add = 0;
8734       else if (unformat (i, "hit-next %U", api_unformat_ip_next_index,
8735                          &hit_next_index))
8736         ;
8737       else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
8738                          &hit_next_index))
8739         ;
8740       else if (unformat (i, "acl-hit-next %U", api_unformat_acl_next_index,
8741                          &hit_next_index))
8742         ;
8743       else if (unformat (i, "policer-hit-next %d", &hit_next_index))
8744         ;
8745       else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index))
8746         ;
8747       else if (unformat (i, "opaque-index %d", &opaque_index))
8748         ;
8749       else if (unformat (i, "skip_n %d", &skip_n_vectors))
8750         ;
8751       else if (unformat (i, "match_n %d", &match_n_vectors))
8752         ;
8753       else if (unformat (i, "match %U", api_unformat_classify_match,
8754                          &match, skip_n_vectors, match_n_vectors))
8755         ;
8756       else if (unformat (i, "advance %d", &advance))
8757         ;
8758       else if (unformat (i, "table-index %d", &table_index))
8759         ;
8760       else if (unformat (i, "action set-ip4-fib-id %d", &metadata))
8761         action = 1;
8762       else if (unformat (i, "action set-ip6-fib-id %d", &metadata))
8763         action = 2;
8764       else if (unformat (i, "action %d", &action))
8765         ;
8766       else if (unformat (i, "metadata %d", &metadata))
8767         ;
8768       else
8769         break;
8770     }
8771
8772   if (table_index == ~0)
8773     {
8774       errmsg ("Table index required");
8775       return -99;
8776     }
8777
8778   if (is_add && match == 0)
8779     {
8780       errmsg ("Match value required");
8781       return -99;
8782     }
8783
8784   M2 (CLASSIFY_ADD_DEL_SESSION, mp, vec_len (match));
8785
8786   mp->is_add = is_add;
8787   mp->table_index = ntohl (table_index);
8788   mp->hit_next_index = ntohl (hit_next_index);
8789   mp->opaque_index = ntohl (opaque_index);
8790   mp->advance = ntohl (advance);
8791   mp->action = action;
8792   mp->metadata = ntohl (metadata);
8793   mp->match_len = ntohl (vec_len (match));
8794   clib_memcpy (mp->match, match, vec_len (match));
8795   vec_free (match);
8796
8797   S (mp);
8798   W (ret);
8799   return ret;
8800 }
8801
8802 static int
8803 api_classify_set_interface_ip_table (vat_main_t * vam)
8804 {
8805   unformat_input_t *i = vam->input;
8806   vl_api_classify_set_interface_ip_table_t *mp;
8807   u32 sw_if_index;
8808   int sw_if_index_set;
8809   u32 table_index = ~0;
8810   u8 is_ipv6 = 0;
8811   int ret;
8812
8813   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8814     {
8815       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8816         sw_if_index_set = 1;
8817       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8818         sw_if_index_set = 1;
8819       else if (unformat (i, "table %d", &table_index))
8820         ;
8821       else
8822         {
8823           clib_warning ("parse error '%U'", format_unformat_error, i);
8824           return -99;
8825         }
8826     }
8827
8828   if (sw_if_index_set == 0)
8829     {
8830       errmsg ("missing interface name or sw_if_index");
8831       return -99;
8832     }
8833
8834
8835   M (CLASSIFY_SET_INTERFACE_IP_TABLE, mp);
8836
8837   mp->sw_if_index = ntohl (sw_if_index);
8838   mp->table_index = ntohl (table_index);
8839   mp->is_ipv6 = is_ipv6;
8840
8841   S (mp);
8842   W (ret);
8843   return ret;
8844 }
8845
8846 static int
8847 api_classify_set_interface_l2_tables (vat_main_t * vam)
8848 {
8849   unformat_input_t *i = vam->input;
8850   vl_api_classify_set_interface_l2_tables_t *mp;
8851   u32 sw_if_index;
8852   int sw_if_index_set;
8853   u32 ip4_table_index = ~0;
8854   u32 ip6_table_index = ~0;
8855   u32 other_table_index = ~0;
8856   u32 is_input = 1;
8857   int ret;
8858
8859   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8860     {
8861       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8862         sw_if_index_set = 1;
8863       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8864         sw_if_index_set = 1;
8865       else if (unformat (i, "ip4-table %d", &ip4_table_index))
8866         ;
8867       else if (unformat (i, "ip6-table %d", &ip6_table_index))
8868         ;
8869       else if (unformat (i, "other-table %d", &other_table_index))
8870         ;
8871       else if (unformat (i, "is-input %d", &is_input))
8872         ;
8873       else
8874         {
8875           clib_warning ("parse error '%U'", format_unformat_error, i);
8876           return -99;
8877         }
8878     }
8879
8880   if (sw_if_index_set == 0)
8881     {
8882       errmsg ("missing interface name or sw_if_index");
8883       return -99;
8884     }
8885
8886
8887   M (CLASSIFY_SET_INTERFACE_L2_TABLES, mp);
8888
8889   mp->sw_if_index = ntohl (sw_if_index);
8890   mp->ip4_table_index = ntohl (ip4_table_index);
8891   mp->ip6_table_index = ntohl (ip6_table_index);
8892   mp->other_table_index = ntohl (other_table_index);
8893   mp->is_input = (u8) is_input;
8894
8895   S (mp);
8896   W (ret);
8897   return ret;
8898 }
8899
8900 static int
8901 api_set_ipfix_exporter (vat_main_t * vam)
8902 {
8903   unformat_input_t *i = vam->input;
8904   vl_api_set_ipfix_exporter_t *mp;
8905   ip4_address_t collector_address;
8906   u8 collector_address_set = 0;
8907   u32 collector_port = ~0;
8908   ip4_address_t src_address;
8909   u8 src_address_set = 0;
8910   u32 vrf_id = ~0;
8911   u32 path_mtu = ~0;
8912   u32 template_interval = ~0;
8913   u8 udp_checksum = 0;
8914   int ret;
8915
8916   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8917     {
8918       if (unformat (i, "collector_address %U", unformat_ip4_address,
8919                     &collector_address))
8920         collector_address_set = 1;
8921       else if (unformat (i, "collector_port %d", &collector_port))
8922         ;
8923       else if (unformat (i, "src_address %U", unformat_ip4_address,
8924                          &src_address))
8925         src_address_set = 1;
8926       else if (unformat (i, "vrf_id %d", &vrf_id))
8927         ;
8928       else if (unformat (i, "path_mtu %d", &path_mtu))
8929         ;
8930       else if (unformat (i, "template_interval %d", &template_interval))
8931         ;
8932       else if (unformat (i, "udp_checksum"))
8933         udp_checksum = 1;
8934       else
8935         break;
8936     }
8937
8938   if (collector_address_set == 0)
8939     {
8940       errmsg ("collector_address required");
8941       return -99;
8942     }
8943
8944   if (src_address_set == 0)
8945     {
8946       errmsg ("src_address required");
8947       return -99;
8948     }
8949
8950   M (SET_IPFIX_EXPORTER, mp);
8951
8952   memcpy (mp->collector_address.un.ip4, collector_address.data,
8953           sizeof (collector_address.data));
8954   mp->collector_port = htons ((u16) collector_port);
8955   memcpy (mp->src_address.un.ip4, src_address.data,
8956           sizeof (src_address.data));
8957   mp->vrf_id = htonl (vrf_id);
8958   mp->path_mtu = htonl (path_mtu);
8959   mp->template_interval = htonl (template_interval);
8960   mp->udp_checksum = udp_checksum;
8961
8962   S (mp);
8963   W (ret);
8964   return ret;
8965 }
8966
8967 static int
8968 api_set_ipfix_classify_stream (vat_main_t * vam)
8969 {
8970   unformat_input_t *i = vam->input;
8971   vl_api_set_ipfix_classify_stream_t *mp;
8972   u32 domain_id = 0;
8973   u32 src_port = UDP_DST_PORT_ipfix;
8974   int ret;
8975
8976   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8977     {
8978       if (unformat (i, "domain %d", &domain_id))
8979         ;
8980       else if (unformat (i, "src_port %d", &src_port))
8981         ;
8982       else
8983         {
8984           errmsg ("unknown input `%U'", format_unformat_error, i);
8985           return -99;
8986         }
8987     }
8988
8989   M (SET_IPFIX_CLASSIFY_STREAM, mp);
8990
8991   mp->domain_id = htonl (domain_id);
8992   mp->src_port = htons ((u16) src_port);
8993
8994   S (mp);
8995   W (ret);
8996   return ret;
8997 }
8998
8999 static int
9000 api_ipfix_classify_table_add_del (vat_main_t * vam)
9001 {
9002   unformat_input_t *i = vam->input;
9003   vl_api_ipfix_classify_table_add_del_t *mp;
9004   int is_add = -1;
9005   u32 classify_table_index = ~0;
9006   u8 ip_version = 0;
9007   u8 transport_protocol = 255;
9008   int ret;
9009
9010   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9011     {
9012       if (unformat (i, "add"))
9013         is_add = 1;
9014       else if (unformat (i, "del"))
9015         is_add = 0;
9016       else if (unformat (i, "table %d", &classify_table_index))
9017         ;
9018       else if (unformat (i, "ip4"))
9019         ip_version = 4;
9020       else if (unformat (i, "ip6"))
9021         ip_version = 6;
9022       else if (unformat (i, "tcp"))
9023         transport_protocol = 6;
9024       else if (unformat (i, "udp"))
9025         transport_protocol = 17;
9026       else
9027         {
9028           errmsg ("unknown input `%U'", format_unformat_error, i);
9029           return -99;
9030         }
9031     }
9032
9033   if (is_add == -1)
9034     {
9035       errmsg ("expecting: add|del");
9036       return -99;
9037     }
9038   if (classify_table_index == ~0)
9039     {
9040       errmsg ("classifier table not specified");
9041       return -99;
9042     }
9043   if (ip_version == 0)
9044     {
9045       errmsg ("IP version not specified");
9046       return -99;
9047     }
9048
9049   M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp);
9050
9051   mp->is_add = is_add;
9052   mp->table_id = htonl (classify_table_index);
9053   mp->ip_version = ip_version;
9054   mp->transport_protocol = transport_protocol;
9055
9056   S (mp);
9057   W (ret);
9058   return ret;
9059 }
9060
9061 static int
9062 api_get_node_index (vat_main_t * vam)
9063 {
9064   unformat_input_t *i = vam->input;
9065   vl_api_get_node_index_t *mp;
9066   u8 *name = 0;
9067   int ret;
9068
9069   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9070     {
9071       if (unformat (i, "node %s", &name))
9072         ;
9073       else
9074         break;
9075     }
9076   if (name == 0)
9077     {
9078       errmsg ("node name required");
9079       return -99;
9080     }
9081   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9082     {
9083       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9084       return -99;
9085     }
9086
9087   M (GET_NODE_INDEX, mp);
9088   clib_memcpy (mp->node_name, name, vec_len (name));
9089   vec_free (name);
9090
9091   S (mp);
9092   W (ret);
9093   return ret;
9094 }
9095
9096 static int
9097 api_get_next_index (vat_main_t * vam)
9098 {
9099   unformat_input_t *i = vam->input;
9100   vl_api_get_next_index_t *mp;
9101   u8 *node_name = 0, *next_node_name = 0;
9102   int ret;
9103
9104   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9105     {
9106       if (unformat (i, "node-name %s", &node_name))
9107         ;
9108       else if (unformat (i, "next-node-name %s", &next_node_name))
9109         break;
9110     }
9111
9112   if (node_name == 0)
9113     {
9114       errmsg ("node name required");
9115       return -99;
9116     }
9117   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
9118     {
9119       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9120       return -99;
9121     }
9122
9123   if (next_node_name == 0)
9124     {
9125       errmsg ("next node name required");
9126       return -99;
9127     }
9128   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
9129     {
9130       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
9131       return -99;
9132     }
9133
9134   M (GET_NEXT_INDEX, mp);
9135   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
9136   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
9137   vec_free (node_name);
9138   vec_free (next_node_name);
9139
9140   S (mp);
9141   W (ret);
9142   return ret;
9143 }
9144
9145 static int
9146 api_add_node_next (vat_main_t * vam)
9147 {
9148   unformat_input_t *i = vam->input;
9149   vl_api_add_node_next_t *mp;
9150   u8 *name = 0;
9151   u8 *next = 0;
9152   int ret;
9153
9154   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9155     {
9156       if (unformat (i, "node %s", &name))
9157         ;
9158       else if (unformat (i, "next %s", &next))
9159         ;
9160       else
9161         break;
9162     }
9163   if (name == 0)
9164     {
9165       errmsg ("node name required");
9166       return -99;
9167     }
9168   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9169     {
9170       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9171       return -99;
9172     }
9173   if (next == 0)
9174     {
9175       errmsg ("next node required");
9176       return -99;
9177     }
9178   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
9179     {
9180       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
9181       return -99;
9182     }
9183
9184   M (ADD_NODE_NEXT, mp);
9185   clib_memcpy (mp->node_name, name, vec_len (name));
9186   clib_memcpy (mp->next_name, next, vec_len (next));
9187   vec_free (name);
9188   vec_free (next);
9189
9190   S (mp);
9191   W (ret);
9192   return ret;
9193 }
9194
9195 static void vl_api_sw_interface_tap_v2_details_t_handler
9196   (vl_api_sw_interface_tap_v2_details_t * mp)
9197 {
9198   vat_main_t *vam = &vat_main;
9199
9200   u8 *ip4 =
9201     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
9202             mp->host_ip4_prefix.len);
9203   u8 *ip6 =
9204     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
9205             mp->host_ip6_prefix.len);
9206
9207   print (vam->ofp,
9208          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
9209          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
9210          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9211          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
9212          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
9213
9214   vec_free (ip4);
9215   vec_free (ip6);
9216 }
9217
9218 static void vl_api_sw_interface_tap_v2_details_t_handler_json
9219   (vl_api_sw_interface_tap_v2_details_t * mp)
9220 {
9221   vat_main_t *vam = &vat_main;
9222   vat_json_node_t *node = NULL;
9223
9224   if (VAT_JSON_ARRAY != vam->json_tree.type)
9225     {
9226       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9227       vat_json_init_array (&vam->json_tree);
9228     }
9229   node = vat_json_array_add (&vam->json_tree);
9230
9231   vat_json_init_object (node);
9232   vat_json_object_add_uint (node, "id", ntohl (mp->id));
9233   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9234   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
9235   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
9236   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9237   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9238   vat_json_object_add_string_copy (node, "host_mac_addr",
9239                                    format (0, "%U", format_ethernet_address,
9240                                            &mp->host_mac_addr));
9241   vat_json_object_add_string_copy (node, "host_namespace",
9242                                    mp->host_namespace);
9243   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
9244   vat_json_object_add_string_copy (node, "host_ip4_addr",
9245                                    format (0, "%U/%d", format_ip4_address,
9246                                            mp->host_ip4_prefix.address,
9247                                            mp->host_ip4_prefix.len));
9248   vat_json_object_add_string_copy (node, "host_ip6_prefix",
9249                                    format (0, "%U/%d", format_ip6_address,
9250                                            mp->host_ip6_prefix.address,
9251                                            mp->host_ip6_prefix.len));
9252
9253 }
9254
9255 static int
9256 api_sw_interface_tap_v2_dump (vat_main_t * vam)
9257 {
9258   vl_api_sw_interface_tap_v2_dump_t *mp;
9259   vl_api_control_ping_t *mp_ping;
9260   int ret;
9261
9262   print (vam->ofp,
9263          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
9264          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
9265          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
9266          "host_ip6_addr");
9267
9268   /* Get list of tap interfaces */
9269   M (SW_INTERFACE_TAP_V2_DUMP, mp);
9270   S (mp);
9271
9272   /* Use a control ping for synchronization */
9273   MPING (CONTROL_PING, mp_ping);
9274   S (mp_ping);
9275
9276   W (ret);
9277   return ret;
9278 }
9279
9280 static void vl_api_sw_interface_virtio_pci_details_t_handler
9281   (vl_api_sw_interface_virtio_pci_details_t * mp)
9282 {
9283   vat_main_t *vam = &vat_main;
9284
9285   typedef union
9286   {
9287     struct
9288     {
9289       u16 domain;
9290       u8 bus;
9291       u8 slot:5;
9292       u8 function:3;
9293     };
9294     u32 as_u32;
9295   } pci_addr_t;
9296   pci_addr_t addr;
9297
9298   addr.domain = ntohs (mp->pci_addr.domain);
9299   addr.bus = mp->pci_addr.bus;
9300   addr.slot = mp->pci_addr.slot;
9301   addr.function = mp->pci_addr.function;
9302
9303   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
9304                          addr.slot, addr.function);
9305
9306   print (vam->ofp,
9307          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
9308          pci_addr, ntohl (mp->sw_if_index),
9309          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9310          format_ethernet_address, mp->mac_addr,
9311          clib_net_to_host_u64 (mp->features));
9312   vec_free (pci_addr);
9313 }
9314
9315 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
9316   (vl_api_sw_interface_virtio_pci_details_t * mp)
9317 {
9318   vat_main_t *vam = &vat_main;
9319   vat_json_node_t *node = NULL;
9320   vlib_pci_addr_t pci_addr;
9321
9322   if (VAT_JSON_ARRAY != vam->json_tree.type)
9323     {
9324       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9325       vat_json_init_array (&vam->json_tree);
9326     }
9327   node = vat_json_array_add (&vam->json_tree);
9328
9329   pci_addr.domain = ntohs (mp->pci_addr.domain);
9330   pci_addr.bus = mp->pci_addr.bus;
9331   pci_addr.slot = mp->pci_addr.slot;
9332   pci_addr.function = mp->pci_addr.function;
9333
9334   vat_json_init_object (node);
9335   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
9336   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9337   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9338   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9339   vat_json_object_add_uint (node, "features",
9340                             clib_net_to_host_u64 (mp->features));
9341   vat_json_object_add_string_copy (node, "mac_addr",
9342                                    format (0, "%U", format_ethernet_address,
9343                                            &mp->mac_addr));
9344 }
9345
9346 static int
9347 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
9348 {
9349   vl_api_sw_interface_virtio_pci_dump_t *mp;
9350   vl_api_control_ping_t *mp_ping;
9351   int ret;
9352
9353   print (vam->ofp,
9354          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
9355          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
9356          "mac_addr", "features");
9357
9358   /* Get list of tap interfaces */
9359   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
9360   S (mp);
9361
9362   /* Use a control ping for synchronization */
9363   MPING (CONTROL_PING, mp_ping);
9364   S (mp_ping);
9365
9366   W (ret);
9367   return ret;
9368 }
9369
9370 static int
9371 api_vxlan_offload_rx (vat_main_t * vam)
9372 {
9373   unformat_input_t *line_input = vam->input;
9374   vl_api_vxlan_offload_rx_t *mp;
9375   u32 hw_if_index = ~0, rx_if_index = ~0;
9376   u8 is_add = 1;
9377   int ret;
9378
9379   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9380     {
9381       if (unformat (line_input, "del"))
9382         is_add = 0;
9383       else if (unformat (line_input, "hw %U", api_unformat_hw_if_index, vam,
9384                          &hw_if_index))
9385         ;
9386       else if (unformat (line_input, "hw hw_if_index %u", &hw_if_index))
9387         ;
9388       else if (unformat (line_input, "rx %U", api_unformat_sw_if_index, vam,
9389                          &rx_if_index))
9390         ;
9391       else if (unformat (line_input, "rx sw_if_index %u", &rx_if_index))
9392         ;
9393       else
9394         {
9395           errmsg ("parse error '%U'", format_unformat_error, line_input);
9396           return -99;
9397         }
9398     }
9399
9400   if (hw_if_index == ~0)
9401     {
9402       errmsg ("no hw interface");
9403       return -99;
9404     }
9405
9406   if (rx_if_index == ~0)
9407     {
9408       errmsg ("no rx tunnel");
9409       return -99;
9410     }
9411
9412   M (VXLAN_OFFLOAD_RX, mp);
9413
9414   mp->hw_if_index = ntohl (hw_if_index);
9415   mp->sw_if_index = ntohl (rx_if_index);
9416   mp->enable = is_add;
9417
9418   S (mp);
9419   W (ret);
9420   return ret;
9421 }
9422
9423 static uword unformat_vxlan_decap_next
9424   (unformat_input_t * input, va_list * args)
9425 {
9426   u32 *result = va_arg (*args, u32 *);
9427   u32 tmp;
9428
9429   if (unformat (input, "l2"))
9430     *result = VXLAN_INPUT_NEXT_L2_INPUT;
9431   else if (unformat (input, "%d", &tmp))
9432     *result = tmp;
9433   else
9434     return 0;
9435   return 1;
9436 }
9437
9438 static int
9439 api_vxlan_add_del_tunnel (vat_main_t * vam)
9440 {
9441   unformat_input_t *line_input = vam->input;
9442   vl_api_vxlan_add_del_tunnel_t *mp;
9443   ip46_address_t src, dst;
9444   u8 is_add = 1;
9445   u8 ipv4_set = 0, ipv6_set = 0;
9446   u8 src_set = 0;
9447   u8 dst_set = 0;
9448   u8 grp_set = 0;
9449   u32 instance = ~0;
9450   u32 mcast_sw_if_index = ~0;
9451   u32 encap_vrf_id = 0;
9452   u32 decap_next_index = ~0;
9453   u32 vni = 0;
9454   int ret;
9455
9456   /* Can't "universally zero init" (={0}) due to GCC bug 53119 */
9457   clib_memset (&src, 0, sizeof src);
9458   clib_memset (&dst, 0, sizeof dst);
9459
9460   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9461     {
9462       if (unformat (line_input, "del"))
9463         is_add = 0;
9464       else if (unformat (line_input, "instance %d", &instance))
9465         ;
9466       else
9467         if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
9468         {
9469           ipv4_set = 1;
9470           src_set = 1;
9471         }
9472       else
9473         if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
9474         {
9475           ipv4_set = 1;
9476           dst_set = 1;
9477         }
9478       else
9479         if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
9480         {
9481           ipv6_set = 1;
9482           src_set = 1;
9483         }
9484       else
9485         if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
9486         {
9487           ipv6_set = 1;
9488           dst_set = 1;
9489         }
9490       else if (unformat (line_input, "group %U %U",
9491                          unformat_ip4_address, &dst.ip4,
9492                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9493         {
9494           grp_set = dst_set = 1;
9495           ipv4_set = 1;
9496         }
9497       else if (unformat (line_input, "group %U",
9498                          unformat_ip4_address, &dst.ip4))
9499         {
9500           grp_set = dst_set = 1;
9501           ipv4_set = 1;
9502         }
9503       else if (unformat (line_input, "group %U %U",
9504                          unformat_ip6_address, &dst.ip6,
9505                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9506         {
9507           grp_set = dst_set = 1;
9508           ipv6_set = 1;
9509         }
9510       else if (unformat (line_input, "group %U",
9511                          unformat_ip6_address, &dst.ip6))
9512         {
9513           grp_set = dst_set = 1;
9514           ipv6_set = 1;
9515         }
9516       else
9517         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
9518         ;
9519       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
9520         ;
9521       else if (unformat (line_input, "decap-next %U",
9522                          unformat_vxlan_decap_next, &decap_next_index))
9523         ;
9524       else if (unformat (line_input, "vni %d", &vni))
9525         ;
9526       else
9527         {
9528           errmsg ("parse error '%U'", format_unformat_error, line_input);
9529           return -99;
9530         }
9531     }
9532
9533   if (src_set == 0)
9534     {
9535       errmsg ("tunnel src address not specified");
9536       return -99;
9537     }
9538   if (dst_set == 0)
9539     {
9540       errmsg ("tunnel dst address not specified");
9541       return -99;
9542     }
9543
9544   if (grp_set && !ip46_address_is_multicast (&dst))
9545     {
9546       errmsg ("tunnel group address not multicast");
9547       return -99;
9548     }
9549   if (grp_set && mcast_sw_if_index == ~0)
9550     {
9551       errmsg ("tunnel nonexistent multicast device");
9552       return -99;
9553     }
9554   if (grp_set == 0 && ip46_address_is_multicast (&dst))
9555     {
9556       errmsg ("tunnel dst address must be unicast");
9557       return -99;
9558     }
9559
9560
9561   if (ipv4_set && ipv6_set)
9562     {
9563       errmsg ("both IPv4 and IPv6 addresses specified");
9564       return -99;
9565     }
9566
9567   if ((vni == 0) || (vni >> 24))
9568     {
9569       errmsg ("vni not specified or out of range");
9570       return -99;
9571     }
9572
9573   M (VXLAN_ADD_DEL_TUNNEL, mp);
9574
9575   if (ipv6_set)
9576     {
9577       clib_memcpy (mp->src_address.un.ip6, &src.ip6, sizeof (src.ip6));
9578       clib_memcpy (mp->dst_address.un.ip6, &dst.ip6, sizeof (dst.ip6));
9579     }
9580   else
9581     {
9582       clib_memcpy (mp->src_address.un.ip4, &src.ip4, sizeof (src.ip4));
9583       clib_memcpy (mp->dst_address.un.ip4, &dst.ip4, sizeof (dst.ip4));
9584     }
9585   mp->src_address.af = ipv6_set;
9586   mp->dst_address.af = ipv6_set;
9587
9588   mp->instance = htonl (instance);
9589   mp->encap_vrf_id = ntohl (encap_vrf_id);
9590   mp->decap_next_index = ntohl (decap_next_index);
9591   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
9592   mp->vni = ntohl (vni);
9593   mp->is_add = is_add;
9594
9595   S (mp);
9596   W (ret);
9597   return ret;
9598 }
9599
9600 static void vl_api_vxlan_tunnel_details_t_handler
9601   (vl_api_vxlan_tunnel_details_t * mp)
9602 {
9603   vat_main_t *vam = &vat_main;
9604   ip46_address_t src =
9605     to_ip46 (mp->dst_address.af, (u8 *) & mp->dst_address.un);
9606   ip46_address_t dst =
9607     to_ip46 (mp->dst_address.af, (u8 *) & mp->src_address.un);
9608
9609   print (vam->ofp, "%11d%11d%24U%24U%14d%18d%13d%19d",
9610          ntohl (mp->sw_if_index),
9611          ntohl (mp->instance),
9612          format_ip46_address, &src, IP46_TYPE_ANY,
9613          format_ip46_address, &dst, IP46_TYPE_ANY,
9614          ntohl (mp->encap_vrf_id),
9615          ntohl (mp->decap_next_index), ntohl (mp->vni),
9616          ntohl (mp->mcast_sw_if_index));
9617 }
9618
9619 static void vl_api_vxlan_tunnel_details_t_handler_json
9620   (vl_api_vxlan_tunnel_details_t * mp)
9621 {
9622   vat_main_t *vam = &vat_main;
9623   vat_json_node_t *node = NULL;
9624
9625   if (VAT_JSON_ARRAY != vam->json_tree.type)
9626     {
9627       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9628       vat_json_init_array (&vam->json_tree);
9629     }
9630   node = vat_json_array_add (&vam->json_tree);
9631
9632   vat_json_init_object (node);
9633   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9634
9635   vat_json_object_add_uint (node, "instance", ntohl (mp->instance));
9636
9637   if (mp->src_address.af)
9638     {
9639       struct in6_addr ip6;
9640
9641       clib_memcpy (&ip6, mp->src_address.un.ip6, sizeof (ip6));
9642       vat_json_object_add_ip6 (node, "src_address", ip6);
9643       clib_memcpy (&ip6, mp->dst_address.un.ip6, sizeof (ip6));
9644       vat_json_object_add_ip6 (node, "dst_address", ip6);
9645     }
9646   else
9647     {
9648       struct in_addr ip4;
9649
9650       clib_memcpy (&ip4, mp->src_address.un.ip4, sizeof (ip4));
9651       vat_json_object_add_ip4 (node, "src_address", ip4);
9652       clib_memcpy (&ip4, mp->dst_address.un.ip4, sizeof (ip4));
9653       vat_json_object_add_ip4 (node, "dst_address", ip4);
9654     }
9655   vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id));
9656   vat_json_object_add_uint (node, "decap_next_index",
9657                             ntohl (mp->decap_next_index));
9658   vat_json_object_add_uint (node, "vni", ntohl (mp->vni));
9659   vat_json_object_add_uint (node, "mcast_sw_if_index",
9660                             ntohl (mp->mcast_sw_if_index));
9661 }
9662
9663 static int
9664 api_vxlan_tunnel_dump (vat_main_t * vam)
9665 {
9666   unformat_input_t *i = vam->input;
9667   vl_api_vxlan_tunnel_dump_t *mp;
9668   vl_api_control_ping_t *mp_ping;
9669   u32 sw_if_index;
9670   u8 sw_if_index_set = 0;
9671   int ret;
9672
9673   /* Parse args required to build the message */
9674   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9675     {
9676       if (unformat (i, "sw_if_index %d", &sw_if_index))
9677         sw_if_index_set = 1;
9678       else
9679         break;
9680     }
9681
9682   if (sw_if_index_set == 0)
9683     {
9684       sw_if_index = ~0;
9685     }
9686
9687   if (!vam->json_output)
9688     {
9689       print (vam->ofp, "%11s%11s%24s%24s%14s%18s%13s%19s",
9690              "sw_if_index", "instance", "src_address", "dst_address",
9691              "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index");
9692     }
9693
9694   /* Get list of vxlan-tunnel interfaces */
9695   M (VXLAN_TUNNEL_DUMP, mp);
9696
9697   mp->sw_if_index = htonl (sw_if_index);
9698
9699   S (mp);
9700
9701   /* Use a control ping for synchronization */
9702   MPING (CONTROL_PING, mp_ping);
9703   S (mp_ping);
9704
9705   W (ret);
9706   return ret;
9707 }
9708
9709 static int
9710 api_gre_tunnel_add_del (vat_main_t * vam)
9711 {
9712   unformat_input_t *line_input = vam->input;
9713   vl_api_address_t src = { }, dst =
9714   {
9715   };
9716   vl_api_gre_tunnel_add_del_t *mp;
9717   vl_api_gre_tunnel_type_t t_type;
9718   u8 is_add = 1;
9719   u8 src_set = 0;
9720   u8 dst_set = 0;
9721   u32 outer_table_id = 0;
9722   u32 session_id = 0;
9723   u32 instance = ~0;
9724   int ret;
9725
9726   t_type = GRE_API_TUNNEL_TYPE_L3;
9727
9728   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9729     {
9730       if (unformat (line_input, "del"))
9731         is_add = 0;
9732       else if (unformat (line_input, "instance %d", &instance))
9733         ;
9734       else if (unformat (line_input, "src %U", unformat_vl_api_address, &src))
9735         {
9736           src_set = 1;
9737         }
9738       else if (unformat (line_input, "dst %U", unformat_vl_api_address, &dst))
9739         {
9740           dst_set = 1;
9741         }
9742       else if (unformat (line_input, "outer-table-id %d", &outer_table_id))
9743         ;
9744       else if (unformat (line_input, "teb"))
9745         t_type = GRE_API_TUNNEL_TYPE_TEB;
9746       else if (unformat (line_input, "erspan %d", &session_id))
9747         t_type = GRE_API_TUNNEL_TYPE_ERSPAN;
9748       else
9749         {
9750           errmsg ("parse error '%U'", format_unformat_error, line_input);
9751           return -99;
9752         }
9753     }
9754
9755   if (src_set == 0)
9756     {
9757       errmsg ("tunnel src address not specified");
9758       return -99;
9759     }
9760   if (dst_set == 0)
9761     {
9762       errmsg ("tunnel dst address not specified");
9763       return -99;
9764     }
9765
9766   M (GRE_TUNNEL_ADD_DEL, mp);
9767
9768   clib_memcpy (&mp->tunnel.src, &src, sizeof (mp->tunnel.src));
9769   clib_memcpy (&mp->tunnel.dst, &dst, sizeof (mp->tunnel.dst));
9770
9771   mp->tunnel.instance = htonl (instance);
9772   mp->tunnel.outer_table_id = htonl (outer_table_id);
9773   mp->is_add = is_add;
9774   mp->tunnel.session_id = htons ((u16) session_id);
9775   mp->tunnel.type = htonl (t_type);
9776
9777   S (mp);
9778   W (ret);
9779   return ret;
9780 }
9781
9782 static void vl_api_gre_tunnel_details_t_handler
9783   (vl_api_gre_tunnel_details_t * mp)
9784 {
9785   vat_main_t *vam = &vat_main;
9786
9787   print (vam->ofp, "%11d%11d%24U%24U%13d%14d%12d",
9788          ntohl (mp->tunnel.sw_if_index),
9789          ntohl (mp->tunnel.instance),
9790          format_vl_api_address, &mp->tunnel.src,
9791          format_vl_api_address, &mp->tunnel.dst,
9792          mp->tunnel.type, ntohl (mp->tunnel.outer_table_id),
9793          ntohl (mp->tunnel.session_id));
9794 }
9795
9796 static void vl_api_gre_tunnel_details_t_handler_json
9797   (vl_api_gre_tunnel_details_t * mp)
9798 {
9799   vat_main_t *vam = &vat_main;
9800   vat_json_node_t *node = NULL;
9801
9802   if (VAT_JSON_ARRAY != vam->json_tree.type)
9803     {
9804       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9805       vat_json_init_array (&vam->json_tree);
9806     }
9807   node = vat_json_array_add (&vam->json_tree);
9808
9809   vat_json_init_object (node);
9810   vat_json_object_add_uint (node, "sw_if_index",
9811                             ntohl (mp->tunnel.sw_if_index));
9812   vat_json_object_add_uint (node, "instance", ntohl (mp->tunnel.instance));
9813
9814   vat_json_object_add_address (node, "src", &mp->tunnel.src);
9815   vat_json_object_add_address (node, "dst", &mp->tunnel.dst);
9816   vat_json_object_add_uint (node, "tunnel_type", mp->tunnel.type);
9817   vat_json_object_add_uint (node, "outer_table_id",
9818                             ntohl (mp->tunnel.outer_table_id));
9819   vat_json_object_add_uint (node, "session_id", mp->tunnel.session_id);
9820 }
9821
9822 static int
9823 api_gre_tunnel_dump (vat_main_t * vam)
9824 {
9825   unformat_input_t *i = vam->input;
9826   vl_api_gre_tunnel_dump_t *mp;
9827   vl_api_control_ping_t *mp_ping;
9828   u32 sw_if_index;
9829   u8 sw_if_index_set = 0;
9830   int ret;
9831
9832   /* Parse args required to build the message */
9833   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9834     {
9835       if (unformat (i, "sw_if_index %d", &sw_if_index))
9836         sw_if_index_set = 1;
9837       else
9838         break;
9839     }
9840
9841   if (sw_if_index_set == 0)
9842     {
9843       sw_if_index = ~0;
9844     }
9845
9846   if (!vam->json_output)
9847     {
9848       print (vam->ofp, "%11s%11s%24s%24s%13s%14s%12s",
9849              "sw_if_index", "instance", "src_address", "dst_address",
9850              "tunnel_type", "outer_fib_id", "session_id");
9851     }
9852
9853   /* Get list of gre-tunnel interfaces */
9854   M (GRE_TUNNEL_DUMP, mp);
9855
9856   mp->sw_if_index = htonl (sw_if_index);
9857
9858   S (mp);
9859
9860   /* Use a control ping for synchronization */
9861   MPING (CONTROL_PING, mp_ping);
9862   S (mp_ping);
9863
9864   W (ret);
9865   return ret;
9866 }
9867
9868 static int
9869 api_l2_fib_clear_table (vat_main_t * vam)
9870 {
9871 //  unformat_input_t * i = vam->input;
9872   vl_api_l2_fib_clear_table_t *mp;
9873   int ret;
9874
9875   M (L2_FIB_CLEAR_TABLE, mp);
9876
9877   S (mp);
9878   W (ret);
9879   return ret;
9880 }
9881
9882 static int
9883 api_l2_interface_efp_filter (vat_main_t * vam)
9884 {
9885   unformat_input_t *i = vam->input;
9886   vl_api_l2_interface_efp_filter_t *mp;
9887   u32 sw_if_index;
9888   u8 enable = 1;
9889   u8 sw_if_index_set = 0;
9890   int ret;
9891
9892   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9893     {
9894       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9895         sw_if_index_set = 1;
9896       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9897         sw_if_index_set = 1;
9898       else if (unformat (i, "enable"))
9899         enable = 1;
9900       else if (unformat (i, "disable"))
9901         enable = 0;
9902       else
9903         {
9904           clib_warning ("parse error '%U'", format_unformat_error, i);
9905           return -99;
9906         }
9907     }
9908
9909   if (sw_if_index_set == 0)
9910     {
9911       errmsg ("missing sw_if_index");
9912       return -99;
9913     }
9914
9915   M (L2_INTERFACE_EFP_FILTER, mp);
9916
9917   mp->sw_if_index = ntohl (sw_if_index);
9918   mp->enable_disable = enable;
9919
9920   S (mp);
9921   W (ret);
9922   return ret;
9923 }
9924
9925 #define foreach_vtr_op                          \
9926 _("disable",  L2_VTR_DISABLED)                  \
9927 _("push-1",  L2_VTR_PUSH_1)                     \
9928 _("push-2",  L2_VTR_PUSH_2)                     \
9929 _("pop-1",  L2_VTR_POP_1)                       \
9930 _("pop-2",  L2_VTR_POP_2)                       \
9931 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
9932 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
9933 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
9934 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
9935
9936 static int
9937 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
9938 {
9939   unformat_input_t *i = vam->input;
9940   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
9941   u32 sw_if_index;
9942   u8 sw_if_index_set = 0;
9943   u8 vtr_op_set = 0;
9944   u32 vtr_op = 0;
9945   u32 push_dot1q = 1;
9946   u32 tag1 = ~0;
9947   u32 tag2 = ~0;
9948   int ret;
9949
9950   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9951     {
9952       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9953         sw_if_index_set = 1;
9954       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9955         sw_if_index_set = 1;
9956       else if (unformat (i, "vtr_op %d", &vtr_op))
9957         vtr_op_set = 1;
9958 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
9959       foreach_vtr_op
9960 #undef _
9961         else if (unformat (i, "push_dot1q %d", &push_dot1q))
9962         ;
9963       else if (unformat (i, "tag1 %d", &tag1))
9964         ;
9965       else if (unformat (i, "tag2 %d", &tag2))
9966         ;
9967       else
9968         {
9969           clib_warning ("parse error '%U'", format_unformat_error, i);
9970           return -99;
9971         }
9972     }
9973
9974   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
9975     {
9976       errmsg ("missing vtr operation or sw_if_index");
9977       return -99;
9978     }
9979
9980   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
9981   mp->sw_if_index = ntohl (sw_if_index);
9982   mp->vtr_op = ntohl (vtr_op);
9983   mp->push_dot1q = ntohl (push_dot1q);
9984   mp->tag1 = ntohl (tag1);
9985   mp->tag2 = ntohl (tag2);
9986
9987   S (mp);
9988   W (ret);
9989   return ret;
9990 }
9991
9992 static int
9993 api_create_vhost_user_if (vat_main_t * vam)
9994 {
9995   unformat_input_t *i = vam->input;
9996   vl_api_create_vhost_user_if_t *mp;
9997   u8 *file_name;
9998   u8 is_server = 0;
9999   u8 file_name_set = 0;
10000   u32 custom_dev_instance = ~0;
10001   u8 hwaddr[6];
10002   u8 use_custom_mac = 0;
10003   u8 disable_mrg_rxbuf = 0;
10004   u8 disable_indirect_desc = 0;
10005   u8 *tag = 0;
10006   u8 enable_gso = 0;
10007   u8 enable_packed = 0;
10008   int ret;
10009
10010   /* Shut up coverity */
10011   clib_memset (hwaddr, 0, sizeof (hwaddr));
10012
10013   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10014     {
10015       if (unformat (i, "socket %s", &file_name))
10016         {
10017           file_name_set = 1;
10018         }
10019       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
10020         ;
10021       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
10022         use_custom_mac = 1;
10023       else if (unformat (i, "server"))
10024         is_server = 1;
10025       else if (unformat (i, "disable_mrg_rxbuf"))
10026         disable_mrg_rxbuf = 1;
10027       else if (unformat (i, "disable_indirect_desc"))
10028         disable_indirect_desc = 1;
10029       else if (unformat (i, "gso"))
10030         enable_gso = 1;
10031       else if (unformat (i, "packed"))
10032         enable_packed = 1;
10033       else if (unformat (i, "tag %s", &tag))
10034         ;
10035       else
10036         break;
10037     }
10038
10039   if (file_name_set == 0)
10040     {
10041       errmsg ("missing socket file name");
10042       return -99;
10043     }
10044
10045   if (vec_len (file_name) > 255)
10046     {
10047       errmsg ("socket file name too long");
10048       return -99;
10049     }
10050   vec_add1 (file_name, 0);
10051
10052   M (CREATE_VHOST_USER_IF, mp);
10053
10054   mp->is_server = is_server;
10055   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
10056   mp->disable_indirect_desc = disable_indirect_desc;
10057   mp->enable_gso = enable_gso;
10058   mp->enable_packed = enable_packed;
10059   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10060   vec_free (file_name);
10061   if (custom_dev_instance != ~0)
10062     {
10063       mp->renumber = 1;
10064       mp->custom_dev_instance = ntohl (custom_dev_instance);
10065     }
10066
10067   mp->use_custom_mac = use_custom_mac;
10068   clib_memcpy (mp->mac_address, hwaddr, 6);
10069   if (tag)
10070     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
10071   vec_free (tag);
10072
10073   S (mp);
10074   W (ret);
10075   return ret;
10076 }
10077
10078 static int
10079 api_modify_vhost_user_if (vat_main_t * vam)
10080 {
10081   unformat_input_t *i = vam->input;
10082   vl_api_modify_vhost_user_if_t *mp;
10083   u8 *file_name;
10084   u8 is_server = 0;
10085   u8 file_name_set = 0;
10086   u32 custom_dev_instance = ~0;
10087   u8 sw_if_index_set = 0;
10088   u32 sw_if_index = (u32) ~ 0;
10089   u8 enable_gso = 0;
10090   u8 enable_packed = 0;
10091   int ret;
10092
10093   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10094     {
10095       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10096         sw_if_index_set = 1;
10097       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10098         sw_if_index_set = 1;
10099       else if (unformat (i, "socket %s", &file_name))
10100         {
10101           file_name_set = 1;
10102         }
10103       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
10104         ;
10105       else if (unformat (i, "server"))
10106         is_server = 1;
10107       else if (unformat (i, "gso"))
10108         enable_gso = 1;
10109       else if (unformat (i, "packed"))
10110         enable_packed = 1;
10111       else
10112         break;
10113     }
10114
10115   if (sw_if_index_set == 0)
10116     {
10117       errmsg ("missing sw_if_index or interface name");
10118       return -99;
10119     }
10120
10121   if (file_name_set == 0)
10122     {
10123       errmsg ("missing socket file name");
10124       return -99;
10125     }
10126
10127   if (vec_len (file_name) > 255)
10128     {
10129       errmsg ("socket file name too long");
10130       return -99;
10131     }
10132   vec_add1 (file_name, 0);
10133
10134   M (MODIFY_VHOST_USER_IF, mp);
10135
10136   mp->sw_if_index = ntohl (sw_if_index);
10137   mp->is_server = is_server;
10138   mp->enable_gso = enable_gso;
10139   mp->enable_packed = enable_packed;
10140   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10141   vec_free (file_name);
10142   if (custom_dev_instance != ~0)
10143     {
10144       mp->renumber = 1;
10145       mp->custom_dev_instance = ntohl (custom_dev_instance);
10146     }
10147
10148   S (mp);
10149   W (ret);
10150   return ret;
10151 }
10152
10153 static int
10154 api_delete_vhost_user_if (vat_main_t * vam)
10155 {
10156   unformat_input_t *i = vam->input;
10157   vl_api_delete_vhost_user_if_t *mp;
10158   u32 sw_if_index = ~0;
10159   u8 sw_if_index_set = 0;
10160   int ret;
10161
10162   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10163     {
10164       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10165         sw_if_index_set = 1;
10166       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10167         sw_if_index_set = 1;
10168       else
10169         break;
10170     }
10171
10172   if (sw_if_index_set == 0)
10173     {
10174       errmsg ("missing sw_if_index or interface name");
10175       return -99;
10176     }
10177
10178
10179   M (DELETE_VHOST_USER_IF, mp);
10180
10181   mp->sw_if_index = ntohl (sw_if_index);
10182
10183   S (mp);
10184   W (ret);
10185   return ret;
10186 }
10187
10188 static void vl_api_sw_interface_vhost_user_details_t_handler
10189   (vl_api_sw_interface_vhost_user_details_t * mp)
10190 {
10191   vat_main_t *vam = &vat_main;
10192   u64 features;
10193
10194   features =
10195     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
10196                                                     clib_net_to_host_u32
10197                                                     (mp->features_last_32) <<
10198                                                     32);
10199
10200   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s",
10201          (char *) mp->interface_name,
10202          ntohl (mp->sw_if_index), ntohl (mp->virtio_net_hdr_sz),
10203          features, mp->is_server,
10204          ntohl (mp->num_regions), (char *) mp->sock_filename);
10205   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
10206 }
10207
10208 static void vl_api_sw_interface_vhost_user_details_t_handler_json
10209   (vl_api_sw_interface_vhost_user_details_t * mp)
10210 {
10211   vat_main_t *vam = &vat_main;
10212   vat_json_node_t *node = NULL;
10213
10214   if (VAT_JSON_ARRAY != vam->json_tree.type)
10215     {
10216       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10217       vat_json_init_array (&vam->json_tree);
10218     }
10219   node = vat_json_array_add (&vam->json_tree);
10220
10221   vat_json_init_object (node);
10222   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10223   vat_json_object_add_string_copy (node, "interface_name",
10224                                    mp->interface_name);
10225   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
10226                             ntohl (mp->virtio_net_hdr_sz));
10227   vat_json_object_add_uint (node, "features_first_32",
10228                             clib_net_to_host_u32 (mp->features_first_32));
10229   vat_json_object_add_uint (node, "features_last_32",
10230                             clib_net_to_host_u32 (mp->features_last_32));
10231   vat_json_object_add_uint (node, "is_server", mp->is_server);
10232   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
10233   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
10234   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
10235 }
10236
10237 static int
10238 api_sw_interface_vhost_user_dump (vat_main_t * vam)
10239 {
10240   unformat_input_t *i = vam->input;
10241   vl_api_sw_interface_vhost_user_dump_t *mp;
10242   vl_api_control_ping_t *mp_ping;
10243   int ret;
10244   u32 sw_if_index = ~0;
10245
10246   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10247     {
10248       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10249         ;
10250       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10251         ;
10252       else
10253         break;
10254     }
10255
10256   print (vam->ofp,
10257          "Interface name            idx hdr_sz features server regions filename");
10258
10259   /* Get list of vhost-user interfaces */
10260   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
10261   mp->sw_if_index = ntohl (sw_if_index);
10262   S (mp);
10263
10264   /* Use a control ping for synchronization */
10265   MPING (CONTROL_PING, mp_ping);
10266   S (mp_ping);
10267
10268   W (ret);
10269   return ret;
10270 }
10271
10272 static int
10273 api_show_version (vat_main_t * vam)
10274 {
10275   vl_api_show_version_t *mp;
10276   int ret;
10277
10278   M (SHOW_VERSION, mp);
10279
10280   S (mp);
10281   W (ret);
10282   return ret;
10283 }
10284
10285
10286 static int
10287 api_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
10288 {
10289   unformat_input_t *line_input = vam->input;
10290   vl_api_vxlan_gpe_add_del_tunnel_t *mp;
10291   ip46_address_t local, remote;
10292   u8 is_add = 1;
10293   u8 local_set = 0;
10294   u8 remote_set = 0;
10295   u8 grp_set = 0;
10296   u32 mcast_sw_if_index = ~0;
10297   u32 encap_vrf_id = 0;
10298   u32 decap_vrf_id = 0;
10299   u8 protocol = ~0;
10300   u32 vni;
10301   u8 vni_set = 0;
10302   int ret;
10303
10304   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10305     {
10306       if (unformat (line_input, "del"))
10307         is_add = 0;
10308       else if (unformat (line_input, "local %U",
10309                          unformat_ip46_address, &local))
10310         {
10311           local_set = 1;
10312         }
10313       else if (unformat (line_input, "remote %U",
10314                          unformat_ip46_address, &remote))
10315         {
10316           remote_set = 1;
10317         }
10318       else if (unformat (line_input, "group %U %U",
10319                          unformat_ip46_address, &remote,
10320                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
10321         {
10322           grp_set = remote_set = 1;
10323         }
10324       else if (unformat (line_input, "group %U",
10325                          unformat_ip46_address, &remote))
10326         {
10327           grp_set = remote_set = 1;
10328         }
10329       else
10330         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
10331         ;
10332       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
10333         ;
10334       else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
10335         ;
10336       else if (unformat (line_input, "vni %d", &vni))
10337         vni_set = 1;
10338       else if (unformat (line_input, "next-ip4"))
10339         protocol = 1;
10340       else if (unformat (line_input, "next-ip6"))
10341         protocol = 2;
10342       else if (unformat (line_input, "next-ethernet"))
10343         protocol = 3;
10344       else if (unformat (line_input, "next-nsh"))
10345         protocol = 4;
10346       else
10347         {
10348           errmsg ("parse error '%U'", format_unformat_error, line_input);
10349           return -99;
10350         }
10351     }
10352
10353   if (local_set == 0)
10354     {
10355       errmsg ("tunnel local address not specified");
10356       return -99;
10357     }
10358   if (remote_set == 0)
10359     {
10360       errmsg ("tunnel remote address not specified");
10361       return -99;
10362     }
10363   if (grp_set && mcast_sw_if_index == ~0)
10364     {
10365       errmsg ("tunnel nonexistent multicast device");
10366       return -99;
10367     }
10368   if (ip46_address_is_ip4 (&local) != ip46_address_is_ip4 (&remote))
10369     {
10370       errmsg ("both IPv4 and IPv6 addresses specified");
10371       return -99;
10372     }
10373
10374   if (vni_set == 0)
10375     {
10376       errmsg ("vni not specified");
10377       return -99;
10378     }
10379
10380   M (VXLAN_GPE_ADD_DEL_TUNNEL, mp);
10381
10382   ip_address_encode (&local,
10383                      ip46_address_is_ip4 (&local) ? IP46_TYPE_IP4 :
10384                      IP46_TYPE_IP6, &mp->local);
10385   ip_address_encode (&remote,
10386                      ip46_address_is_ip4 (&remote) ? IP46_TYPE_IP4 :
10387                      IP46_TYPE_IP6, &mp->remote);
10388
10389   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
10390   mp->encap_vrf_id = ntohl (encap_vrf_id);
10391   mp->decap_vrf_id = ntohl (decap_vrf_id);
10392   mp->protocol = protocol;
10393   mp->vni = ntohl (vni);
10394   mp->is_add = is_add;
10395
10396   S (mp);
10397   W (ret);
10398   return ret;
10399 }
10400
10401 static void vl_api_vxlan_gpe_tunnel_details_t_handler
10402   (vl_api_vxlan_gpe_tunnel_details_t * mp)
10403 {
10404   vat_main_t *vam = &vat_main;
10405   ip46_address_t local, remote;
10406
10407   ip_address_decode (&mp->local, &local);
10408   ip_address_decode (&mp->remote, &remote);
10409
10410   print (vam->ofp, "%11d%24U%24U%13d%12d%19d%14d%14d",
10411          ntohl (mp->sw_if_index),
10412          format_ip46_address, &local, IP46_TYPE_ANY,
10413          format_ip46_address, &remote, IP46_TYPE_ANY,
10414          ntohl (mp->vni), mp->protocol,
10415          ntohl (mp->mcast_sw_if_index),
10416          ntohl (mp->encap_vrf_id), ntohl (mp->decap_vrf_id));
10417 }
10418
10419
10420 static void vl_api_vxlan_gpe_tunnel_details_t_handler_json
10421   (vl_api_vxlan_gpe_tunnel_details_t * mp)
10422 {
10423   vat_main_t *vam = &vat_main;
10424   vat_json_node_t *node = NULL;
10425   struct in_addr ip4;
10426   struct in6_addr ip6;
10427   ip46_address_t local, remote;
10428
10429   ip_address_decode (&mp->local, &local);
10430   ip_address_decode (&mp->remote, &remote);
10431
10432   if (VAT_JSON_ARRAY != vam->json_tree.type)
10433     {
10434       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10435       vat_json_init_array (&vam->json_tree);
10436     }
10437   node = vat_json_array_add (&vam->json_tree);
10438
10439   vat_json_init_object (node);
10440   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10441   if (ip46_address_is_ip4 (&local))
10442     {
10443       clib_memcpy (&ip4, &local.ip4, sizeof (ip4));
10444       vat_json_object_add_ip4 (node, "local", ip4);
10445       clib_memcpy (&ip4, &remote.ip4, sizeof (ip4));
10446       vat_json_object_add_ip4 (node, "remote", ip4);
10447     }
10448   else
10449     {
10450       clib_memcpy (&ip6, &local.ip6, sizeof (ip6));
10451       vat_json_object_add_ip6 (node, "local", ip6);
10452       clib_memcpy (&ip6, &remote.ip6, sizeof (ip6));
10453       vat_json_object_add_ip6 (node, "remote", ip6);
10454     }
10455   vat_json_object_add_uint (node, "vni", ntohl (mp->vni));
10456   vat_json_object_add_uint (node, "protocol", ntohl (mp->protocol));
10457   vat_json_object_add_uint (node, "mcast_sw_if_index",
10458                             ntohl (mp->mcast_sw_if_index));
10459   vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id));
10460   vat_json_object_add_uint (node, "decap_vrf_id", ntohl (mp->decap_vrf_id));
10461   vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6 ? 1 : 0);
10462 }
10463
10464 static int
10465 api_vxlan_gpe_tunnel_dump (vat_main_t * vam)
10466 {
10467   unformat_input_t *i = vam->input;
10468   vl_api_vxlan_gpe_tunnel_dump_t *mp;
10469   vl_api_control_ping_t *mp_ping;
10470   u32 sw_if_index;
10471   u8 sw_if_index_set = 0;
10472   int ret;
10473
10474   /* Parse args required to build the message */
10475   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10476     {
10477       if (unformat (i, "sw_if_index %d", &sw_if_index))
10478         sw_if_index_set = 1;
10479       else
10480         break;
10481     }
10482
10483   if (sw_if_index_set == 0)
10484     {
10485       sw_if_index = ~0;
10486     }
10487
10488   if (!vam->json_output)
10489     {
10490       print (vam->ofp, "%11s%24s%24s%13s%15s%19s%14s%14s",
10491              "sw_if_index", "local", "remote", "vni",
10492              "protocol", "mcast_sw_if_index", "encap_vrf_id", "decap_vrf_id");
10493     }
10494
10495   /* Get list of vxlan-tunnel interfaces */
10496   M (VXLAN_GPE_TUNNEL_DUMP, mp);
10497
10498   mp->sw_if_index = htonl (sw_if_index);
10499
10500   S (mp);
10501
10502   /* Use a control ping for synchronization */
10503   MPING (CONTROL_PING, mp_ping);
10504   S (mp_ping);
10505
10506   W (ret);
10507   return ret;
10508 }
10509
10510 static void vl_api_l2_fib_table_details_t_handler
10511   (vl_api_l2_fib_table_details_t * mp)
10512 {
10513   vat_main_t *vam = &vat_main;
10514
10515   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
10516          "       %d       %d     %d",
10517          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
10518          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
10519          mp->bvi_mac);
10520 }
10521
10522 static void vl_api_l2_fib_table_details_t_handler_json
10523   (vl_api_l2_fib_table_details_t * mp)
10524 {
10525   vat_main_t *vam = &vat_main;
10526   vat_json_node_t *node = NULL;
10527
10528   if (VAT_JSON_ARRAY != vam->json_tree.type)
10529     {
10530       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10531       vat_json_init_array (&vam->json_tree);
10532     }
10533   node = vat_json_array_add (&vam->json_tree);
10534
10535   vat_json_init_object (node);
10536   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
10537   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
10538   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
10539   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
10540   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
10541   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
10542 }
10543
10544 static int
10545 api_l2_fib_table_dump (vat_main_t * vam)
10546 {
10547   unformat_input_t *i = vam->input;
10548   vl_api_l2_fib_table_dump_t *mp;
10549   vl_api_control_ping_t *mp_ping;
10550   u32 bd_id;
10551   u8 bd_id_set = 0;
10552   int ret;
10553
10554   /* Parse args required to build the message */
10555   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10556     {
10557       if (unformat (i, "bd_id %d", &bd_id))
10558         bd_id_set = 1;
10559       else
10560         break;
10561     }
10562
10563   if (bd_id_set == 0)
10564     {
10565       errmsg ("missing bridge domain");
10566       return -99;
10567     }
10568
10569   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
10570
10571   /* Get list of l2 fib entries */
10572   M (L2_FIB_TABLE_DUMP, mp);
10573
10574   mp->bd_id = ntohl (bd_id);
10575   S (mp);
10576
10577   /* Use a control ping for synchronization */
10578   MPING (CONTROL_PING, mp_ping);
10579   S (mp_ping);
10580
10581   W (ret);
10582   return ret;
10583 }
10584
10585
10586 static int
10587 api_interface_name_renumber (vat_main_t * vam)
10588 {
10589   unformat_input_t *line_input = vam->input;
10590   vl_api_interface_name_renumber_t *mp;
10591   u32 sw_if_index = ~0;
10592   u32 new_show_dev_instance = ~0;
10593   int ret;
10594
10595   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10596     {
10597       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
10598                     &sw_if_index))
10599         ;
10600       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
10601         ;
10602       else if (unformat (line_input, "new_show_dev_instance %d",
10603                          &new_show_dev_instance))
10604         ;
10605       else
10606         break;
10607     }
10608
10609   if (sw_if_index == ~0)
10610     {
10611       errmsg ("missing interface name or sw_if_index");
10612       return -99;
10613     }
10614
10615   if (new_show_dev_instance == ~0)
10616     {
10617       errmsg ("missing new_show_dev_instance");
10618       return -99;
10619     }
10620
10621   M (INTERFACE_NAME_RENUMBER, mp);
10622
10623   mp->sw_if_index = ntohl (sw_if_index);
10624   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
10625
10626   S (mp);
10627   W (ret);
10628   return ret;
10629 }
10630
10631 static int
10632 api_want_l2_macs_events (vat_main_t * vam)
10633 {
10634   unformat_input_t *line_input = vam->input;
10635   vl_api_want_l2_macs_events_t *mp;
10636   u8 enable_disable = 1;
10637   u32 scan_delay = 0;
10638   u32 max_macs_in_event = 0;
10639   u32 learn_limit = 0;
10640   int ret;
10641
10642   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
10643     {
10644       if (unformat (line_input, "learn-limit %d", &learn_limit))
10645         ;
10646       else if (unformat (line_input, "scan-delay %d", &scan_delay))
10647         ;
10648       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
10649         ;
10650       else if (unformat (line_input, "disable"))
10651         enable_disable = 0;
10652       else
10653         break;
10654     }
10655
10656   M (WANT_L2_MACS_EVENTS, mp);
10657   mp->enable_disable = enable_disable;
10658   mp->pid = htonl (getpid ());
10659   mp->learn_limit = htonl (learn_limit);
10660   mp->scan_delay = (u8) scan_delay;
10661   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
10662   S (mp);
10663   W (ret);
10664   return ret;
10665 }
10666
10667 static int
10668 api_input_acl_set_interface (vat_main_t * vam)
10669 {
10670   unformat_input_t *i = vam->input;
10671   vl_api_input_acl_set_interface_t *mp;
10672   u32 sw_if_index;
10673   int sw_if_index_set;
10674   u32 ip4_table_index = ~0;
10675   u32 ip6_table_index = ~0;
10676   u32 l2_table_index = ~0;
10677   u8 is_add = 1;
10678   int ret;
10679
10680   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10681     {
10682       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10683         sw_if_index_set = 1;
10684       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10685         sw_if_index_set = 1;
10686       else if (unformat (i, "del"))
10687         is_add = 0;
10688       else if (unformat (i, "ip4-table %d", &ip4_table_index))
10689         ;
10690       else if (unformat (i, "ip6-table %d", &ip6_table_index))
10691         ;
10692       else if (unformat (i, "l2-table %d", &l2_table_index))
10693         ;
10694       else
10695         {
10696           clib_warning ("parse error '%U'", format_unformat_error, i);
10697           return -99;
10698         }
10699     }
10700
10701   if (sw_if_index_set == 0)
10702     {
10703       errmsg ("missing interface name or sw_if_index");
10704       return -99;
10705     }
10706
10707   M (INPUT_ACL_SET_INTERFACE, mp);
10708
10709   mp->sw_if_index = ntohl (sw_if_index);
10710   mp->ip4_table_index = ntohl (ip4_table_index);
10711   mp->ip6_table_index = ntohl (ip6_table_index);
10712   mp->l2_table_index = ntohl (l2_table_index);
10713   mp->is_add = is_add;
10714
10715   S (mp);
10716   W (ret);
10717   return ret;
10718 }
10719
10720 static int
10721 api_output_acl_set_interface (vat_main_t * vam)
10722 {
10723   unformat_input_t *i = vam->input;
10724   vl_api_output_acl_set_interface_t *mp;
10725   u32 sw_if_index;
10726   int sw_if_index_set;
10727   u32 ip4_table_index = ~0;
10728   u32 ip6_table_index = ~0;
10729   u32 l2_table_index = ~0;
10730   u8 is_add = 1;
10731   int ret;
10732
10733   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10734     {
10735       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10736         sw_if_index_set = 1;
10737       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10738         sw_if_index_set = 1;
10739       else if (unformat (i, "del"))
10740         is_add = 0;
10741       else if (unformat (i, "ip4-table %d", &ip4_table_index))
10742         ;
10743       else if (unformat (i, "ip6-table %d", &ip6_table_index))
10744         ;
10745       else if (unformat (i, "l2-table %d", &l2_table_index))
10746         ;
10747       else
10748         {
10749           clib_warning ("parse error '%U'", format_unformat_error, i);
10750           return -99;
10751         }
10752     }
10753
10754   if (sw_if_index_set == 0)
10755     {
10756       errmsg ("missing interface name or sw_if_index");
10757       return -99;
10758     }
10759
10760   M (OUTPUT_ACL_SET_INTERFACE, mp);
10761
10762   mp->sw_if_index = ntohl (sw_if_index);
10763   mp->ip4_table_index = ntohl (ip4_table_index);
10764   mp->ip6_table_index = ntohl (ip6_table_index);
10765   mp->l2_table_index = ntohl (l2_table_index);
10766   mp->is_add = is_add;
10767
10768   S (mp);
10769   W (ret);
10770   return ret;
10771 }
10772
10773 static int
10774 api_ip_address_dump (vat_main_t * vam)
10775 {
10776   unformat_input_t *i = vam->input;
10777   vl_api_ip_address_dump_t *mp;
10778   vl_api_control_ping_t *mp_ping;
10779   u32 sw_if_index = ~0;
10780   u8 sw_if_index_set = 0;
10781   u8 ipv4_set = 0;
10782   u8 ipv6_set = 0;
10783   int ret;
10784
10785   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10786     {
10787       if (unformat (i, "sw_if_index %d", &sw_if_index))
10788         sw_if_index_set = 1;
10789       else
10790         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10791         sw_if_index_set = 1;
10792       else if (unformat (i, "ipv4"))
10793         ipv4_set = 1;
10794       else if (unformat (i, "ipv6"))
10795         ipv6_set = 1;
10796       else
10797         break;
10798     }
10799
10800   if (ipv4_set && ipv6_set)
10801     {
10802       errmsg ("ipv4 and ipv6 flags cannot be both set");
10803       return -99;
10804     }
10805
10806   if ((!ipv4_set) && (!ipv6_set))
10807     {
10808       errmsg ("no ipv4 nor ipv6 flag set");
10809       return -99;
10810     }
10811
10812   if (sw_if_index_set == 0)
10813     {
10814       errmsg ("missing interface name or sw_if_index");
10815       return -99;
10816     }
10817
10818   vam->current_sw_if_index = sw_if_index;
10819   vam->is_ipv6 = ipv6_set;
10820
10821   M (IP_ADDRESS_DUMP, mp);
10822   mp->sw_if_index = ntohl (sw_if_index);
10823   mp->is_ipv6 = ipv6_set;
10824   S (mp);
10825
10826   /* Use a control ping for synchronization */
10827   MPING (CONTROL_PING, mp_ping);
10828   S (mp_ping);
10829
10830   W (ret);
10831   return ret;
10832 }
10833
10834 static int
10835 api_ip_dump (vat_main_t * vam)
10836 {
10837   vl_api_ip_dump_t *mp;
10838   vl_api_control_ping_t *mp_ping;
10839   unformat_input_t *in = vam->input;
10840   int ipv4_set = 0;
10841   int ipv6_set = 0;
10842   int is_ipv6;
10843   int i;
10844   int ret;
10845
10846   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
10847     {
10848       if (unformat (in, "ipv4"))
10849         ipv4_set = 1;
10850       else if (unformat (in, "ipv6"))
10851         ipv6_set = 1;
10852       else
10853         break;
10854     }
10855
10856   if (ipv4_set && ipv6_set)
10857     {
10858       errmsg ("ipv4 and ipv6 flags cannot be both set");
10859       return -99;
10860     }
10861
10862   if ((!ipv4_set) && (!ipv6_set))
10863     {
10864       errmsg ("no ipv4 nor ipv6 flag set");
10865       return -99;
10866     }
10867
10868   is_ipv6 = ipv6_set;
10869   vam->is_ipv6 = is_ipv6;
10870
10871   /* free old data */
10872   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
10873     {
10874       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
10875     }
10876   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
10877
10878   M (IP_DUMP, mp);
10879   mp->is_ipv6 = ipv6_set;
10880   S (mp);
10881
10882   /* Use a control ping for synchronization */
10883   MPING (CONTROL_PING, mp_ping);
10884   S (mp_ping);
10885
10886   W (ret);
10887   return ret;
10888 }
10889
10890 static int
10891 api_ipsec_spd_add_del (vat_main_t * vam)
10892 {
10893   unformat_input_t *i = vam->input;
10894   vl_api_ipsec_spd_add_del_t *mp;
10895   u32 spd_id = ~0;
10896   u8 is_add = 1;
10897   int ret;
10898
10899   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10900     {
10901       if (unformat (i, "spd_id %d", &spd_id))
10902         ;
10903       else if (unformat (i, "del"))
10904         is_add = 0;
10905       else
10906         {
10907           clib_warning ("parse error '%U'", format_unformat_error, i);
10908           return -99;
10909         }
10910     }
10911   if (spd_id == ~0)
10912     {
10913       errmsg ("spd_id must be set");
10914       return -99;
10915     }
10916
10917   M (IPSEC_SPD_ADD_DEL, mp);
10918
10919   mp->spd_id = ntohl (spd_id);
10920   mp->is_add = is_add;
10921
10922   S (mp);
10923   W (ret);
10924   return ret;
10925 }
10926
10927 static int
10928 api_ipsec_interface_add_del_spd (vat_main_t * vam)
10929 {
10930   unformat_input_t *i = vam->input;
10931   vl_api_ipsec_interface_add_del_spd_t *mp;
10932   u32 sw_if_index;
10933   u8 sw_if_index_set = 0;
10934   u32 spd_id = (u32) ~ 0;
10935   u8 is_add = 1;
10936   int ret;
10937
10938   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10939     {
10940       if (unformat (i, "del"))
10941         is_add = 0;
10942       else if (unformat (i, "spd_id %d", &spd_id))
10943         ;
10944       else
10945         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10946         sw_if_index_set = 1;
10947       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10948         sw_if_index_set = 1;
10949       else
10950         {
10951           clib_warning ("parse error '%U'", format_unformat_error, i);
10952           return -99;
10953         }
10954
10955     }
10956
10957   if (spd_id == (u32) ~ 0)
10958     {
10959       errmsg ("spd_id must be set");
10960       return -99;
10961     }
10962
10963   if (sw_if_index_set == 0)
10964     {
10965       errmsg ("missing interface name or sw_if_index");
10966       return -99;
10967     }
10968
10969   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
10970
10971   mp->spd_id = ntohl (spd_id);
10972   mp->sw_if_index = ntohl (sw_if_index);
10973   mp->is_add = is_add;
10974
10975   S (mp);
10976   W (ret);
10977   return ret;
10978 }
10979
10980 static int
10981 api_ipsec_spd_entry_add_del (vat_main_t * vam)
10982 {
10983   unformat_input_t *i = vam->input;
10984   vl_api_ipsec_spd_entry_add_del_t *mp;
10985   u8 is_add = 1, is_outbound = 0;
10986   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
10987   i32 priority = 0;
10988   u32 rport_start = 0, rport_stop = (u32) ~ 0;
10989   u32 lport_start = 0, lport_stop = (u32) ~ 0;
10990   vl_api_address_t laddr_start = { }, laddr_stop =
10991   {
10992   }, raddr_start =
10993   {
10994   }, raddr_stop =
10995   {
10996   };
10997   int ret;
10998
10999   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11000     {
11001       if (unformat (i, "del"))
11002         is_add = 0;
11003       if (unformat (i, "outbound"))
11004         is_outbound = 1;
11005       if (unformat (i, "inbound"))
11006         is_outbound = 0;
11007       else if (unformat (i, "spd_id %d", &spd_id))
11008         ;
11009       else if (unformat (i, "sa_id %d", &sa_id))
11010         ;
11011       else if (unformat (i, "priority %d", &priority))
11012         ;
11013       else if (unformat (i, "protocol %d", &protocol))
11014         ;
11015       else if (unformat (i, "lport_start %d", &lport_start))
11016         ;
11017       else if (unformat (i, "lport_stop %d", &lport_stop))
11018         ;
11019       else if (unformat (i, "rport_start %d", &rport_start))
11020         ;
11021       else if (unformat (i, "rport_stop %d", &rport_stop))
11022         ;
11023       else if (unformat (i, "laddr_start %U",
11024                          unformat_vl_api_address, &laddr_start))
11025         ;
11026       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
11027                          &laddr_stop))
11028         ;
11029       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
11030                          &raddr_start))
11031         ;
11032       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
11033                          &raddr_stop))
11034         ;
11035       else
11036         if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
11037         {
11038           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
11039             {
11040               clib_warning ("unsupported action: 'resolve'");
11041               return -99;
11042             }
11043         }
11044       else
11045         {
11046           clib_warning ("parse error '%U'", format_unformat_error, i);
11047           return -99;
11048         }
11049
11050     }
11051
11052   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
11053
11054   mp->is_add = is_add;
11055
11056   mp->entry.spd_id = ntohl (spd_id);
11057   mp->entry.priority = ntohl (priority);
11058   mp->entry.is_outbound = is_outbound;
11059
11060   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
11061                sizeof (vl_api_address_t));
11062   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
11063                sizeof (vl_api_address_t));
11064   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
11065                sizeof (vl_api_address_t));
11066   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
11067                sizeof (vl_api_address_t));
11068
11069   mp->entry.protocol = (u8) protocol;
11070   mp->entry.local_port_start = ntohs ((u16) lport_start);
11071   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
11072   mp->entry.remote_port_start = ntohs ((u16) rport_start);
11073   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
11074   mp->entry.policy = (u8) policy;
11075   mp->entry.sa_id = ntohl (sa_id);
11076
11077   S (mp);
11078   W (ret);
11079   return ret;
11080 }
11081
11082 static int
11083 api_ipsec_sad_entry_add_del (vat_main_t * vam)
11084 {
11085   unformat_input_t *i = vam->input;
11086   vl_api_ipsec_sad_entry_add_del_t *mp;
11087   u32 sad_id = 0, spi = 0;
11088   u8 *ck = 0, *ik = 0;
11089   u8 is_add = 1;
11090
11091   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
11092   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
11093   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
11094   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
11095   vl_api_address_t tun_src, tun_dst;
11096   int ret;
11097
11098   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11099     {
11100       if (unformat (i, "del"))
11101         is_add = 0;
11102       else if (unformat (i, "sad_id %d", &sad_id))
11103         ;
11104       else if (unformat (i, "spi %d", &spi))
11105         ;
11106       else if (unformat (i, "esp"))
11107         protocol = IPSEC_API_PROTO_ESP;
11108       else
11109         if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
11110         {
11111           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
11112           if (ADDRESS_IP6 == tun_src.af)
11113             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
11114         }
11115       else
11116         if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
11117         {
11118           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
11119           if (ADDRESS_IP6 == tun_src.af)
11120             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
11121         }
11122       else
11123         if (unformat (i, "crypto_alg %U",
11124                       unformat_ipsec_api_crypto_alg, &crypto_alg))
11125         ;
11126       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
11127         ;
11128       else if (unformat (i, "integ_alg %U",
11129                          unformat_ipsec_api_integ_alg, &integ_alg))
11130         ;
11131       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
11132         ;
11133       else
11134         {
11135           clib_warning ("parse error '%U'", format_unformat_error, i);
11136           return -99;
11137         }
11138
11139     }
11140
11141   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
11142
11143   mp->is_add = is_add;
11144   mp->entry.sad_id = ntohl (sad_id);
11145   mp->entry.protocol = protocol;
11146   mp->entry.spi = ntohl (spi);
11147   mp->entry.flags = flags;
11148
11149   mp->entry.crypto_algorithm = crypto_alg;
11150   mp->entry.integrity_algorithm = integ_alg;
11151   mp->entry.crypto_key.length = vec_len (ck);
11152   mp->entry.integrity_key.length = vec_len (ik);
11153
11154   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
11155     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
11156
11157   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
11158     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
11159
11160   if (ck)
11161     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
11162   if (ik)
11163     clib_memcpy (mp->entry.integrity_key.data, ik,
11164                  mp->entry.integrity_key.length);
11165
11166   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
11167     {
11168       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
11169                    sizeof (mp->entry.tunnel_src));
11170       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
11171                    sizeof (mp->entry.tunnel_dst));
11172     }
11173
11174   S (mp);
11175   W (ret);
11176   return ret;
11177 }
11178
11179 static int
11180 api_ipsec_tunnel_if_add_del (vat_main_t * vam)
11181 {
11182   unformat_input_t *i = vam->input;
11183   vl_api_ipsec_tunnel_if_add_del_t *mp;
11184   u32 local_spi = 0, remote_spi = 0;
11185   u32 crypto_alg = 0, integ_alg = 0;
11186   u8 *lck = NULL, *rck = NULL;
11187   u8 *lik = NULL, *rik = NULL;
11188   vl_api_address_t local_ip = { 0 };
11189   vl_api_address_t remote_ip = { 0 };
11190   f64 before = 0;
11191   u8 is_add = 1;
11192   u8 esn = 0;
11193   u8 anti_replay = 0;
11194   u8 renumber = 0;
11195   u32 instance = ~0;
11196   u32 count = 1, jj;
11197   int ret = -1;
11198
11199   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11200     {
11201       if (unformat (i, "del"))
11202         is_add = 0;
11203       else if (unformat (i, "esn"))
11204         esn = 1;
11205       else if (unformat (i, "anti-replay"))
11206         anti_replay = 1;
11207       else if (unformat (i, "count %d", &count))
11208         ;
11209       else if (unformat (i, "local_spi %d", &local_spi))
11210         ;
11211       else if (unformat (i, "remote_spi %d", &remote_spi))
11212         ;
11213       else
11214         if (unformat (i, "local_ip %U", unformat_vl_api_address, &local_ip))
11215         ;
11216       else
11217         if (unformat (i, "remote_ip %U", unformat_vl_api_address, &remote_ip))
11218         ;
11219       else if (unformat (i, "local_crypto_key %U", unformat_hex_string, &lck))
11220         ;
11221       else
11222         if (unformat (i, "remote_crypto_key %U", unformat_hex_string, &rck))
11223         ;
11224       else if (unformat (i, "local_integ_key %U", unformat_hex_string, &lik))
11225         ;
11226       else if (unformat (i, "remote_integ_key %U", unformat_hex_string, &rik))
11227         ;
11228       else
11229         if (unformat
11230             (i, "crypto_alg %U", unformat_ipsec_api_crypto_alg, &crypto_alg))
11231         {
11232           if (crypto_alg >= IPSEC_CRYPTO_N_ALG)
11233             {
11234               errmsg ("unsupported crypto-alg: '%U'\n",
11235                       format_ipsec_crypto_alg, crypto_alg);
11236               return -99;
11237             }
11238         }
11239       else
11240         if (unformat
11241             (i, "integ_alg %U", unformat_ipsec_api_integ_alg, &integ_alg))
11242         {
11243           if (integ_alg >= IPSEC_INTEG_N_ALG)
11244             {
11245               errmsg ("unsupported integ-alg: '%U'\n",
11246                       format_ipsec_integ_alg, integ_alg);
11247               return -99;
11248             }
11249         }
11250       else if (unformat (i, "instance %u", &instance))
11251         renumber = 1;
11252       else
11253         {
11254           errmsg ("parse error '%U'\n", format_unformat_error, i);
11255           return -99;
11256         }
11257     }
11258
11259   if (count > 1)
11260     {
11261       /* Turn on async mode */
11262       vam->async_mode = 1;
11263       vam->async_errors = 0;
11264       before = vat_time_now (vam);
11265     }
11266
11267   for (jj = 0; jj < count; jj++)
11268     {
11269       M (IPSEC_TUNNEL_IF_ADD_DEL, mp);
11270
11271       mp->is_add = is_add;
11272       mp->esn = esn;
11273       mp->anti_replay = anti_replay;
11274
11275       if (jj > 0)
11276         increment_address (&remote_ip);
11277
11278       clib_memcpy (&mp->local_ip, &local_ip, sizeof (local_ip));
11279       clib_memcpy (&mp->remote_ip, &remote_ip, sizeof (remote_ip));
11280
11281       mp->local_spi = htonl (local_spi + jj);
11282       mp->remote_spi = htonl (remote_spi + jj);
11283       mp->crypto_alg = (u8) crypto_alg;
11284
11285       mp->local_crypto_key_len = 0;
11286       if (lck)
11287         {
11288           mp->local_crypto_key_len = vec_len (lck);
11289           if (mp->local_crypto_key_len > sizeof (mp->local_crypto_key))
11290             mp->local_crypto_key_len = sizeof (mp->local_crypto_key);
11291           clib_memcpy (mp->local_crypto_key, lck, mp->local_crypto_key_len);
11292         }
11293
11294       mp->remote_crypto_key_len = 0;
11295       if (rck)
11296         {
11297           mp->remote_crypto_key_len = vec_len (rck);
11298           if (mp->remote_crypto_key_len > sizeof (mp->remote_crypto_key))
11299             mp->remote_crypto_key_len = sizeof (mp->remote_crypto_key);
11300           clib_memcpy (mp->remote_crypto_key, rck, mp->remote_crypto_key_len);
11301         }
11302
11303       mp->integ_alg = (u8) integ_alg;
11304
11305       mp->local_integ_key_len = 0;
11306       if (lik)
11307         {
11308           mp->local_integ_key_len = vec_len (lik);
11309           if (mp->local_integ_key_len > sizeof (mp->local_integ_key))
11310             mp->local_integ_key_len = sizeof (mp->local_integ_key);
11311           clib_memcpy (mp->local_integ_key, lik, mp->local_integ_key_len);
11312         }
11313
11314       mp->remote_integ_key_len = 0;
11315       if (rik)
11316         {
11317           mp->remote_integ_key_len = vec_len (rik);
11318           if (mp->remote_integ_key_len > sizeof (mp->remote_integ_key))
11319             mp->remote_integ_key_len = sizeof (mp->remote_integ_key);
11320           clib_memcpy (mp->remote_integ_key, rik, mp->remote_integ_key_len);
11321         }
11322
11323       if (renumber)
11324         {
11325           mp->renumber = renumber;
11326           mp->show_instance = ntohl (instance);
11327         }
11328       S (mp);
11329     }
11330
11331   /* When testing multiple add/del ops, use a control-ping to sync */
11332   if (count > 1)
11333     {
11334       vl_api_control_ping_t *mp_ping;
11335       f64 after;
11336       f64 timeout;
11337
11338       /* Shut off async mode */
11339       vam->async_mode = 0;
11340
11341       MPING (CONTROL_PING, mp_ping);
11342       S (mp_ping);
11343
11344       timeout = vat_time_now (vam) + 1.0;
11345       while (vat_time_now (vam) < timeout)
11346         if (vam->result_ready == 1)
11347           goto out;
11348       vam->retval = -99;
11349
11350     out:
11351       if (vam->retval == -99)
11352         errmsg ("timeout");
11353
11354       if (vam->async_errors > 0)
11355         {
11356           errmsg ("%d asynchronous errors", vam->async_errors);
11357           vam->retval = -98;
11358         }
11359       vam->async_errors = 0;
11360       after = vat_time_now (vam);
11361
11362       /* slim chance, but we might have eaten SIGTERM on the first iteration */
11363       if (jj > 0)
11364         count = jj;
11365
11366       print (vam->ofp, "%d tunnels in %.6f secs, %.2f tunnels/sec",
11367              count, after - before, count / (after - before));
11368     }
11369   else
11370     {
11371       /* Wait for a reply... */
11372       W (ret);
11373       return ret;
11374     }
11375
11376   return ret;
11377 }
11378
11379 static void
11380 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
11381 {
11382   vat_main_t *vam = &vat_main;
11383
11384   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
11385          "crypto_key %U integ_alg %u integ_key %U flags %x "
11386          "tunnel_src_addr %U tunnel_dst_addr %U "
11387          "salt %u seq_outbound %lu last_seq_inbound %lu "
11388          "replay_window %lu stat_index %u\n",
11389          ntohl (mp->entry.sad_id),
11390          ntohl (mp->sw_if_index),
11391          ntohl (mp->entry.spi),
11392          ntohl (mp->entry.protocol),
11393          ntohl (mp->entry.crypto_algorithm),
11394          format_hex_bytes, mp->entry.crypto_key.data,
11395          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
11396          format_hex_bytes, mp->entry.integrity_key.data,
11397          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
11398          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
11399          &mp->entry.tunnel_dst, ntohl (mp->salt),
11400          clib_net_to_host_u64 (mp->seq_outbound),
11401          clib_net_to_host_u64 (mp->last_seq_inbound),
11402          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
11403 }
11404
11405 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
11406 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
11407
11408 static void vl_api_ipsec_sa_details_t_handler_json
11409   (vl_api_ipsec_sa_details_t * mp)
11410 {
11411   vat_main_t *vam = &vat_main;
11412   vat_json_node_t *node = NULL;
11413   vl_api_ipsec_sad_flags_t flags;
11414
11415   if (VAT_JSON_ARRAY != vam->json_tree.type)
11416     {
11417       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11418       vat_json_init_array (&vam->json_tree);
11419     }
11420   node = vat_json_array_add (&vam->json_tree);
11421
11422   vat_json_init_object (node);
11423   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
11424   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11425   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
11426   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
11427   vat_json_object_add_uint (node, "crypto_alg",
11428                             ntohl (mp->entry.crypto_algorithm));
11429   vat_json_object_add_uint (node, "integ_alg",
11430                             ntohl (mp->entry.integrity_algorithm));
11431   flags = ntohl (mp->entry.flags);
11432   vat_json_object_add_uint (node, "use_esn",
11433                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
11434   vat_json_object_add_uint (node, "use_anti_replay",
11435                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
11436   vat_json_object_add_uint (node, "is_tunnel",
11437                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
11438   vat_json_object_add_uint (node, "is_tunnel_ip6",
11439                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
11440   vat_json_object_add_uint (node, "udp_encap",
11441                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
11442   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
11443                              mp->entry.crypto_key.length);
11444   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
11445                              mp->entry.integrity_key.length);
11446   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
11447   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
11448   vat_json_object_add_uint (node, "replay_window",
11449                             clib_net_to_host_u64 (mp->replay_window));
11450   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
11451 }
11452
11453 static int
11454 api_ipsec_sa_dump (vat_main_t * vam)
11455 {
11456   unformat_input_t *i = vam->input;
11457   vl_api_ipsec_sa_dump_t *mp;
11458   vl_api_control_ping_t *mp_ping;
11459   u32 sa_id = ~0;
11460   int ret;
11461
11462   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11463     {
11464       if (unformat (i, "sa_id %d", &sa_id))
11465         ;
11466       else
11467         {
11468           clib_warning ("parse error '%U'", format_unformat_error, i);
11469           return -99;
11470         }
11471     }
11472
11473   M (IPSEC_SA_DUMP, mp);
11474
11475   mp->sa_id = ntohl (sa_id);
11476
11477   S (mp);
11478
11479   /* Use a control ping for synchronization */
11480   M (CONTROL_PING, mp_ping);
11481   S (mp_ping);
11482
11483   W (ret);
11484   return ret;
11485 }
11486
11487 static int
11488 api_ipsec_tunnel_if_set_sa (vat_main_t * vam)
11489 {
11490   unformat_input_t *i = vam->input;
11491   vl_api_ipsec_tunnel_if_set_sa_t *mp;
11492   u32 sw_if_index = ~0;
11493   u32 sa_id = ~0;
11494   u8 is_outbound = (u8) ~ 0;
11495   int ret;
11496
11497   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11498     {
11499       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11500         ;
11501       else if (unformat (i, "sa_id %d", &sa_id))
11502         ;
11503       else if (unformat (i, "outbound"))
11504         is_outbound = 1;
11505       else if (unformat (i, "inbound"))
11506         is_outbound = 0;
11507       else
11508         {
11509           clib_warning ("parse error '%U'", format_unformat_error, i);
11510           return -99;
11511         }
11512     }
11513
11514   if (sw_if_index == ~0)
11515     {
11516       errmsg ("interface must be specified");
11517       return -99;
11518     }
11519
11520   if (sa_id == ~0)
11521     {
11522       errmsg ("SA ID must be specified");
11523       return -99;
11524     }
11525
11526   M (IPSEC_TUNNEL_IF_SET_SA, mp);
11527
11528   mp->sw_if_index = htonl (sw_if_index);
11529   mp->sa_id = htonl (sa_id);
11530   mp->is_outbound = is_outbound;
11531
11532   S (mp);
11533   W (ret);
11534
11535   return ret;
11536 }
11537
11538 static int
11539 api_get_first_msg_id (vat_main_t * vam)
11540 {
11541   vl_api_get_first_msg_id_t *mp;
11542   unformat_input_t *i = vam->input;
11543   u8 *name;
11544   u8 name_set = 0;
11545   int ret;
11546
11547   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11548     {
11549       if (unformat (i, "client %s", &name))
11550         name_set = 1;
11551       else
11552         break;
11553     }
11554
11555   if (name_set == 0)
11556     {
11557       errmsg ("missing client name");
11558       return -99;
11559     }
11560   vec_add1 (name, 0);
11561
11562   if (vec_len (name) > 63)
11563     {
11564       errmsg ("client name too long");
11565       return -99;
11566     }
11567
11568   M (GET_FIRST_MSG_ID, mp);
11569   clib_memcpy (mp->name, name, vec_len (name));
11570   S (mp);
11571   W (ret);
11572   return ret;
11573 }
11574
11575 static int
11576 api_cop_interface_enable_disable (vat_main_t * vam)
11577 {
11578   unformat_input_t *line_input = vam->input;
11579   vl_api_cop_interface_enable_disable_t *mp;
11580   u32 sw_if_index = ~0;
11581   u8 enable_disable = 1;
11582   int ret;
11583
11584   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11585     {
11586       if (unformat (line_input, "disable"))
11587         enable_disable = 0;
11588       if (unformat (line_input, "enable"))
11589         enable_disable = 1;
11590       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11591                          vam, &sw_if_index))
11592         ;
11593       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11594         ;
11595       else
11596         break;
11597     }
11598
11599   if (sw_if_index == ~0)
11600     {
11601       errmsg ("missing interface name or sw_if_index");
11602       return -99;
11603     }
11604
11605   /* Construct the API message */
11606   M (COP_INTERFACE_ENABLE_DISABLE, mp);
11607   mp->sw_if_index = ntohl (sw_if_index);
11608   mp->enable_disable = enable_disable;
11609
11610   /* send it... */
11611   S (mp);
11612   /* Wait for the reply */
11613   W (ret);
11614   return ret;
11615 }
11616
11617 static int
11618 api_cop_whitelist_enable_disable (vat_main_t * vam)
11619 {
11620   unformat_input_t *line_input = vam->input;
11621   vl_api_cop_whitelist_enable_disable_t *mp;
11622   u32 sw_if_index = ~0;
11623   u8 ip4 = 0, ip6 = 0, default_cop = 0;
11624   u32 fib_id = 0;
11625   int ret;
11626
11627   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11628     {
11629       if (unformat (line_input, "ip4"))
11630         ip4 = 1;
11631       else if (unformat (line_input, "ip6"))
11632         ip6 = 1;
11633       else if (unformat (line_input, "default"))
11634         default_cop = 1;
11635       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11636                          vam, &sw_if_index))
11637         ;
11638       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11639         ;
11640       else if (unformat (line_input, "fib-id %d", &fib_id))
11641         ;
11642       else
11643         break;
11644     }
11645
11646   if (sw_if_index == ~0)
11647     {
11648       errmsg ("missing interface name or sw_if_index");
11649       return -99;
11650     }
11651
11652   /* Construct the API message */
11653   M (COP_WHITELIST_ENABLE_DISABLE, mp);
11654   mp->sw_if_index = ntohl (sw_if_index);
11655   mp->fib_id = ntohl (fib_id);
11656   mp->ip4 = ip4;
11657   mp->ip6 = ip6;
11658   mp->default_cop = default_cop;
11659
11660   /* send it... */
11661   S (mp);
11662   /* Wait for the reply */
11663   W (ret);
11664   return ret;
11665 }
11666
11667 static int
11668 api_get_node_graph (vat_main_t * vam)
11669 {
11670   vl_api_get_node_graph_t *mp;
11671   int ret;
11672
11673   M (GET_NODE_GRAPH, mp);
11674
11675   /* send it... */
11676   S (mp);
11677   /* Wait for the reply */
11678   W (ret);
11679   return ret;
11680 }
11681
11682 static int
11683 api_af_packet_create (vat_main_t * vam)
11684 {
11685   unformat_input_t *i = vam->input;
11686   vl_api_af_packet_create_t *mp;
11687   u8 *host_if_name = 0;
11688   u8 hw_addr[6];
11689   u8 random_hw_addr = 1;
11690   int ret;
11691
11692   clib_memset (hw_addr, 0, sizeof (hw_addr));
11693
11694   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11695     {
11696       if (unformat (i, "name %s", &host_if_name))
11697         vec_add1 (host_if_name, 0);
11698       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
11699         random_hw_addr = 0;
11700       else
11701         break;
11702     }
11703
11704   if (!vec_len (host_if_name))
11705     {
11706       errmsg ("host-interface name must be specified");
11707       return -99;
11708     }
11709
11710   if (vec_len (host_if_name) > 64)
11711     {
11712       errmsg ("host-interface name too long");
11713       return -99;
11714     }
11715
11716   M (AF_PACKET_CREATE, mp);
11717
11718   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11719   clib_memcpy (mp->hw_addr, hw_addr, 6);
11720   mp->use_random_hw_addr = random_hw_addr;
11721   vec_free (host_if_name);
11722
11723   S (mp);
11724
11725   /* *INDENT-OFF* */
11726   W2 (ret,
11727       ({
11728         if (ret == 0)
11729           fprintf (vam->ofp ? vam->ofp : stderr,
11730                    " new sw_if_index = %d\n", vam->sw_if_index);
11731       }));
11732   /* *INDENT-ON* */
11733   return ret;
11734 }
11735
11736 static int
11737 api_af_packet_delete (vat_main_t * vam)
11738 {
11739   unformat_input_t *i = vam->input;
11740   vl_api_af_packet_delete_t *mp;
11741   u8 *host_if_name = 0;
11742   int ret;
11743
11744   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11745     {
11746       if (unformat (i, "name %s", &host_if_name))
11747         vec_add1 (host_if_name, 0);
11748       else
11749         break;
11750     }
11751
11752   if (!vec_len (host_if_name))
11753     {
11754       errmsg ("host-interface name must be specified");
11755       return -99;
11756     }
11757
11758   if (vec_len (host_if_name) > 64)
11759     {
11760       errmsg ("host-interface name too long");
11761       return -99;
11762     }
11763
11764   M (AF_PACKET_DELETE, mp);
11765
11766   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11767   vec_free (host_if_name);
11768
11769   S (mp);
11770   W (ret);
11771   return ret;
11772 }
11773
11774 static void vl_api_af_packet_details_t_handler
11775   (vl_api_af_packet_details_t * mp)
11776 {
11777   vat_main_t *vam = &vat_main;
11778
11779   print (vam->ofp, "%-16s %d",
11780          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
11781 }
11782
11783 static void vl_api_af_packet_details_t_handler_json
11784   (vl_api_af_packet_details_t * mp)
11785 {
11786   vat_main_t *vam = &vat_main;
11787   vat_json_node_t *node = NULL;
11788
11789   if (VAT_JSON_ARRAY != vam->json_tree.type)
11790     {
11791       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11792       vat_json_init_array (&vam->json_tree);
11793     }
11794   node = vat_json_array_add (&vam->json_tree);
11795
11796   vat_json_init_object (node);
11797   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11798   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
11799 }
11800
11801 static int
11802 api_af_packet_dump (vat_main_t * vam)
11803 {
11804   vl_api_af_packet_dump_t *mp;
11805   vl_api_control_ping_t *mp_ping;
11806   int ret;
11807
11808   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
11809   /* Get list of tap interfaces */
11810   M (AF_PACKET_DUMP, mp);
11811   S (mp);
11812
11813   /* Use a control ping for synchronization */
11814   MPING (CONTROL_PING, mp_ping);
11815   S (mp_ping);
11816
11817   W (ret);
11818   return ret;
11819 }
11820
11821 static int
11822 api_policer_add_del (vat_main_t * vam)
11823 {
11824   unformat_input_t *i = vam->input;
11825   vl_api_policer_add_del_t *mp;
11826   u8 is_add = 1;
11827   u8 *name = 0;
11828   u32 cir = 0;
11829   u32 eir = 0;
11830   u64 cb = 0;
11831   u64 eb = 0;
11832   u8 rate_type = 0;
11833   u8 round_type = 0;
11834   u8 type = 0;
11835   u8 color_aware = 0;
11836   sse2_qos_pol_action_params_st conform_action, exceed_action, violate_action;
11837   int ret;
11838
11839   conform_action.action_type = SSE2_QOS_ACTION_TRANSMIT;
11840   conform_action.dscp = 0;
11841   exceed_action.action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
11842   exceed_action.dscp = 0;
11843   violate_action.action_type = SSE2_QOS_ACTION_DROP;
11844   violate_action.dscp = 0;
11845
11846   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11847     {
11848       if (unformat (i, "del"))
11849         is_add = 0;
11850       else if (unformat (i, "name %s", &name))
11851         vec_add1 (name, 0);
11852       else if (unformat (i, "cir %u", &cir))
11853         ;
11854       else if (unformat (i, "eir %u", &eir))
11855         ;
11856       else if (unformat (i, "cb %u", &cb))
11857         ;
11858       else if (unformat (i, "eb %u", &eb))
11859         ;
11860       else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
11861                          &rate_type))
11862         ;
11863       else if (unformat (i, "round_type %U", unformat_policer_round_type,
11864                          &round_type))
11865         ;
11866       else if (unformat (i, "type %U", unformat_policer_type, &type))
11867         ;
11868       else if (unformat (i, "conform_action %U", unformat_policer_action_type,
11869                          &conform_action))
11870         ;
11871       else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
11872                          &exceed_action))
11873         ;
11874       else if (unformat (i, "violate_action %U", unformat_policer_action_type,
11875                          &violate_action))
11876         ;
11877       else if (unformat (i, "color-aware"))
11878         color_aware = 1;
11879       else
11880         break;
11881     }
11882
11883   if (!vec_len (name))
11884     {
11885       errmsg ("policer name must be specified");
11886       return -99;
11887     }
11888
11889   if (vec_len (name) > 64)
11890     {
11891       errmsg ("policer name too long");
11892       return -99;
11893     }
11894
11895   M (POLICER_ADD_DEL, mp);
11896
11897   clib_memcpy (mp->name, name, vec_len (name));
11898   vec_free (name);
11899   mp->is_add = is_add;
11900   mp->cir = ntohl (cir);
11901   mp->eir = ntohl (eir);
11902   mp->cb = clib_net_to_host_u64 (cb);
11903   mp->eb = clib_net_to_host_u64 (eb);
11904   mp->rate_type = rate_type;
11905   mp->round_type = round_type;
11906   mp->type = type;
11907   mp->conform_action.type = conform_action.action_type;
11908   mp->conform_action.dscp = conform_action.dscp;
11909   mp->exceed_action.type = exceed_action.action_type;
11910   mp->exceed_action.dscp = exceed_action.dscp;
11911   mp->violate_action.type = violate_action.action_type;
11912   mp->violate_action.dscp = violate_action.dscp;
11913   mp->color_aware = color_aware;
11914
11915   S (mp);
11916   W (ret);
11917   return ret;
11918 }
11919
11920 static int
11921 api_policer_dump (vat_main_t * vam)
11922 {
11923   unformat_input_t *i = vam->input;
11924   vl_api_policer_dump_t *mp;
11925   vl_api_control_ping_t *mp_ping;
11926   u8 *match_name = 0;
11927   u8 match_name_valid = 0;
11928   int ret;
11929
11930   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11931     {
11932       if (unformat (i, "name %s", &match_name))
11933         {
11934           vec_add1 (match_name, 0);
11935           match_name_valid = 1;
11936         }
11937       else
11938         break;
11939     }
11940
11941   M (POLICER_DUMP, mp);
11942   mp->match_name_valid = match_name_valid;
11943   clib_memcpy (mp->match_name, match_name, vec_len (match_name));
11944   vec_free (match_name);
11945   /* send it... */
11946   S (mp);
11947
11948   /* Use a control ping for synchronization */
11949   MPING (CONTROL_PING, mp_ping);
11950   S (mp_ping);
11951
11952   /* Wait for a reply... */
11953   W (ret);
11954   return ret;
11955 }
11956
11957 static int
11958 api_policer_classify_set_interface (vat_main_t * vam)
11959 {
11960   unformat_input_t *i = vam->input;
11961   vl_api_policer_classify_set_interface_t *mp;
11962   u32 sw_if_index;
11963   int sw_if_index_set;
11964   u32 ip4_table_index = ~0;
11965   u32 ip6_table_index = ~0;
11966   u32 l2_table_index = ~0;
11967   u8 is_add = 1;
11968   int ret;
11969
11970   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11971     {
11972       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11973         sw_if_index_set = 1;
11974       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11975         sw_if_index_set = 1;
11976       else if (unformat (i, "del"))
11977         is_add = 0;
11978       else if (unformat (i, "ip4-table %d", &ip4_table_index))
11979         ;
11980       else if (unformat (i, "ip6-table %d", &ip6_table_index))
11981         ;
11982       else if (unformat (i, "l2-table %d", &l2_table_index))
11983         ;
11984       else
11985         {
11986           clib_warning ("parse error '%U'", format_unformat_error, i);
11987           return -99;
11988         }
11989     }
11990
11991   if (sw_if_index_set == 0)
11992     {
11993       errmsg ("missing interface name or sw_if_index");
11994       return -99;
11995     }
11996
11997   M (POLICER_CLASSIFY_SET_INTERFACE, mp);
11998
11999   mp->sw_if_index = ntohl (sw_if_index);
12000   mp->ip4_table_index = ntohl (ip4_table_index);
12001   mp->ip6_table_index = ntohl (ip6_table_index);
12002   mp->l2_table_index = ntohl (l2_table_index);
12003   mp->is_add = is_add;
12004
12005   S (mp);
12006   W (ret);
12007   return ret;
12008 }
12009
12010 static int
12011 api_policer_classify_dump (vat_main_t * vam)
12012 {
12013   unformat_input_t *i = vam->input;
12014   vl_api_policer_classify_dump_t *mp;
12015   vl_api_control_ping_t *mp_ping;
12016   u8 type = POLICER_CLASSIFY_N_TABLES;
12017   int ret;
12018
12019   if (unformat (i, "type %U", unformat_policer_classify_table_type, &type))
12020     ;
12021   else
12022     {
12023       errmsg ("classify table type must be specified");
12024       return -99;
12025     }
12026
12027   if (!vam->json_output)
12028     {
12029       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
12030     }
12031
12032   M (POLICER_CLASSIFY_DUMP, mp);
12033   mp->type = type;
12034   /* send it... */
12035   S (mp);
12036
12037   /* Use a control ping for synchronization */
12038   MPING (CONTROL_PING, mp_ping);
12039   S (mp_ping);
12040
12041   /* Wait for a reply... */
12042   W (ret);
12043   return ret;
12044 }
12045
12046 static u8 *
12047 format_fib_api_path_nh_proto (u8 * s, va_list * args)
12048 {
12049   vl_api_fib_path_nh_proto_t proto =
12050     va_arg (*args, vl_api_fib_path_nh_proto_t);
12051
12052   switch (proto)
12053     {
12054     case FIB_API_PATH_NH_PROTO_IP4:
12055       s = format (s, "ip4");
12056       break;
12057     case FIB_API_PATH_NH_PROTO_IP6:
12058       s = format (s, "ip6");
12059       break;
12060     case FIB_API_PATH_NH_PROTO_MPLS:
12061       s = format (s, "mpls");
12062       break;
12063     case FIB_API_PATH_NH_PROTO_BIER:
12064       s = format (s, "bier");
12065       break;
12066     case FIB_API_PATH_NH_PROTO_ETHERNET:
12067       s = format (s, "ethernet");
12068       break;
12069     }
12070
12071   return (s);
12072 }
12073
12074 static u8 *
12075 format_vl_api_ip_address_union (u8 * s, va_list * args)
12076 {
12077   vl_api_address_family_t af = va_arg (*args, int);
12078   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
12079
12080   switch (af)
12081     {
12082     case ADDRESS_IP4:
12083       s = format (s, "%U", format_ip4_address, u->ip4);
12084       break;
12085     case ADDRESS_IP6:
12086       s = format (s, "%U", format_ip6_address, u->ip6);
12087       break;
12088     }
12089   return (s);
12090 }
12091
12092 static u8 *
12093 format_vl_api_fib_path_type (u8 * s, va_list * args)
12094 {
12095   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
12096
12097   switch (t)
12098     {
12099     case FIB_API_PATH_TYPE_NORMAL:
12100       s = format (s, "normal");
12101       break;
12102     case FIB_API_PATH_TYPE_LOCAL:
12103       s = format (s, "local");
12104       break;
12105     case FIB_API_PATH_TYPE_DROP:
12106       s = format (s, "drop");
12107       break;
12108     case FIB_API_PATH_TYPE_UDP_ENCAP:
12109       s = format (s, "udp-encap");
12110       break;
12111     case FIB_API_PATH_TYPE_BIER_IMP:
12112       s = format (s, "bier-imp");
12113       break;
12114     case FIB_API_PATH_TYPE_ICMP_UNREACH:
12115       s = format (s, "unreach");
12116       break;
12117     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
12118       s = format (s, "prohibit");
12119       break;
12120     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
12121       s = format (s, "src-lookup");
12122       break;
12123     case FIB_API_PATH_TYPE_DVR:
12124       s = format (s, "dvr");
12125       break;
12126     case FIB_API_PATH_TYPE_INTERFACE_RX:
12127       s = format (s, "interface-rx");
12128       break;
12129     case FIB_API_PATH_TYPE_CLASSIFY:
12130       s = format (s, "classify");
12131       break;
12132     }
12133
12134   return (s);
12135 }
12136
12137 static void
12138 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
12139 {
12140   print (vam->ofp,
12141          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
12142          ntohl (fp->weight), ntohl (fp->sw_if_index),
12143          format_vl_api_fib_path_type, fp->type,
12144          format_fib_api_path_nh_proto, fp->proto,
12145          format_vl_api_ip_address_union, &fp->nh.address);
12146 }
12147
12148 static void
12149 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
12150                                  vl_api_fib_path_t * fp)
12151 {
12152   struct in_addr ip4;
12153   struct in6_addr ip6;
12154
12155   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
12156   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
12157   vat_json_object_add_uint (node, "type", fp->type);
12158   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
12159   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
12160     {
12161       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
12162       vat_json_object_add_ip4 (node, "next_hop", ip4);
12163     }
12164   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
12165     {
12166       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
12167       vat_json_object_add_ip6 (node, "next_hop", ip6);
12168     }
12169 }
12170
12171 static void
12172 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
12173 {
12174   vat_main_t *vam = &vat_main;
12175   int count = ntohl (mp->mt_tunnel.mt_n_paths);
12176   vl_api_fib_path_t *fp;
12177   i32 i;
12178
12179   print (vam->ofp, "sw_if_index %d via:",
12180          ntohl (mp->mt_tunnel.mt_sw_if_index));
12181   fp = mp->mt_tunnel.mt_paths;
12182   for (i = 0; i < count; i++)
12183     {
12184       vl_api_fib_path_print (vam, fp);
12185       fp++;
12186     }
12187
12188   print (vam->ofp, "");
12189 }
12190
12191 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
12192 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
12193
12194 static void
12195 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
12196 {
12197   vat_main_t *vam = &vat_main;
12198   vat_json_node_t *node = NULL;
12199   int count = ntohl (mp->mt_tunnel.mt_n_paths);
12200   vl_api_fib_path_t *fp;
12201   i32 i;
12202
12203   if (VAT_JSON_ARRAY != vam->json_tree.type)
12204     {
12205       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12206       vat_json_init_array (&vam->json_tree);
12207     }
12208   node = vat_json_array_add (&vam->json_tree);
12209
12210   vat_json_init_object (node);
12211   vat_json_object_add_uint (node, "sw_if_index",
12212                             ntohl (mp->mt_tunnel.mt_sw_if_index));
12213
12214   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
12215
12216   fp = mp->mt_tunnel.mt_paths;
12217   for (i = 0; i < count; i++)
12218     {
12219       vl_api_mpls_fib_path_json_print (node, fp);
12220       fp++;
12221     }
12222 }
12223
12224 static int
12225 api_mpls_tunnel_dump (vat_main_t * vam)
12226 {
12227   vl_api_mpls_tunnel_dump_t *mp;
12228   vl_api_control_ping_t *mp_ping;
12229   int ret;
12230
12231   M (MPLS_TUNNEL_DUMP, mp);
12232
12233   S (mp);
12234
12235   /* Use a control ping for synchronization */
12236   MPING (CONTROL_PING, mp_ping);
12237   S (mp_ping);
12238
12239   W (ret);
12240   return ret;
12241 }
12242
12243 #define vl_api_mpls_table_details_t_endian vl_noop_handler
12244 #define vl_api_mpls_table_details_t_print vl_noop_handler
12245
12246
12247 static void
12248 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
12249 {
12250   vat_main_t *vam = &vat_main;
12251
12252   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
12253 }
12254
12255 static void vl_api_mpls_table_details_t_handler_json
12256   (vl_api_mpls_table_details_t * mp)
12257 {
12258   vat_main_t *vam = &vat_main;
12259   vat_json_node_t *node = NULL;
12260
12261   if (VAT_JSON_ARRAY != vam->json_tree.type)
12262     {
12263       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12264       vat_json_init_array (&vam->json_tree);
12265     }
12266   node = vat_json_array_add (&vam->json_tree);
12267
12268   vat_json_init_object (node);
12269   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
12270 }
12271
12272 static int
12273 api_mpls_table_dump (vat_main_t * vam)
12274 {
12275   vl_api_mpls_table_dump_t *mp;
12276   vl_api_control_ping_t *mp_ping;
12277   int ret;
12278
12279   M (MPLS_TABLE_DUMP, mp);
12280   S (mp);
12281
12282   /* Use a control ping for synchronization */
12283   MPING (CONTROL_PING, mp_ping);
12284   S (mp_ping);
12285
12286   W (ret);
12287   return ret;
12288 }
12289
12290 #define vl_api_mpls_route_details_t_endian vl_noop_handler
12291 #define vl_api_mpls_route_details_t_print vl_noop_handler
12292
12293 static void
12294 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
12295 {
12296   vat_main_t *vam = &vat_main;
12297   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
12298   vl_api_fib_path_t *fp;
12299   int i;
12300
12301   print (vam->ofp,
12302          "table-id %d, label %u, ess_bit %u",
12303          ntohl (mp->mr_route.mr_table_id),
12304          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
12305   fp = mp->mr_route.mr_paths;
12306   for (i = 0; i < count; i++)
12307     {
12308       vl_api_fib_path_print (vam, fp);
12309       fp++;
12310     }
12311 }
12312
12313 static void vl_api_mpls_route_details_t_handler_json
12314   (vl_api_mpls_route_details_t * mp)
12315 {
12316   vat_main_t *vam = &vat_main;
12317   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
12318   vat_json_node_t *node = NULL;
12319   vl_api_fib_path_t *fp;
12320   int i;
12321
12322   if (VAT_JSON_ARRAY != vam->json_tree.type)
12323     {
12324       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12325       vat_json_init_array (&vam->json_tree);
12326     }
12327   node = vat_json_array_add (&vam->json_tree);
12328
12329   vat_json_init_object (node);
12330   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
12331   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
12332   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
12333   vat_json_object_add_uint (node, "path_count", count);
12334   fp = mp->mr_route.mr_paths;
12335   for (i = 0; i < count; i++)
12336     {
12337       vl_api_mpls_fib_path_json_print (node, fp);
12338       fp++;
12339     }
12340 }
12341
12342 static int
12343 api_mpls_route_dump (vat_main_t * vam)
12344 {
12345   unformat_input_t *input = vam->input;
12346   vl_api_mpls_route_dump_t *mp;
12347   vl_api_control_ping_t *mp_ping;
12348   u32 table_id;
12349   int ret;
12350
12351   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12352     {
12353       if (unformat (input, "table_id %d", &table_id))
12354         ;
12355       else
12356         break;
12357     }
12358   if (table_id == ~0)
12359     {
12360       errmsg ("missing table id");
12361       return -99;
12362     }
12363
12364   M (MPLS_ROUTE_DUMP, mp);
12365
12366   mp->table.mt_table_id = ntohl (table_id);
12367   S (mp);
12368
12369   /* Use a control ping for synchronization */
12370   MPING (CONTROL_PING, mp_ping);
12371   S (mp_ping);
12372
12373   W (ret);
12374   return ret;
12375 }
12376
12377 #define vl_api_ip_table_details_t_endian vl_noop_handler
12378 #define vl_api_ip_table_details_t_print vl_noop_handler
12379
12380 static void
12381 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
12382 {
12383   vat_main_t *vam = &vat_main;
12384
12385   print (vam->ofp,
12386          "%s; table-id %d, prefix %U/%d",
12387          mp->table.name, ntohl (mp->table.table_id));
12388 }
12389
12390
12391 static void vl_api_ip_table_details_t_handler_json
12392   (vl_api_ip_table_details_t * mp)
12393 {
12394   vat_main_t *vam = &vat_main;
12395   vat_json_node_t *node = NULL;
12396
12397   if (VAT_JSON_ARRAY != vam->json_tree.type)
12398     {
12399       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12400       vat_json_init_array (&vam->json_tree);
12401     }
12402   node = vat_json_array_add (&vam->json_tree);
12403
12404   vat_json_init_object (node);
12405   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
12406 }
12407
12408 static int
12409 api_ip_table_dump (vat_main_t * vam)
12410 {
12411   vl_api_ip_table_dump_t *mp;
12412   vl_api_control_ping_t *mp_ping;
12413   int ret;
12414
12415   M (IP_TABLE_DUMP, mp);
12416   S (mp);
12417
12418   /* Use a control ping for synchronization */
12419   MPING (CONTROL_PING, mp_ping);
12420   S (mp_ping);
12421
12422   W (ret);
12423   return ret;
12424 }
12425
12426 static int
12427 api_ip_mtable_dump (vat_main_t * vam)
12428 {
12429   vl_api_ip_mtable_dump_t *mp;
12430   vl_api_control_ping_t *mp_ping;
12431   int ret;
12432
12433   M (IP_MTABLE_DUMP, mp);
12434   S (mp);
12435
12436   /* Use a control ping for synchronization */
12437   MPING (CONTROL_PING, mp_ping);
12438   S (mp_ping);
12439
12440   W (ret);
12441   return ret;
12442 }
12443
12444 static int
12445 api_ip_mroute_dump (vat_main_t * vam)
12446 {
12447   unformat_input_t *input = vam->input;
12448   vl_api_control_ping_t *mp_ping;
12449   vl_api_ip_mroute_dump_t *mp;
12450   int ret, is_ip6;
12451   u32 table_id;
12452
12453   is_ip6 = 0;
12454   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12455     {
12456       if (unformat (input, "table_id %d", &table_id))
12457         ;
12458       else if (unformat (input, "ip6"))
12459         is_ip6 = 1;
12460       else if (unformat (input, "ip4"))
12461         is_ip6 = 0;
12462       else
12463         break;
12464     }
12465   if (table_id == ~0)
12466     {
12467       errmsg ("missing table id");
12468       return -99;
12469     }
12470
12471   M (IP_MROUTE_DUMP, mp);
12472   mp->table.table_id = table_id;
12473   mp->table.is_ip6 = is_ip6;
12474   S (mp);
12475
12476   /* Use a control ping for synchronization */
12477   MPING (CONTROL_PING, mp_ping);
12478   S (mp_ping);
12479
12480   W (ret);
12481   return ret;
12482 }
12483
12484 #define vl_api_ip_route_details_t_endian vl_noop_handler
12485 #define vl_api_ip_route_details_t_print vl_noop_handler
12486
12487 static void
12488 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
12489 {
12490   vat_main_t *vam = &vat_main;
12491   u8 count = mp->route.n_paths;
12492   vl_api_fib_path_t *fp;
12493   int i;
12494
12495   print (vam->ofp,
12496          "table-id %d, prefix %U/%d",
12497          ntohl (mp->route.table_id),
12498          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
12499   for (i = 0; i < count; i++)
12500     {
12501       fp = &mp->route.paths[i];
12502
12503       vl_api_fib_path_print (vam, fp);
12504       fp++;
12505     }
12506 }
12507
12508 static void vl_api_ip_route_details_t_handler_json
12509   (vl_api_ip_route_details_t * mp)
12510 {
12511   vat_main_t *vam = &vat_main;
12512   u8 count = mp->route.n_paths;
12513   vat_json_node_t *node = NULL;
12514   struct in_addr ip4;
12515   struct in6_addr ip6;
12516   vl_api_fib_path_t *fp;
12517   int i;
12518
12519   if (VAT_JSON_ARRAY != vam->json_tree.type)
12520     {
12521       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12522       vat_json_init_array (&vam->json_tree);
12523     }
12524   node = vat_json_array_add (&vam->json_tree);
12525
12526   vat_json_init_object (node);
12527   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
12528   if (ADDRESS_IP6 == mp->route.prefix.address.af)
12529     {
12530       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
12531       vat_json_object_add_ip6 (node, "prefix", ip6);
12532     }
12533   else
12534     {
12535       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
12536       vat_json_object_add_ip4 (node, "prefix", ip4);
12537     }
12538   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
12539   vat_json_object_add_uint (node, "path_count", count);
12540   for (i = 0; i < count; i++)
12541     {
12542       fp = &mp->route.paths[i];
12543       vl_api_mpls_fib_path_json_print (node, fp);
12544     }
12545 }
12546
12547 static int
12548 api_ip_route_dump (vat_main_t * vam)
12549 {
12550   unformat_input_t *input = vam->input;
12551   vl_api_ip_route_dump_t *mp;
12552   vl_api_control_ping_t *mp_ping;
12553   u32 table_id;
12554   u8 is_ip6;
12555   int ret;
12556
12557   is_ip6 = 0;
12558   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12559     {
12560       if (unformat (input, "table_id %d", &table_id))
12561         ;
12562       else if (unformat (input, "ip6"))
12563         is_ip6 = 1;
12564       else if (unformat (input, "ip4"))
12565         is_ip6 = 0;
12566       else
12567         break;
12568     }
12569   if (table_id == ~0)
12570     {
12571       errmsg ("missing table id");
12572       return -99;
12573     }
12574
12575   M (IP_ROUTE_DUMP, mp);
12576
12577   mp->table.table_id = table_id;
12578   mp->table.is_ip6 = is_ip6;
12579
12580   S (mp);
12581
12582   /* Use a control ping for synchronization */
12583   MPING (CONTROL_PING, mp_ping);
12584   S (mp_ping);
12585
12586   W (ret);
12587   return ret;
12588 }
12589
12590 int
12591 api_classify_table_ids (vat_main_t * vam)
12592 {
12593   vl_api_classify_table_ids_t *mp;
12594   int ret;
12595
12596   /* Construct the API message */
12597   M (CLASSIFY_TABLE_IDS, mp);
12598   mp->context = 0;
12599
12600   S (mp);
12601   W (ret);
12602   return ret;
12603 }
12604
12605 int
12606 api_classify_table_by_interface (vat_main_t * vam)
12607 {
12608   unformat_input_t *input = vam->input;
12609   vl_api_classify_table_by_interface_t *mp;
12610
12611   u32 sw_if_index = ~0;
12612   int ret;
12613   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12614     {
12615       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
12616         ;
12617       else if (unformat (input, "sw_if_index %d", &sw_if_index))
12618         ;
12619       else
12620         break;
12621     }
12622   if (sw_if_index == ~0)
12623     {
12624       errmsg ("missing interface name or sw_if_index");
12625       return -99;
12626     }
12627
12628   /* Construct the API message */
12629   M (CLASSIFY_TABLE_BY_INTERFACE, mp);
12630   mp->context = 0;
12631   mp->sw_if_index = ntohl (sw_if_index);
12632
12633   S (mp);
12634   W (ret);
12635   return ret;
12636 }
12637
12638 int
12639 api_classify_table_info (vat_main_t * vam)
12640 {
12641   unformat_input_t *input = vam->input;
12642   vl_api_classify_table_info_t *mp;
12643
12644   u32 table_id = ~0;
12645   int ret;
12646   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12647     {
12648       if (unformat (input, "table_id %d", &table_id))
12649         ;
12650       else
12651         break;
12652     }
12653   if (table_id == ~0)
12654     {
12655       errmsg ("missing table id");
12656       return -99;
12657     }
12658
12659   /* Construct the API message */
12660   M (CLASSIFY_TABLE_INFO, mp);
12661   mp->context = 0;
12662   mp->table_id = ntohl (table_id);
12663
12664   S (mp);
12665   W (ret);
12666   return ret;
12667 }
12668
12669 int
12670 api_classify_session_dump (vat_main_t * vam)
12671 {
12672   unformat_input_t *input = vam->input;
12673   vl_api_classify_session_dump_t *mp;
12674   vl_api_control_ping_t *mp_ping;
12675
12676   u32 table_id = ~0;
12677   int ret;
12678   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12679     {
12680       if (unformat (input, "table_id %d", &table_id))
12681         ;
12682       else
12683         break;
12684     }
12685   if (table_id == ~0)
12686     {
12687       errmsg ("missing table id");
12688       return -99;
12689     }
12690
12691   /* Construct the API message */
12692   M (CLASSIFY_SESSION_DUMP, mp);
12693   mp->context = 0;
12694   mp->table_id = ntohl (table_id);
12695   S (mp);
12696
12697   /* Use a control ping for synchronization */
12698   MPING (CONTROL_PING, mp_ping);
12699   S (mp_ping);
12700
12701   W (ret);
12702   return ret;
12703 }
12704
12705 static void
12706 vl_api_ipfix_exporter_details_t_handler (vl_api_ipfix_exporter_details_t * mp)
12707 {
12708   vat_main_t *vam = &vat_main;
12709
12710   print (vam->ofp, "collector_address %U, collector_port %d, "
12711          "src_address %U, vrf_id %d, path_mtu %u, "
12712          "template_interval %u, udp_checksum %d",
12713          format_ip4_address, mp->collector_address,
12714          ntohs (mp->collector_port),
12715          format_ip4_address, mp->src_address,
12716          ntohl (mp->vrf_id), ntohl (mp->path_mtu),
12717          ntohl (mp->template_interval), mp->udp_checksum);
12718
12719   vam->retval = 0;
12720   vam->result_ready = 1;
12721 }
12722
12723 static void
12724   vl_api_ipfix_exporter_details_t_handler_json
12725   (vl_api_ipfix_exporter_details_t * mp)
12726 {
12727   vat_main_t *vam = &vat_main;
12728   vat_json_node_t node;
12729   struct in_addr collector_address;
12730   struct in_addr src_address;
12731
12732   vat_json_init_object (&node);
12733   clib_memcpy (&collector_address, &mp->collector_address,
12734                sizeof (collector_address));
12735   vat_json_object_add_ip4 (&node, "collector_address", collector_address);
12736   vat_json_object_add_uint (&node, "collector_port",
12737                             ntohs (mp->collector_port));
12738   clib_memcpy (&src_address, &mp->src_address, sizeof (src_address));
12739   vat_json_object_add_ip4 (&node, "src_address", src_address);
12740   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
12741   vat_json_object_add_uint (&node, "path_mtu", ntohl (mp->path_mtu));
12742   vat_json_object_add_uint (&node, "template_interval",
12743                             ntohl (mp->template_interval));
12744   vat_json_object_add_int (&node, "udp_checksum", mp->udp_checksum);
12745
12746   vat_json_print (vam->ofp, &node);
12747   vat_json_free (&node);
12748   vam->retval = 0;
12749   vam->result_ready = 1;
12750 }
12751
12752 int
12753 api_ipfix_exporter_dump (vat_main_t * vam)
12754 {
12755   vl_api_ipfix_exporter_dump_t *mp;
12756   int ret;
12757
12758   /* Construct the API message */
12759   M (IPFIX_EXPORTER_DUMP, mp);
12760   mp->context = 0;
12761
12762   S (mp);
12763   W (ret);
12764   return ret;
12765 }
12766
12767 static int
12768 api_ipfix_classify_stream_dump (vat_main_t * vam)
12769 {
12770   vl_api_ipfix_classify_stream_dump_t *mp;
12771   int ret;
12772
12773   /* Construct the API message */
12774   M (IPFIX_CLASSIFY_STREAM_DUMP, mp);
12775   mp->context = 0;
12776
12777   S (mp);
12778   W (ret);
12779   return ret;
12780   /* NOTREACHED */
12781   return 0;
12782 }
12783
12784 static void
12785   vl_api_ipfix_classify_stream_details_t_handler
12786   (vl_api_ipfix_classify_stream_details_t * mp)
12787 {
12788   vat_main_t *vam = &vat_main;
12789   print (vam->ofp, "domain_id %d, src_port %d",
12790          ntohl (mp->domain_id), ntohs (mp->src_port));
12791   vam->retval = 0;
12792   vam->result_ready = 1;
12793 }
12794
12795 static void
12796   vl_api_ipfix_classify_stream_details_t_handler_json
12797   (vl_api_ipfix_classify_stream_details_t * mp)
12798 {
12799   vat_main_t *vam = &vat_main;
12800   vat_json_node_t node;
12801
12802   vat_json_init_object (&node);
12803   vat_json_object_add_uint (&node, "domain_id", ntohl (mp->domain_id));
12804   vat_json_object_add_uint (&node, "src_port", ntohs (mp->src_port));
12805
12806   vat_json_print (vam->ofp, &node);
12807   vat_json_free (&node);
12808   vam->retval = 0;
12809   vam->result_ready = 1;
12810 }
12811
12812 static int
12813 api_ipfix_classify_table_dump (vat_main_t * vam)
12814 {
12815   vl_api_ipfix_classify_table_dump_t *mp;
12816   vl_api_control_ping_t *mp_ping;
12817   int ret;
12818
12819   if (!vam->json_output)
12820     {
12821       print (vam->ofp, "%15s%15s%20s", "table_id", "ip_version",
12822              "transport_protocol");
12823     }
12824
12825   /* Construct the API message */
12826   M (IPFIX_CLASSIFY_TABLE_DUMP, mp);
12827
12828   /* send it... */
12829   S (mp);
12830
12831   /* Use a control ping for synchronization */
12832   MPING (CONTROL_PING, mp_ping);
12833   S (mp_ping);
12834
12835   W (ret);
12836   return ret;
12837 }
12838
12839 static void
12840   vl_api_ipfix_classify_table_details_t_handler
12841   (vl_api_ipfix_classify_table_details_t * mp)
12842 {
12843   vat_main_t *vam = &vat_main;
12844   print (vam->ofp, "%15d%15d%20d", ntohl (mp->table_id), mp->ip_version,
12845          mp->transport_protocol);
12846 }
12847
12848 static void
12849   vl_api_ipfix_classify_table_details_t_handler_json
12850   (vl_api_ipfix_classify_table_details_t * mp)
12851 {
12852   vat_json_node_t *node = NULL;
12853   vat_main_t *vam = &vat_main;
12854
12855   if (VAT_JSON_ARRAY != vam->json_tree.type)
12856     {
12857       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12858       vat_json_init_array (&vam->json_tree);
12859     }
12860
12861   node = vat_json_array_add (&vam->json_tree);
12862   vat_json_init_object (node);
12863
12864   vat_json_object_add_uint (node, "table_id", ntohl (mp->table_id));
12865   vat_json_object_add_uint (node, "ip_version", mp->ip_version);
12866   vat_json_object_add_uint (node, "transport_protocol",
12867                             mp->transport_protocol);
12868 }
12869
12870 static int
12871 api_sw_interface_span_enable_disable (vat_main_t * vam)
12872 {
12873   unformat_input_t *i = vam->input;
12874   vl_api_sw_interface_span_enable_disable_t *mp;
12875   u32 src_sw_if_index = ~0;
12876   u32 dst_sw_if_index = ~0;
12877   u8 state = 3;
12878   int ret;
12879   u8 is_l2 = 0;
12880
12881   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12882     {
12883       if (unformat
12884           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
12885         ;
12886       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
12887         ;
12888       else
12889         if (unformat
12890             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
12891         ;
12892       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
12893         ;
12894       else if (unformat (i, "disable"))
12895         state = 0;
12896       else if (unformat (i, "rx"))
12897         state = 1;
12898       else if (unformat (i, "tx"))
12899         state = 2;
12900       else if (unformat (i, "both"))
12901         state = 3;
12902       else if (unformat (i, "l2"))
12903         is_l2 = 1;
12904       else
12905         break;
12906     }
12907
12908   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
12909
12910   mp->sw_if_index_from = htonl (src_sw_if_index);
12911   mp->sw_if_index_to = htonl (dst_sw_if_index);
12912   mp->state = state;
12913   mp->is_l2 = is_l2;
12914
12915   S (mp);
12916   W (ret);
12917   return ret;
12918 }
12919
12920 static void
12921 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
12922                                             * mp)
12923 {
12924   vat_main_t *vam = &vat_main;
12925   u8 *sw_if_from_name = 0;
12926   u8 *sw_if_to_name = 0;
12927   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12928   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12929   char *states[] = { "none", "rx", "tx", "both" };
12930   hash_pair_t *p;
12931
12932   /* *INDENT-OFF* */
12933   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12934   ({
12935     if ((u32) p->value[0] == sw_if_index_from)
12936       {
12937         sw_if_from_name = (u8 *)(p->key);
12938         if (sw_if_to_name)
12939           break;
12940       }
12941     if ((u32) p->value[0] == sw_if_index_to)
12942       {
12943         sw_if_to_name = (u8 *)(p->key);
12944         if (sw_if_from_name)
12945           break;
12946       }
12947   }));
12948   /* *INDENT-ON* */
12949   print (vam->ofp, "%20s => %20s (%s) %s",
12950          sw_if_from_name, sw_if_to_name, states[mp->state],
12951          mp->is_l2 ? "l2" : "device");
12952 }
12953
12954 static void
12955   vl_api_sw_interface_span_details_t_handler_json
12956   (vl_api_sw_interface_span_details_t * mp)
12957 {
12958   vat_main_t *vam = &vat_main;
12959   vat_json_node_t *node = NULL;
12960   u8 *sw_if_from_name = 0;
12961   u8 *sw_if_to_name = 0;
12962   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12963   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12964   hash_pair_t *p;
12965
12966   /* *INDENT-OFF* */
12967   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12968   ({
12969     if ((u32) p->value[0] == sw_if_index_from)
12970       {
12971         sw_if_from_name = (u8 *)(p->key);
12972         if (sw_if_to_name)
12973           break;
12974       }
12975     if ((u32) p->value[0] == sw_if_index_to)
12976       {
12977         sw_if_to_name = (u8 *)(p->key);
12978         if (sw_if_from_name)
12979           break;
12980       }
12981   }));
12982   /* *INDENT-ON* */
12983
12984   if (VAT_JSON_ARRAY != vam->json_tree.type)
12985     {
12986       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12987       vat_json_init_array (&vam->json_tree);
12988     }
12989   node = vat_json_array_add (&vam->json_tree);
12990
12991   vat_json_init_object (node);
12992   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
12993   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
12994   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
12995   if (0 != sw_if_to_name)
12996     {
12997       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
12998     }
12999   vat_json_object_add_uint (node, "state", mp->state);
13000   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
13001 }
13002
13003 static int
13004 api_sw_interface_span_dump (vat_main_t * vam)
13005 {
13006   unformat_input_t *input = vam->input;
13007   vl_api_sw_interface_span_dump_t *mp;
13008   vl_api_control_ping_t *mp_ping;
13009   u8 is_l2 = 0;
13010   int ret;
13011
13012   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13013     {
13014       if (unformat (input, "l2"))
13015         is_l2 = 1;
13016       else
13017         break;
13018     }
13019
13020   M (SW_INTERFACE_SPAN_DUMP, mp);
13021   mp->is_l2 = is_l2;
13022   S (mp);
13023
13024   /* Use a control ping for synchronization */
13025   MPING (CONTROL_PING, mp_ping);
13026   S (mp_ping);
13027
13028   W (ret);
13029   return ret;
13030 }
13031
13032 int
13033 api_pg_create_interface (vat_main_t * vam)
13034 {
13035   unformat_input_t *input = vam->input;
13036   vl_api_pg_create_interface_t *mp;
13037
13038   u32 if_id = ~0, gso_size = 0;
13039   u8 gso_enabled = 0;
13040   int ret;
13041   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13042     {
13043       if (unformat (input, "if_id %d", &if_id))
13044         ;
13045       else if (unformat (input, "gso-enabled"))
13046         {
13047           gso_enabled = 1;
13048           if (unformat (input, "gso-size %u", &gso_size))
13049             ;
13050           else
13051             {
13052               errmsg ("missing gso-size");
13053               return -99;
13054             }
13055         }
13056       else
13057         break;
13058     }
13059   if (if_id == ~0)
13060     {
13061       errmsg ("missing pg interface index");
13062       return -99;
13063     }
13064
13065   /* Construct the API message */
13066   M (PG_CREATE_INTERFACE, mp);
13067   mp->context = 0;
13068   mp->interface_id = ntohl (if_id);
13069   mp->gso_enabled = gso_enabled;
13070
13071   S (mp);
13072   W (ret);
13073   return ret;
13074 }
13075
13076 int
13077 api_pg_capture (vat_main_t * vam)
13078 {
13079   unformat_input_t *input = vam->input;
13080   vl_api_pg_capture_t *mp;
13081
13082   u32 if_id = ~0;
13083   u8 enable = 1;
13084   u32 count = 1;
13085   u8 pcap_file_set = 0;
13086   u8 *pcap_file = 0;
13087   int ret;
13088   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13089     {
13090       if (unformat (input, "if_id %d", &if_id))
13091         ;
13092       else if (unformat (input, "pcap %s", &pcap_file))
13093         pcap_file_set = 1;
13094       else if (unformat (input, "count %d", &count))
13095         ;
13096       else if (unformat (input, "disable"))
13097         enable = 0;
13098       else
13099         break;
13100     }
13101   if (if_id == ~0)
13102     {
13103       errmsg ("missing pg interface index");
13104       return -99;
13105     }
13106   if (pcap_file_set > 0)
13107     {
13108       if (vec_len (pcap_file) > 255)
13109         {
13110           errmsg ("pcap file name is too long");
13111           return -99;
13112         }
13113     }
13114
13115   /* Construct the API message */
13116   M (PG_CAPTURE, mp);
13117   mp->context = 0;
13118   mp->interface_id = ntohl (if_id);
13119   mp->is_enabled = enable;
13120   mp->count = ntohl (count);
13121   if (pcap_file_set != 0)
13122     {
13123       vl_api_vec_to_api_string (pcap_file, &mp->pcap_file_name);
13124     }
13125   vec_free (pcap_file);
13126
13127   S (mp);
13128   W (ret);
13129   return ret;
13130 }
13131
13132 int
13133 api_pg_enable_disable (vat_main_t * vam)
13134 {
13135   unformat_input_t *input = vam->input;
13136   vl_api_pg_enable_disable_t *mp;
13137
13138   u8 enable = 1;
13139   u8 stream_name_set = 0;
13140   u8 *stream_name = 0;
13141   int ret;
13142   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13143     {
13144       if (unformat (input, "stream %s", &stream_name))
13145         stream_name_set = 1;
13146       else if (unformat (input, "disable"))
13147         enable = 0;
13148       else
13149         break;
13150     }
13151
13152   if (stream_name_set > 0)
13153     {
13154       if (vec_len (stream_name) > 255)
13155         {
13156           errmsg ("stream name too long");
13157           return -99;
13158         }
13159     }
13160
13161   /* Construct the API message */
13162   M (PG_ENABLE_DISABLE, mp);
13163   mp->context = 0;
13164   mp->is_enabled = enable;
13165   if (stream_name_set != 0)
13166     {
13167       vl_api_vec_to_api_string (stream_name, &mp->stream_name);
13168     }
13169   vec_free (stream_name);
13170
13171   S (mp);
13172   W (ret);
13173   return ret;
13174 }
13175
13176 int
13177 api_pg_interface_enable_disable_coalesce (vat_main_t * vam)
13178 {
13179   unformat_input_t *input = vam->input;
13180   vl_api_pg_interface_enable_disable_coalesce_t *mp;
13181
13182   u32 sw_if_index = ~0;
13183   u8 enable = 1;
13184   int ret;
13185   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13186     {
13187       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13188         ;
13189       else if (unformat (input, "sw_if_index %d", &sw_if_index))
13190         ;
13191       else if (unformat (input, "disable"))
13192         enable = 0;
13193       else
13194         break;
13195     }
13196
13197   if (sw_if_index == ~0)
13198     {
13199       errmsg ("Interface required but not specified");
13200       return -99;
13201     }
13202
13203   /* Construct the API message */
13204   M (PG_INTERFACE_ENABLE_DISABLE_COALESCE, mp);
13205   mp->context = 0;
13206   mp->coalesce_enabled = enable;
13207   mp->sw_if_index = htonl (sw_if_index);
13208
13209   S (mp);
13210   W (ret);
13211   return ret;
13212 }
13213
13214 int
13215 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
13216 {
13217   unformat_input_t *input = vam->input;
13218   vl_api_ip_source_and_port_range_check_add_del_t *mp;
13219
13220   u16 *low_ports = 0;
13221   u16 *high_ports = 0;
13222   u16 this_low;
13223   u16 this_hi;
13224   vl_api_prefix_t prefix;
13225   u32 tmp, tmp2;
13226   u8 prefix_set = 0;
13227   u32 vrf_id = ~0;
13228   u8 is_add = 1;
13229   int ret;
13230
13231   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13232     {
13233       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
13234         prefix_set = 1;
13235       else if (unformat (input, "vrf %d", &vrf_id))
13236         ;
13237       else if (unformat (input, "del"))
13238         is_add = 0;
13239       else if (unformat (input, "port %d", &tmp))
13240         {
13241           if (tmp == 0 || tmp > 65535)
13242             {
13243               errmsg ("port %d out of range", tmp);
13244               return -99;
13245             }
13246           this_low = tmp;
13247           this_hi = this_low + 1;
13248           vec_add1 (low_ports, this_low);
13249           vec_add1 (high_ports, this_hi);
13250         }
13251       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
13252         {
13253           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
13254             {
13255               errmsg ("incorrect range parameters");
13256               return -99;
13257             }
13258           this_low = tmp;
13259           /* Note: in debug CLI +1 is added to high before
13260              passing to real fn that does "the work"
13261              (ip_source_and_port_range_check_add_del).
13262              This fn is a wrapper around the binary API fn a
13263              control plane will call, which expects this increment
13264              to have occurred. Hence letting the binary API control
13265              plane fn do the increment for consistency between VAT
13266              and other control planes.
13267            */
13268           this_hi = tmp2;
13269           vec_add1 (low_ports, this_low);
13270           vec_add1 (high_ports, this_hi);
13271         }
13272       else
13273         break;
13274     }
13275
13276   if (prefix_set == 0)
13277     {
13278       errmsg ("<address>/<mask> not specified");
13279       return -99;
13280     }
13281
13282   if (vrf_id == ~0)
13283     {
13284       errmsg ("VRF ID required, not specified");
13285       return -99;
13286     }
13287
13288   if (vrf_id == 0)
13289     {
13290       errmsg
13291         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13292       return -99;
13293     }
13294
13295   if (vec_len (low_ports) == 0)
13296     {
13297       errmsg ("At least one port or port range required");
13298       return -99;
13299     }
13300
13301   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
13302
13303   mp->is_add = is_add;
13304
13305   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
13306
13307   mp->number_of_ranges = vec_len (low_ports);
13308
13309   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
13310   vec_free (low_ports);
13311
13312   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
13313   vec_free (high_ports);
13314
13315   mp->vrf_id = ntohl (vrf_id);
13316
13317   S (mp);
13318   W (ret);
13319   return ret;
13320 }
13321
13322 int
13323 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
13324 {
13325   unformat_input_t *input = vam->input;
13326   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
13327   u32 sw_if_index = ~0;
13328   int vrf_set = 0;
13329   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
13330   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
13331   u8 is_add = 1;
13332   int ret;
13333
13334   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13335     {
13336       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13337         ;
13338       else if (unformat (input, "sw_if_index %d", &sw_if_index))
13339         ;
13340       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
13341         vrf_set = 1;
13342       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
13343         vrf_set = 1;
13344       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
13345         vrf_set = 1;
13346       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
13347         vrf_set = 1;
13348       else if (unformat (input, "del"))
13349         is_add = 0;
13350       else
13351         break;
13352     }
13353
13354   if (sw_if_index == ~0)
13355     {
13356       errmsg ("Interface required but not specified");
13357       return -99;
13358     }
13359
13360   if (vrf_set == 0)
13361     {
13362       errmsg ("VRF ID required but not specified");
13363       return -99;
13364     }
13365
13366   if (tcp_out_vrf_id == 0
13367       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
13368     {
13369       errmsg
13370         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13371       return -99;
13372     }
13373
13374   /* Construct the API message */
13375   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
13376
13377   mp->sw_if_index = ntohl (sw_if_index);
13378   mp->is_add = is_add;
13379   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
13380   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
13381   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
13382   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
13383
13384   /* send it... */
13385   S (mp);
13386
13387   /* Wait for a reply... */
13388   W (ret);
13389   return ret;
13390 }
13391
13392 static int
13393 api_set_punt (vat_main_t * vam)
13394 {
13395   unformat_input_t *i = vam->input;
13396   vl_api_address_family_t af;
13397   vl_api_set_punt_t *mp;
13398   u32 protocol = ~0;
13399   u32 port = ~0;
13400   int is_add = 1;
13401   int ret;
13402
13403   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13404     {
13405       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
13406         ;
13407       else if (unformat (i, "protocol %d", &protocol))
13408         ;
13409       else if (unformat (i, "port %d", &port))
13410         ;
13411       else if (unformat (i, "del"))
13412         is_add = 0;
13413       else
13414         {
13415           clib_warning ("parse error '%U'", format_unformat_error, i);
13416           return -99;
13417         }
13418     }
13419
13420   M (SET_PUNT, mp);
13421
13422   mp->is_add = (u8) is_add;
13423   mp->punt.type = PUNT_API_TYPE_L4;
13424   mp->punt.punt.l4.af = af;
13425   mp->punt.punt.l4.protocol = (u8) protocol;
13426   mp->punt.punt.l4.port = htons ((u16) port);
13427
13428   S (mp);
13429   W (ret);
13430   return ret;
13431 }
13432
13433 static int
13434 api_delete_subif (vat_main_t * vam)
13435 {
13436   unformat_input_t *i = vam->input;
13437   vl_api_delete_subif_t *mp;
13438   u32 sw_if_index = ~0;
13439   int ret;
13440
13441   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13442     {
13443       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13444         ;
13445       if (unformat (i, "sw_if_index %d", &sw_if_index))
13446         ;
13447       else
13448         break;
13449     }
13450
13451   if (sw_if_index == ~0)
13452     {
13453       errmsg ("missing sw_if_index");
13454       return -99;
13455     }
13456
13457   /* Construct the API message */
13458   M (DELETE_SUBIF, mp);
13459   mp->sw_if_index = ntohl (sw_if_index);
13460
13461   S (mp);
13462   W (ret);
13463   return ret;
13464 }
13465
13466 #define foreach_pbb_vtr_op      \
13467 _("disable",  L2_VTR_DISABLED)  \
13468 _("pop",  L2_VTR_POP_2)         \
13469 _("push",  L2_VTR_PUSH_2)
13470
13471 static int
13472 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
13473 {
13474   unformat_input_t *i = vam->input;
13475   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
13476   u32 sw_if_index = ~0, vtr_op = ~0;
13477   u16 outer_tag = ~0;
13478   u8 dmac[6], smac[6];
13479   u8 dmac_set = 0, smac_set = 0;
13480   u16 vlanid = 0;
13481   u32 sid = ~0;
13482   u32 tmp;
13483   int ret;
13484
13485   /* Shut up coverity */
13486   clib_memset (dmac, 0, sizeof (dmac));
13487   clib_memset (smac, 0, sizeof (smac));
13488
13489   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13490     {
13491       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13492         ;
13493       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13494         ;
13495       else if (unformat (i, "vtr_op %d", &vtr_op))
13496         ;
13497 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
13498       foreach_pbb_vtr_op
13499 #undef _
13500         else if (unformat (i, "translate_pbb_stag"))
13501         {
13502           if (unformat (i, "%d", &tmp))
13503             {
13504               vtr_op = L2_VTR_TRANSLATE_2_1;
13505               outer_tag = tmp;
13506             }
13507           else
13508             {
13509               errmsg
13510                 ("translate_pbb_stag operation requires outer tag definition");
13511               return -99;
13512             }
13513         }
13514       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
13515         dmac_set++;
13516       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
13517         smac_set++;
13518       else if (unformat (i, "sid %d", &sid))
13519         ;
13520       else if (unformat (i, "vlanid %d", &tmp))
13521         vlanid = tmp;
13522       else
13523         {
13524           clib_warning ("parse error '%U'", format_unformat_error, i);
13525           return -99;
13526         }
13527     }
13528
13529   if ((sw_if_index == ~0) || (vtr_op == ~0))
13530     {
13531       errmsg ("missing sw_if_index or vtr operation");
13532       return -99;
13533     }
13534   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
13535       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
13536     {
13537       errmsg
13538         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
13539       return -99;
13540     }
13541
13542   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
13543   mp->sw_if_index = ntohl (sw_if_index);
13544   mp->vtr_op = ntohl (vtr_op);
13545   mp->outer_tag = ntohs (outer_tag);
13546   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
13547   clib_memcpy (mp->b_smac, smac, sizeof (smac));
13548   mp->b_vlanid = ntohs (vlanid);
13549   mp->i_sid = ntohl (sid);
13550
13551   S (mp);
13552   W (ret);
13553   return ret;
13554 }
13555
13556 static int
13557 api_flow_classify_set_interface (vat_main_t * vam)
13558 {
13559   unformat_input_t *i = vam->input;
13560   vl_api_flow_classify_set_interface_t *mp;
13561   u32 sw_if_index;
13562   int sw_if_index_set;
13563   u32 ip4_table_index = ~0;
13564   u32 ip6_table_index = ~0;
13565   u8 is_add = 1;
13566   int ret;
13567
13568   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13569     {
13570       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13571         sw_if_index_set = 1;
13572       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13573         sw_if_index_set = 1;
13574       else if (unformat (i, "del"))
13575         is_add = 0;
13576       else if (unformat (i, "ip4-table %d", &ip4_table_index))
13577         ;
13578       else if (unformat (i, "ip6-table %d", &ip6_table_index))
13579         ;
13580       else
13581         {
13582           clib_warning ("parse error '%U'", format_unformat_error, i);
13583           return -99;
13584         }
13585     }
13586
13587   if (sw_if_index_set == 0)
13588     {
13589       errmsg ("missing interface name or sw_if_index");
13590       return -99;
13591     }
13592
13593   M (FLOW_CLASSIFY_SET_INTERFACE, mp);
13594
13595   mp->sw_if_index = ntohl (sw_if_index);
13596   mp->ip4_table_index = ntohl (ip4_table_index);
13597   mp->ip6_table_index = ntohl (ip6_table_index);
13598   mp->is_add = is_add;
13599
13600   S (mp);
13601   W (ret);
13602   return ret;
13603 }
13604
13605 static int
13606 api_flow_classify_dump (vat_main_t * vam)
13607 {
13608   unformat_input_t *i = vam->input;
13609   vl_api_flow_classify_dump_t *mp;
13610   vl_api_control_ping_t *mp_ping;
13611   u8 type = FLOW_CLASSIFY_N_TABLES;
13612   int ret;
13613
13614   if (unformat (i, "type %U", unformat_flow_classify_table_type, &type))
13615     ;
13616   else
13617     {
13618       errmsg ("classify table type must be specified");
13619       return -99;
13620     }
13621
13622   if (!vam->json_output)
13623     {
13624       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
13625     }
13626
13627   M (FLOW_CLASSIFY_DUMP, mp);
13628   mp->type = type;
13629   /* send it... */
13630   S (mp);
13631
13632   /* Use a control ping for synchronization */
13633   MPING (CONTROL_PING, mp_ping);
13634   S (mp_ping);
13635
13636   /* Wait for a reply... */
13637   W (ret);
13638   return ret;
13639 }
13640
13641 static int
13642 api_feature_enable_disable (vat_main_t * vam)
13643 {
13644   unformat_input_t *i = vam->input;
13645   vl_api_feature_enable_disable_t *mp;
13646   u8 *arc_name = 0;
13647   u8 *feature_name = 0;
13648   u32 sw_if_index = ~0;
13649   u8 enable = 1;
13650   int ret;
13651
13652   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13653     {
13654       if (unformat (i, "arc_name %s", &arc_name))
13655         ;
13656       else if (unformat (i, "feature_name %s", &feature_name))
13657         ;
13658       else
13659         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13660         ;
13661       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13662         ;
13663       else if (unformat (i, "disable"))
13664         enable = 0;
13665       else
13666         break;
13667     }
13668
13669   if (arc_name == 0)
13670     {
13671       errmsg ("missing arc name");
13672       return -99;
13673     }
13674   if (vec_len (arc_name) > 63)
13675     {
13676       errmsg ("arc name too long");
13677     }
13678
13679   if (feature_name == 0)
13680     {
13681       errmsg ("missing feature name");
13682       return -99;
13683     }
13684   if (vec_len (feature_name) > 63)
13685     {
13686       errmsg ("feature name too long");
13687     }
13688
13689   if (sw_if_index == ~0)
13690     {
13691       errmsg ("missing interface name or sw_if_index");
13692       return -99;
13693     }
13694
13695   /* Construct the API message */
13696   M (FEATURE_ENABLE_DISABLE, mp);
13697   mp->sw_if_index = ntohl (sw_if_index);
13698   mp->enable = enable;
13699   clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
13700   clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
13701   vec_free (arc_name);
13702   vec_free (feature_name);
13703
13704   S (mp);
13705   W (ret);
13706   return ret;
13707 }
13708
13709 static int
13710 api_feature_gso_enable_disable (vat_main_t * vam)
13711 {
13712   unformat_input_t *i = vam->input;
13713   vl_api_feature_gso_enable_disable_t *mp;
13714   u32 sw_if_index = ~0;
13715   u8 enable = 1;
13716   int ret;
13717
13718   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13719     {
13720       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13721         ;
13722       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13723         ;
13724       else if (unformat (i, "enable"))
13725         enable = 1;
13726       else if (unformat (i, "disable"))
13727         enable = 0;
13728       else
13729         break;
13730     }
13731
13732   if (sw_if_index == ~0)
13733     {
13734       errmsg ("missing interface name or sw_if_index");
13735       return -99;
13736     }
13737
13738   /* Construct the API message */
13739   M (FEATURE_GSO_ENABLE_DISABLE, mp);
13740   mp->sw_if_index = ntohl (sw_if_index);
13741   mp->enable_disable = enable;
13742
13743   S (mp);
13744   W (ret);
13745   return ret;
13746 }
13747
13748 static int
13749 api_sw_interface_tag_add_del (vat_main_t * vam)
13750 {
13751   unformat_input_t *i = vam->input;
13752   vl_api_sw_interface_tag_add_del_t *mp;
13753   u32 sw_if_index = ~0;
13754   u8 *tag = 0;
13755   u8 enable = 1;
13756   int ret;
13757
13758   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13759     {
13760       if (unformat (i, "tag %s", &tag))
13761         ;
13762       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13763         ;
13764       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13765         ;
13766       else if (unformat (i, "del"))
13767         enable = 0;
13768       else
13769         break;
13770     }
13771
13772   if (sw_if_index == ~0)
13773     {
13774       errmsg ("missing interface name or sw_if_index");
13775       return -99;
13776     }
13777
13778   if (enable && (tag == 0))
13779     {
13780       errmsg ("no tag specified");
13781       return -99;
13782     }
13783
13784   /* Construct the API message */
13785   M (SW_INTERFACE_TAG_ADD_DEL, mp);
13786   mp->sw_if_index = ntohl (sw_if_index);
13787   mp->is_add = enable;
13788   if (enable)
13789     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
13790   vec_free (tag);
13791
13792   S (mp);
13793   W (ret);
13794   return ret;
13795 }
13796
13797 static int
13798 api_sw_interface_add_del_mac_address (vat_main_t * vam)
13799 {
13800   unformat_input_t *i = vam->input;
13801   vl_api_mac_address_t mac = { 0 };
13802   vl_api_sw_interface_add_del_mac_address_t *mp;
13803   u32 sw_if_index = ~0;
13804   u8 is_add = 1;
13805   u8 mac_set = 0;
13806   int ret;
13807
13808   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13809     {
13810       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13811         ;
13812       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13813         ;
13814       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
13815         mac_set++;
13816       else if (unformat (i, "del"))
13817         is_add = 0;
13818       else
13819         break;
13820     }
13821
13822   if (sw_if_index == ~0)
13823     {
13824       errmsg ("missing interface name or sw_if_index");
13825       return -99;
13826     }
13827
13828   if (!mac_set)
13829     {
13830       errmsg ("missing MAC address");
13831       return -99;
13832     }
13833
13834   /* Construct the API message */
13835   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
13836   mp->sw_if_index = ntohl (sw_if_index);
13837   mp->is_add = is_add;
13838   clib_memcpy (&mp->addr, &mac, sizeof (mac));
13839
13840   S (mp);
13841   W (ret);
13842   return ret;
13843 }
13844
13845 static void vl_api_l2_xconnect_details_t_handler
13846   (vl_api_l2_xconnect_details_t * mp)
13847 {
13848   vat_main_t *vam = &vat_main;
13849
13850   print (vam->ofp, "%15d%15d",
13851          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
13852 }
13853
13854 static void vl_api_l2_xconnect_details_t_handler_json
13855   (vl_api_l2_xconnect_details_t * mp)
13856 {
13857   vat_main_t *vam = &vat_main;
13858   vat_json_node_t *node = NULL;
13859
13860   if (VAT_JSON_ARRAY != vam->json_tree.type)
13861     {
13862       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
13863       vat_json_init_array (&vam->json_tree);
13864     }
13865   node = vat_json_array_add (&vam->json_tree);
13866
13867   vat_json_init_object (node);
13868   vat_json_object_add_uint (node, "rx_sw_if_index",
13869                             ntohl (mp->rx_sw_if_index));
13870   vat_json_object_add_uint (node, "tx_sw_if_index",
13871                             ntohl (mp->tx_sw_if_index));
13872 }
13873
13874 static int
13875 api_l2_xconnect_dump (vat_main_t * vam)
13876 {
13877   vl_api_l2_xconnect_dump_t *mp;
13878   vl_api_control_ping_t *mp_ping;
13879   int ret;
13880
13881   if (!vam->json_output)
13882     {
13883       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
13884     }
13885
13886   M (L2_XCONNECT_DUMP, mp);
13887
13888   S (mp);
13889
13890   /* Use a control ping for synchronization */
13891   MPING (CONTROL_PING, mp_ping);
13892   S (mp_ping);
13893
13894   W (ret);
13895   return ret;
13896 }
13897
13898 static int
13899 api_hw_interface_set_mtu (vat_main_t * vam)
13900 {
13901   unformat_input_t *i = vam->input;
13902   vl_api_hw_interface_set_mtu_t *mp;
13903   u32 sw_if_index = ~0;
13904   u32 mtu = 0;
13905   int ret;
13906
13907   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13908     {
13909       if (unformat (i, "mtu %d", &mtu))
13910         ;
13911       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13912         ;
13913       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13914         ;
13915       else
13916         break;
13917     }
13918
13919   if (sw_if_index == ~0)
13920     {
13921       errmsg ("missing interface name or sw_if_index");
13922       return -99;
13923     }
13924
13925   if (mtu == 0)
13926     {
13927       errmsg ("no mtu specified");
13928       return -99;
13929     }
13930
13931   /* Construct the API message */
13932   M (HW_INTERFACE_SET_MTU, mp);
13933   mp->sw_if_index = ntohl (sw_if_index);
13934   mp->mtu = ntohs ((u16) mtu);
13935
13936   S (mp);
13937   W (ret);
13938   return ret;
13939 }
13940
13941 static int
13942 api_p2p_ethernet_add (vat_main_t * vam)
13943 {
13944   unformat_input_t *i = vam->input;
13945   vl_api_p2p_ethernet_add_t *mp;
13946   u32 parent_if_index = ~0;
13947   u32 sub_id = ~0;
13948   u8 remote_mac[6];
13949   u8 mac_set = 0;
13950   int ret;
13951
13952   clib_memset (remote_mac, 0, sizeof (remote_mac));
13953   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13954     {
13955       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
13956         ;
13957       else if (unformat (i, "sw_if_index %d", &parent_if_index))
13958         ;
13959       else
13960         if (unformat
13961             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
13962         mac_set++;
13963       else if (unformat (i, "sub_id %d", &sub_id))
13964         ;
13965       else
13966         {
13967           clib_warning ("parse error '%U'", format_unformat_error, i);
13968           return -99;
13969         }
13970     }
13971
13972   if (parent_if_index == ~0)
13973     {
13974       errmsg ("missing interface name or sw_if_index");
13975       return -99;
13976     }
13977   if (mac_set == 0)
13978     {
13979       errmsg ("missing remote mac address");
13980       return -99;
13981     }
13982   if (sub_id == ~0)
13983     {
13984       errmsg ("missing sub-interface id");
13985       return -99;
13986     }
13987
13988   M (P2P_ETHERNET_ADD, mp);
13989   mp->parent_if_index = ntohl (parent_if_index);
13990   mp->subif_id = ntohl (sub_id);
13991   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
13992
13993   S (mp);
13994   W (ret);
13995   return ret;
13996 }
13997
13998 static int
13999 api_p2p_ethernet_del (vat_main_t * vam)
14000 {
14001   unformat_input_t *i = vam->input;
14002   vl_api_p2p_ethernet_del_t *mp;
14003   u32 parent_if_index = ~0;
14004   u8 remote_mac[6];
14005   u8 mac_set = 0;
14006   int ret;
14007
14008   clib_memset (remote_mac, 0, sizeof (remote_mac));
14009   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14010     {
14011       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
14012         ;
14013       else if (unformat (i, "sw_if_index %d", &parent_if_index))
14014         ;
14015       else
14016         if (unformat
14017             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
14018         mac_set++;
14019       else
14020         {
14021           clib_warning ("parse error '%U'", format_unformat_error, i);
14022           return -99;
14023         }
14024     }
14025
14026   if (parent_if_index == ~0)
14027     {
14028       errmsg ("missing interface name or sw_if_index");
14029       return -99;
14030     }
14031   if (mac_set == 0)
14032     {
14033       errmsg ("missing remote mac address");
14034       return -99;
14035     }
14036
14037   M (P2P_ETHERNET_DEL, mp);
14038   mp->parent_if_index = ntohl (parent_if_index);
14039   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
14040
14041   S (mp);
14042   W (ret);
14043   return ret;
14044 }
14045
14046 static int
14047 api_tcp_configure_src_addresses (vat_main_t * vam)
14048 {
14049   vl_api_tcp_configure_src_addresses_t *mp;
14050   unformat_input_t *i = vam->input;
14051   vl_api_address_t first, last;
14052   u8 range_set = 0;
14053   u32 vrf_id = 0;
14054   int ret;
14055
14056   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14057     {
14058       if (unformat (i, "%U - %U",
14059                     unformat_vl_api_address, &first,
14060                     unformat_vl_api_address, &last))
14061         {
14062           if (range_set)
14063             {
14064               errmsg ("one range per message (range already set)");
14065               return -99;
14066             }
14067           range_set = 1;
14068         }
14069       else if (unformat (i, "vrf %d", &vrf_id))
14070         ;
14071       else
14072         break;
14073     }
14074
14075   if (range_set == 0)
14076     {
14077       errmsg ("address range not set");
14078       return -99;
14079     }
14080
14081   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
14082
14083   mp->vrf_id = ntohl (vrf_id);
14084   clib_memcpy (&mp->first_address, &first, sizeof (first));
14085   clib_memcpy (&mp->last_address, &last, sizeof (last));
14086
14087   S (mp);
14088   W (ret);
14089   return ret;
14090 }
14091
14092 static void vl_api_app_namespace_add_del_reply_t_handler
14093   (vl_api_app_namespace_add_del_reply_t * mp)
14094 {
14095   vat_main_t *vam = &vat_main;
14096   i32 retval = ntohl (mp->retval);
14097   if (vam->async_mode)
14098     {
14099       vam->async_errors += (retval < 0);
14100     }
14101   else
14102     {
14103       vam->retval = retval;
14104       if (retval == 0)
14105         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
14106       vam->result_ready = 1;
14107     }
14108 }
14109
14110 static void vl_api_app_namespace_add_del_reply_t_handler_json
14111   (vl_api_app_namespace_add_del_reply_t * mp)
14112 {
14113   vat_main_t *vam = &vat_main;
14114   vat_json_node_t node;
14115
14116   vat_json_init_object (&node);
14117   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
14118   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
14119
14120   vat_json_print (vam->ofp, &node);
14121   vat_json_free (&node);
14122
14123   vam->retval = ntohl (mp->retval);
14124   vam->result_ready = 1;
14125 }
14126
14127 static int
14128 api_app_namespace_add_del (vat_main_t * vam)
14129 {
14130   vl_api_app_namespace_add_del_t *mp;
14131   unformat_input_t *i = vam->input;
14132   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
14133   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
14134   u64 secret;
14135   int ret;
14136
14137   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14138     {
14139       if (unformat (i, "id %_%v%_", &ns_id))
14140         ;
14141       else if (unformat (i, "secret %lu", &secret))
14142         secret_set = 1;
14143       else if (unformat (i, "sw_if_index %d", &sw_if_index))
14144         sw_if_index_set = 1;
14145       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
14146         ;
14147       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
14148         ;
14149       else
14150         break;
14151     }
14152   if (!ns_id || !secret_set || !sw_if_index_set)
14153     {
14154       errmsg ("namespace id, secret and sw_if_index must be set");
14155       return -99;
14156     }
14157   if (vec_len (ns_id) > 64)
14158     {
14159       errmsg ("namespace id too long");
14160       return -99;
14161     }
14162   M (APP_NAMESPACE_ADD_DEL, mp);
14163
14164   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
14165   mp->secret = clib_host_to_net_u64 (secret);
14166   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
14167   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
14168   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
14169   vec_free (ns_id);
14170   S (mp);
14171   W (ret);
14172   return ret;
14173 }
14174
14175 static int
14176 api_sock_init_shm (vat_main_t * vam)
14177 {
14178 #if VPP_API_TEST_BUILTIN == 0
14179   unformat_input_t *i = vam->input;
14180   vl_api_shm_elem_config_t *config = 0;
14181   u64 size = 64 << 20;
14182   int rv;
14183
14184   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14185     {
14186       if (unformat (i, "size %U", unformat_memory_size, &size))
14187         ;
14188       else
14189         break;
14190     }
14191
14192   /*
14193    * Canned custom ring allocator config.
14194    * Should probably parse all of this
14195    */
14196   vec_validate (config, 6);
14197   config[0].type = VL_API_VLIB_RING;
14198   config[0].size = 256;
14199   config[0].count = 32;
14200
14201   config[1].type = VL_API_VLIB_RING;
14202   config[1].size = 1024;
14203   config[1].count = 16;
14204
14205   config[2].type = VL_API_VLIB_RING;
14206   config[2].size = 4096;
14207   config[2].count = 2;
14208
14209   config[3].type = VL_API_CLIENT_RING;
14210   config[3].size = 256;
14211   config[3].count = 32;
14212
14213   config[4].type = VL_API_CLIENT_RING;
14214   config[4].size = 1024;
14215   config[4].count = 16;
14216
14217   config[5].type = VL_API_CLIENT_RING;
14218   config[5].size = 4096;
14219   config[5].count = 2;
14220
14221   config[6].type = VL_API_QUEUE;
14222   config[6].count = 128;
14223   config[6].size = sizeof (uword);
14224
14225   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
14226   if (!rv)
14227     vam->client_index_invalid = 1;
14228   return rv;
14229 #else
14230   return -99;
14231 #endif
14232 }
14233
14234 static void
14235 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
14236 {
14237   vat_main_t *vam = &vat_main;
14238   fib_prefix_t lcl, rmt;
14239
14240   ip_prefix_decode (&mp->lcl, &lcl);
14241   ip_prefix_decode (&mp->rmt, &rmt);
14242
14243   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
14244     {
14245       print (vam->ofp,
14246              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
14247              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
14248              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
14249              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
14250              &rmt.fp_addr.ip4, rmt.fp_len,
14251              clib_net_to_host_u16 (mp->rmt_port),
14252              clib_net_to_host_u32 (mp->action_index), mp->tag);
14253     }
14254   else
14255     {
14256       print (vam->ofp,
14257              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
14258              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
14259              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
14260              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
14261              &rmt.fp_addr.ip6, rmt.fp_len,
14262              clib_net_to_host_u16 (mp->rmt_port),
14263              clib_net_to_host_u32 (mp->action_index), mp->tag);
14264     }
14265 }
14266
14267 static void
14268 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
14269                                              mp)
14270 {
14271   vat_main_t *vam = &vat_main;
14272   vat_json_node_t *node = NULL;
14273   struct in6_addr ip6;
14274   struct in_addr ip4;
14275
14276   fib_prefix_t lcl, rmt;
14277
14278   ip_prefix_decode (&mp->lcl, &lcl);
14279   ip_prefix_decode (&mp->rmt, &rmt);
14280
14281   if (VAT_JSON_ARRAY != vam->json_tree.type)
14282     {
14283       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
14284       vat_json_init_array (&vam->json_tree);
14285     }
14286   node = vat_json_array_add (&vam->json_tree);
14287   vat_json_init_object (node);
14288
14289   vat_json_object_add_uint (node, "appns_index",
14290                             clib_net_to_host_u32 (mp->appns_index));
14291   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
14292   vat_json_object_add_uint (node, "scope", mp->scope);
14293   vat_json_object_add_uint (node, "action_index",
14294                             clib_net_to_host_u32 (mp->action_index));
14295   vat_json_object_add_uint (node, "lcl_port",
14296                             clib_net_to_host_u16 (mp->lcl_port));
14297   vat_json_object_add_uint (node, "rmt_port",
14298                             clib_net_to_host_u16 (mp->rmt_port));
14299   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
14300   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
14301   vat_json_object_add_string_copy (node, "tag", mp->tag);
14302   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
14303     {
14304       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
14305       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
14306       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
14307       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
14308     }
14309   else
14310     {
14311       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
14312       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
14313       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
14314       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
14315     }
14316 }
14317
14318 static int
14319 api_session_rule_add_del (vat_main_t * vam)
14320 {
14321   vl_api_session_rule_add_del_t *mp;
14322   unformat_input_t *i = vam->input;
14323   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
14324   u32 appns_index = 0, scope = 0;
14325   ip4_address_t lcl_ip4, rmt_ip4;
14326   ip6_address_t lcl_ip6, rmt_ip6;
14327   u8 is_ip4 = 1, conn_set = 0;
14328   u8 is_add = 1, *tag = 0;
14329   int ret;
14330   fib_prefix_t lcl, rmt;
14331
14332   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14333     {
14334       if (unformat (i, "del"))
14335         is_add = 0;
14336       else if (unformat (i, "add"))
14337         ;
14338       else if (unformat (i, "proto tcp"))
14339         proto = 0;
14340       else if (unformat (i, "proto udp"))
14341         proto = 1;
14342       else if (unformat (i, "appns %d", &appns_index))
14343         ;
14344       else if (unformat (i, "scope %d", &scope))
14345         ;
14346       else if (unformat (i, "tag %_%v%_", &tag))
14347         ;
14348       else
14349         if (unformat
14350             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
14351              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
14352              &rmt_port))
14353         {
14354           is_ip4 = 1;
14355           conn_set = 1;
14356         }
14357       else
14358         if (unformat
14359             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
14360              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
14361              &rmt_port))
14362         {
14363           is_ip4 = 0;
14364           conn_set = 1;
14365         }
14366       else if (unformat (i, "action %d", &action))
14367         ;
14368       else
14369         break;
14370     }
14371   if (proto == ~0 || !conn_set || action == ~0)
14372     {
14373       errmsg ("transport proto, connection and action must be set");
14374       return -99;
14375     }
14376
14377   if (scope > 3)
14378     {
14379       errmsg ("scope should be 0-3");
14380       return -99;
14381     }
14382
14383   M (SESSION_RULE_ADD_DEL, mp);
14384
14385   clib_memset (&lcl, 0, sizeof (lcl));
14386   clib_memset (&rmt, 0, sizeof (rmt));
14387   if (is_ip4)
14388     {
14389       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
14390       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
14391       lcl.fp_len = lcl_plen;
14392       rmt.fp_len = rmt_plen;
14393     }
14394   else
14395     {
14396       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
14397       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
14398       lcl.fp_len = lcl_plen;
14399       rmt.fp_len = rmt_plen;
14400     }
14401
14402
14403   ip_prefix_encode (&lcl, &mp->lcl);
14404   ip_prefix_encode (&rmt, &mp->rmt);
14405   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
14406   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
14407   mp->transport_proto =
14408     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
14409   mp->action_index = clib_host_to_net_u32 (action);
14410   mp->appns_index = clib_host_to_net_u32 (appns_index);
14411   mp->scope = scope;
14412   mp->is_add = is_add;
14413   if (tag)
14414     {
14415       clib_memcpy (mp->tag, tag, vec_len (tag));
14416       vec_free (tag);
14417     }
14418
14419   S (mp);
14420   W (ret);
14421   return ret;
14422 }
14423
14424 static int
14425 api_session_rules_dump (vat_main_t * vam)
14426 {
14427   vl_api_session_rules_dump_t *mp;
14428   vl_api_control_ping_t *mp_ping;
14429   int ret;
14430
14431   if (!vam->json_output)
14432     {
14433       print (vam->ofp, "%=20s", "Session Rules");
14434     }
14435
14436   M (SESSION_RULES_DUMP, mp);
14437   /* send it... */
14438   S (mp);
14439
14440   /* Use a control ping for synchronization */
14441   MPING (CONTROL_PING, mp_ping);
14442   S (mp_ping);
14443
14444   /* Wait for a reply... */
14445   W (ret);
14446   return ret;
14447 }
14448
14449 static int
14450 api_ip_container_proxy_add_del (vat_main_t * vam)
14451 {
14452   vl_api_ip_container_proxy_add_del_t *mp;
14453   unformat_input_t *i = vam->input;
14454   u32 sw_if_index = ~0;
14455   vl_api_prefix_t pfx = { };
14456   u8 is_add = 1;
14457   int ret;
14458
14459   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14460     {
14461       if (unformat (i, "del"))
14462         is_add = 0;
14463       else if (unformat (i, "add"))
14464         ;
14465       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
14466         ;
14467       else if (unformat (i, "sw_if_index %u", &sw_if_index))
14468         ;
14469       else
14470         break;
14471     }
14472   if (sw_if_index == ~0 || pfx.len == 0)
14473     {
14474       errmsg ("address and sw_if_index must be set");
14475       return -99;
14476     }
14477
14478   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
14479
14480   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
14481   mp->is_add = is_add;
14482   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
14483
14484   S (mp);
14485   W (ret);
14486   return ret;
14487 }
14488
14489 static int
14490 api_qos_record_enable_disable (vat_main_t * vam)
14491 {
14492   unformat_input_t *i = vam->input;
14493   vl_api_qos_record_enable_disable_t *mp;
14494   u32 sw_if_index, qs = 0xff;
14495   u8 sw_if_index_set = 0;
14496   u8 enable = 1;
14497   int ret;
14498
14499   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14500     {
14501       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
14502         sw_if_index_set = 1;
14503       else if (unformat (i, "sw_if_index %d", &sw_if_index))
14504         sw_if_index_set = 1;
14505       else if (unformat (i, "%U", unformat_qos_source, &qs))
14506         ;
14507       else if (unformat (i, "disable"))
14508         enable = 0;
14509       else
14510         {
14511           clib_warning ("parse error '%U'", format_unformat_error, i);
14512           return -99;
14513         }
14514     }
14515
14516   if (sw_if_index_set == 0)
14517     {
14518       errmsg ("missing interface name or sw_if_index");
14519       return -99;
14520     }
14521   if (qs == 0xff)
14522     {
14523       errmsg ("input location must be specified");
14524       return -99;
14525     }
14526
14527   M (QOS_RECORD_ENABLE_DISABLE, mp);
14528
14529   mp->record.sw_if_index = ntohl (sw_if_index);
14530   mp->record.input_source = qs;
14531   mp->enable = enable;
14532
14533   S (mp);
14534   W (ret);
14535   return ret;
14536 }
14537
14538
14539 static int
14540 q_or_quit (vat_main_t * vam)
14541 {
14542 #if VPP_API_TEST_BUILTIN == 0
14543   longjmp (vam->jump_buf, 1);
14544 #endif
14545   return 0;                     /* not so much */
14546 }
14547
14548 static int
14549 q (vat_main_t * vam)
14550 {
14551   return q_or_quit (vam);
14552 }
14553
14554 static int
14555 quit (vat_main_t * vam)
14556 {
14557   return q_or_quit (vam);
14558 }
14559
14560 static int
14561 comment (vat_main_t * vam)
14562 {
14563   return 0;
14564 }
14565
14566 static int
14567 elog_save (vat_main_t * vam)
14568 {
14569 #if VPP_API_TEST_BUILTIN == 0
14570   elog_main_t *em = &vam->elog_main;
14571   unformat_input_t *i = vam->input;
14572   char *file, *chroot_file;
14573   clib_error_t *error;
14574
14575   if (!unformat (i, "%s", &file))
14576     {
14577       errmsg ("expected file name, got `%U'", format_unformat_error, i);
14578       return 0;
14579     }
14580
14581   /* It's fairly hard to get "../oopsie" through unformat; just in case */
14582   if (strstr (file, "..") || index (file, '/'))
14583     {
14584       errmsg ("illegal characters in filename '%s'", file);
14585       return 0;
14586     }
14587
14588   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
14589
14590   vec_free (file);
14591
14592   errmsg ("Saving %wd of %wd events to %s",
14593           elog_n_events_in_buffer (em),
14594           elog_buffer_capacity (em), chroot_file);
14595
14596   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
14597   vec_free (chroot_file);
14598
14599   if (error)
14600     clib_error_report (error);
14601 #else
14602   errmsg ("Use the vpp event loger...");
14603 #endif
14604
14605   return 0;
14606 }
14607
14608 static int
14609 elog_setup (vat_main_t * vam)
14610 {
14611 #if VPP_API_TEST_BUILTIN == 0
14612   elog_main_t *em = &vam->elog_main;
14613   unformat_input_t *i = vam->input;
14614   u32 nevents = 128 << 10;
14615
14616   (void) unformat (i, "nevents %d", &nevents);
14617
14618   elog_init (em, nevents);
14619   vl_api_set_elog_main (em);
14620   vl_api_set_elog_trace_api_messages (1);
14621   errmsg ("Event logger initialized with %u events", nevents);
14622 #else
14623   errmsg ("Use the vpp event loger...");
14624 #endif
14625   return 0;
14626 }
14627
14628 static int
14629 elog_enable (vat_main_t * vam)
14630 {
14631 #if VPP_API_TEST_BUILTIN == 0
14632   elog_main_t *em = &vam->elog_main;
14633
14634   elog_enable_disable (em, 1 /* enable */ );
14635   vl_api_set_elog_trace_api_messages (1);
14636   errmsg ("Event logger enabled...");
14637 #else
14638   errmsg ("Use the vpp event loger...");
14639 #endif
14640   return 0;
14641 }
14642
14643 static int
14644 elog_disable (vat_main_t * vam)
14645 {
14646 #if VPP_API_TEST_BUILTIN == 0
14647   elog_main_t *em = &vam->elog_main;
14648
14649   elog_enable_disable (em, 0 /* enable */ );
14650   vl_api_set_elog_trace_api_messages (1);
14651   errmsg ("Event logger disabled...");
14652 #else
14653   errmsg ("Use the vpp event loger...");
14654 #endif
14655   return 0;
14656 }
14657
14658 static int
14659 statseg (vat_main_t * vam)
14660 {
14661   ssvm_private_t *ssvmp = &vam->stat_segment;
14662   ssvm_shared_header_t *shared_header = ssvmp->sh;
14663   vlib_counter_t **counters;
14664   u64 thread0_index1_packets;
14665   u64 thread0_index1_bytes;
14666   f64 vector_rate, input_rate;
14667   uword *p;
14668
14669   uword *counter_vector_by_name;
14670   if (vam->stat_segment_lockp == 0)
14671     {
14672       errmsg ("Stat segment not mapped...");
14673       return -99;
14674     }
14675
14676   /* look up "/if/rx for sw_if_index 1 as a test */
14677
14678   clib_spinlock_lock (vam->stat_segment_lockp);
14679
14680   counter_vector_by_name = (uword *) shared_header->opaque[1];
14681
14682   p = hash_get_mem (counter_vector_by_name, "/if/rx");
14683   if (p == 0)
14684     {
14685       clib_spinlock_unlock (vam->stat_segment_lockp);
14686       errmsg ("/if/tx not found?");
14687       return -99;
14688     }
14689
14690   /* Fish per-thread vector of combined counters from shared memory */
14691   counters = (vlib_counter_t **) p[0];
14692
14693   if (vec_len (counters[0]) < 2)
14694     {
14695       clib_spinlock_unlock (vam->stat_segment_lockp);
14696       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
14697       return -99;
14698     }
14699
14700   /* Read thread 0 sw_if_index 1 counter */
14701   thread0_index1_packets = counters[0][1].packets;
14702   thread0_index1_bytes = counters[0][1].bytes;
14703
14704   p = hash_get_mem (counter_vector_by_name, "vector_rate");
14705   if (p == 0)
14706     {
14707       clib_spinlock_unlock (vam->stat_segment_lockp);
14708       errmsg ("vector_rate not found?");
14709       return -99;
14710     }
14711
14712   vector_rate = *(f64 *) (p[0]);
14713   p = hash_get_mem (counter_vector_by_name, "input_rate");
14714   if (p == 0)
14715     {
14716       clib_spinlock_unlock (vam->stat_segment_lockp);
14717       errmsg ("input_rate not found?");
14718       return -99;
14719     }
14720   input_rate = *(f64 *) (p[0]);
14721
14722   clib_spinlock_unlock (vam->stat_segment_lockp);
14723
14724   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
14725          vector_rate, input_rate);
14726   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
14727          thread0_index1_packets, thread0_index1_bytes);
14728
14729   return 0;
14730 }
14731
14732 static int
14733 cmd_cmp (void *a1, void *a2)
14734 {
14735   u8 **c1 = a1;
14736   u8 **c2 = a2;
14737
14738   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
14739 }
14740
14741 static int
14742 help (vat_main_t * vam)
14743 {
14744   u8 **cmds = 0;
14745   u8 *name = 0;
14746   hash_pair_t *p;
14747   unformat_input_t *i = vam->input;
14748   int j;
14749
14750   if (unformat (i, "%s", &name))
14751     {
14752       uword *hs;
14753
14754       vec_add1 (name, 0);
14755
14756       hs = hash_get_mem (vam->help_by_name, name);
14757       if (hs)
14758         print (vam->ofp, "usage: %s %s", name, hs[0]);
14759       else
14760         print (vam->ofp, "No such msg / command '%s'", name);
14761       vec_free (name);
14762       return 0;
14763     }
14764
14765   print (vam->ofp, "Help is available for the following:");
14766
14767     /* *INDENT-OFF* */
14768     hash_foreach_pair (p, vam->function_by_name,
14769     ({
14770       vec_add1 (cmds, (u8 *)(p->key));
14771     }));
14772     /* *INDENT-ON* */
14773
14774   vec_sort_with_function (cmds, cmd_cmp);
14775
14776   for (j = 0; j < vec_len (cmds); j++)
14777     print (vam->ofp, "%s", cmds[j]);
14778
14779   vec_free (cmds);
14780   return 0;
14781 }
14782
14783 static int
14784 set (vat_main_t * vam)
14785 {
14786   u8 *name = 0, *value = 0;
14787   unformat_input_t *i = vam->input;
14788
14789   if (unformat (i, "%s", &name))
14790     {
14791       /* The input buffer is a vector, not a string. */
14792       value = vec_dup (i->buffer);
14793       vec_delete (value, i->index, 0);
14794       /* Almost certainly has a trailing newline */
14795       if (value[vec_len (value) - 1] == '\n')
14796         value[vec_len (value) - 1] = 0;
14797       /* Make sure it's a proper string, one way or the other */
14798       vec_add1 (value, 0);
14799       (void) clib_macro_set_value (&vam->macro_main,
14800                                    (char *) name, (char *) value);
14801     }
14802   else
14803     errmsg ("usage: set <name> <value>");
14804
14805   vec_free (name);
14806   vec_free (value);
14807   return 0;
14808 }
14809
14810 static int
14811 unset (vat_main_t * vam)
14812 {
14813   u8 *name = 0;
14814
14815   if (unformat (vam->input, "%s", &name))
14816     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
14817       errmsg ("unset: %s wasn't set", name);
14818   vec_free (name);
14819   return 0;
14820 }
14821
14822 typedef struct
14823 {
14824   u8 *name;
14825   u8 *value;
14826 } macro_sort_t;
14827
14828
14829 static int
14830 macro_sort_cmp (void *a1, void *a2)
14831 {
14832   macro_sort_t *s1 = a1;
14833   macro_sort_t *s2 = a2;
14834
14835   return strcmp ((char *) (s1->name), (char *) (s2->name));
14836 }
14837
14838 static int
14839 dump_macro_table (vat_main_t * vam)
14840 {
14841   macro_sort_t *sort_me = 0, *sm;
14842   int i;
14843   hash_pair_t *p;
14844
14845     /* *INDENT-OFF* */
14846     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
14847     ({
14848       vec_add2 (sort_me, sm, 1);
14849       sm->name = (u8 *)(p->key);
14850       sm->value = (u8 *) (p->value[0]);
14851     }));
14852     /* *INDENT-ON* */
14853
14854   vec_sort_with_function (sort_me, macro_sort_cmp);
14855
14856   if (vec_len (sort_me))
14857     print (vam->ofp, "%-15s%s", "Name", "Value");
14858   else
14859     print (vam->ofp, "The macro table is empty...");
14860
14861   for (i = 0; i < vec_len (sort_me); i++)
14862     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
14863   return 0;
14864 }
14865
14866 static int
14867 dump_node_table (vat_main_t * vam)
14868 {
14869   int i, j;
14870   vlib_node_t *node, *next_node;
14871
14872   if (vec_len (vam->graph_nodes) == 0)
14873     {
14874       print (vam->ofp, "Node table empty, issue get_node_graph...");
14875       return 0;
14876     }
14877
14878   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
14879     {
14880       node = vam->graph_nodes[0][i];
14881       print (vam->ofp, "[%d] %s", i, node->name);
14882       for (j = 0; j < vec_len (node->next_nodes); j++)
14883         {
14884           if (node->next_nodes[j] != ~0)
14885             {
14886               next_node = vam->graph_nodes[0][node->next_nodes[j]];
14887               print (vam->ofp, "  [%d] %s", j, next_node->name);
14888             }
14889         }
14890     }
14891   return 0;
14892 }
14893
14894 static int
14895 value_sort_cmp (void *a1, void *a2)
14896 {
14897   name_sort_t *n1 = a1;
14898   name_sort_t *n2 = a2;
14899
14900   if (n1->value < n2->value)
14901     return -1;
14902   if (n1->value > n2->value)
14903     return 1;
14904   return 0;
14905 }
14906
14907
14908 static int
14909 dump_msg_api_table (vat_main_t * vam)
14910 {
14911   api_main_t *am = vlibapi_get_main ();
14912   name_sort_t *nses = 0, *ns;
14913   hash_pair_t *hp;
14914   int i;
14915
14916   /* *INDENT-OFF* */
14917   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
14918   ({
14919     vec_add2 (nses, ns, 1);
14920     ns->name = (u8 *)(hp->key);
14921     ns->value = (u32) hp->value[0];
14922   }));
14923   /* *INDENT-ON* */
14924
14925   vec_sort_with_function (nses, value_sort_cmp);
14926
14927   for (i = 0; i < vec_len (nses); i++)
14928     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
14929   vec_free (nses);
14930   return 0;
14931 }
14932
14933 static int
14934 get_msg_id (vat_main_t * vam)
14935 {
14936   u8 *name_and_crc;
14937   u32 message_index;
14938
14939   if (unformat (vam->input, "%s", &name_and_crc))
14940     {
14941       message_index = vl_msg_api_get_msg_index (name_and_crc);
14942       if (message_index == ~0)
14943         {
14944           print (vam->ofp, " '%s' not found", name_and_crc);
14945           return 0;
14946         }
14947       print (vam->ofp, " '%s' has message index %d",
14948              name_and_crc, message_index);
14949       return 0;
14950     }
14951   errmsg ("name_and_crc required...");
14952   return 0;
14953 }
14954
14955 static int
14956 search_node_table (vat_main_t * vam)
14957 {
14958   unformat_input_t *line_input = vam->input;
14959   u8 *node_to_find;
14960   int j;
14961   vlib_node_t *node, *next_node;
14962   uword *p;
14963
14964   if (vam->graph_node_index_by_name == 0)
14965     {
14966       print (vam->ofp, "Node table empty, issue get_node_graph...");
14967       return 0;
14968     }
14969
14970   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
14971     {
14972       if (unformat (line_input, "%s", &node_to_find))
14973         {
14974           vec_add1 (node_to_find, 0);
14975           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
14976           if (p == 0)
14977             {
14978               print (vam->ofp, "%s not found...", node_to_find);
14979               goto out;
14980             }
14981           node = vam->graph_nodes[0][p[0]];
14982           print (vam->ofp, "[%d] %s", p[0], node->name);
14983           for (j = 0; j < vec_len (node->next_nodes); j++)
14984             {
14985               if (node->next_nodes[j] != ~0)
14986                 {
14987                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
14988                   print (vam->ofp, "  [%d] %s", j, next_node->name);
14989                 }
14990             }
14991         }
14992
14993       else
14994         {
14995           clib_warning ("parse error '%U'", format_unformat_error,
14996                         line_input);
14997           return -99;
14998         }
14999
15000     out:
15001       vec_free (node_to_find);
15002
15003     }
15004
15005   return 0;
15006 }
15007
15008
15009 static int
15010 script (vat_main_t * vam)
15011 {
15012 #if (VPP_API_TEST_BUILTIN==0)
15013   u8 *s = 0;
15014   char *save_current_file;
15015   unformat_input_t save_input;
15016   jmp_buf save_jump_buf;
15017   u32 save_line_number;
15018
15019   FILE *new_fp, *save_ifp;
15020
15021   if (unformat (vam->input, "%s", &s))
15022     {
15023       new_fp = fopen ((char *) s, "r");
15024       if (new_fp == 0)
15025         {
15026           errmsg ("Couldn't open script file %s", s);
15027           vec_free (s);
15028           return -99;
15029         }
15030     }
15031   else
15032     {
15033       errmsg ("Missing script name");
15034       return -99;
15035     }
15036
15037   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
15038   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
15039   save_ifp = vam->ifp;
15040   save_line_number = vam->input_line_number;
15041   save_current_file = (char *) vam->current_file;
15042
15043   vam->input_line_number = 0;
15044   vam->ifp = new_fp;
15045   vam->current_file = s;
15046   do_one_file (vam);
15047
15048   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
15049   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
15050   vam->ifp = save_ifp;
15051   vam->input_line_number = save_line_number;
15052   vam->current_file = (u8 *) save_current_file;
15053   vec_free (s);
15054
15055   return 0;
15056 #else
15057   clib_warning ("use the exec command...");
15058   return -99;
15059 #endif
15060 }
15061
15062 static int
15063 echo (vat_main_t * vam)
15064 {
15065   print (vam->ofp, "%v", vam->input->buffer);
15066   return 0;
15067 }
15068
15069 /* List of API message constructors, CLI names map to api_xxx */
15070 #define foreach_vpe_api_msg                                             \
15071 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
15072 _(sw_interface_dump,"")                                                 \
15073 _(sw_interface_set_flags,                                               \
15074   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
15075 _(sw_interface_add_del_address,                                         \
15076   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
15077 _(sw_interface_set_rx_mode,                                             \
15078   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
15079 _(sw_interface_set_rx_placement,                                        \
15080   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
15081 _(sw_interface_rx_placement_dump,                                       \
15082   "[<intfc> | sw_if_index <id>]")                                         \
15083 _(sw_interface_set_table,                                               \
15084   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
15085 _(sw_interface_set_mpls_enable,                                         \
15086   "<intfc> | sw_if_index [disable | dis]")                              \
15087 _(sw_interface_set_vpath,                                               \
15088   "<intfc> | sw_if_index <id> enable | disable")                        \
15089 _(sw_interface_set_vxlan_bypass,                                        \
15090   "<intfc> | sw_if_index <id> [ip4 | ip6] [enable | disable]")          \
15091 _(sw_interface_set_l2_xconnect,                                         \
15092   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
15093   "enable | disable")                                                   \
15094 _(sw_interface_set_l2_bridge,                                           \
15095   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
15096   "[shg <split-horizon-group>] [bvi]\n"                                 \
15097   "enable | disable")                                                   \
15098 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
15099 _(bridge_domain_add_del,                                                \
15100   "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") \
15101 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
15102 _(l2fib_add_del,                                                        \
15103   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
15104 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
15105 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
15106 _(l2_flags,                                                             \
15107   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
15108 _(bridge_flags,                                                         \
15109   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
15110 _(tap_create_v2,                                                        \
15111   "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]") \
15112 _(tap_delete_v2,                                                        \
15113   "<vpp-if-name> | sw_if_index <id>")                                   \
15114 _(sw_interface_tap_v2_dump, "")                                         \
15115 _(virtio_pci_create_v2,                                                    \
15116   "pci-addr <pci-address> [use_random_mac | hw-addr <mac-addr>] [features <hex-value>] [gso-enabled [gro-coalesce] | csum-offload-enabled] [packed] [in-order]") \
15117 _(virtio_pci_delete,                                                    \
15118   "<vpp-if-name> | sw_if_index <id>")                                   \
15119 _(sw_interface_virtio_pci_dump, "")                                     \
15120 _(bond_create,                                                          \
15121   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
15122   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
15123   "[id <if-id>]")                                                       \
15124 _(bond_create2,                                                         \
15125   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
15126   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
15127   "[id <if-id>] [gso]")                                                 \
15128 _(bond_delete,                                                          \
15129   "<vpp-if-name> | sw_if_index <id>")                                   \
15130 _(bond_add_member,                                                      \
15131   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
15132 _(bond_detach_member,                                                   \
15133   "sw_if_index <n>")                                                    \
15134  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
15135  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
15136  _(sw_member_interface_dump,                                            \
15137   "<vpp-if-name> | sw_if_index <id>")                                   \
15138 _(ip_table_add_del,                                                     \
15139   "table <n> [ipv6] [add | del]\n")                                     \
15140 _(ip_route_add_del,                                                     \
15141   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
15142   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
15143   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
15144   "[multipath] [count <n>] [del]")                                      \
15145 _(ip_mroute_add_del,                                                    \
15146   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
15147   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
15148 _(mpls_table_add_del,                                                   \
15149   "table <n> [add | del]\n")                                            \
15150 _(mpls_route_add_del,                                                   \
15151   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
15152   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
15153   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
15154   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
15155   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
15156   "[count <n>] [del]")                                                  \
15157 _(mpls_ip_bind_unbind,                                                  \
15158   "<label> <addr/len>")                                                 \
15159 _(mpls_tunnel_add_del,                                                  \
15160   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
15161   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
15162   "[l2-only]  [out-label <n>]")                                         \
15163 _(sr_mpls_policy_add,                                                   \
15164   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
15165 _(sr_mpls_policy_del,                                                   \
15166   "bsid <id>")                                                          \
15167 _(bier_table_add_del,                                                   \
15168   "<label> <sub-domain> <set> <bsl> [del]")                             \
15169 _(bier_route_add_del,                                                   \
15170   "<bit-position> <sub-domain> <set> <bsl> via <addr> [table-id <n>]\n" \
15171   "[<intfc> | sw_if_index <id>]"                                        \
15172   "[weight <n>] [del] [multipath]")                                     \
15173 _(sw_interface_set_unnumbered,                                          \
15174   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
15175 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
15176 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
15177   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
15178   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
15179   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
15180 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
15181 _(ip_table_flush, "table <n> [ipv6]")                                   \
15182 _(ip_table_replace_end, "table <n> [ipv6]")                             \
15183 _(set_ip_flow_hash,                                                     \
15184   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
15185 _(sw_interface_ip6_enable_disable,                                      \
15186   "<intfc> | sw_if_index <id> enable | disable")                        \
15187 _(l2_patch_add_del,                                                     \
15188   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
15189   "enable | disable")                                                   \
15190 _(sr_localsid_add_del,                                                  \
15191   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
15192   "fib-table <num> (end.psp) sw_if_index <num>")                        \
15193 _(classify_add_del_table,                                               \
15194   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
15195   " [del] [del-chain] mask <mask-value>\n"                              \
15196   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>\n"             \
15197   " [current-data-flag <n>] [current-data-offset <nn>] [table <nn>]")   \
15198 _(classify_add_del_session,                                             \
15199   "[hit-next|l2-hit-next|acl-hit-next|policer-hit-next] <name|nn>\n"    \
15200   "  table-index <nn> skip_n <nn> match_n <nn> match [hex] [l2]\n"      \
15201   "  [l3 [ip4|ip6]] [action set-ip4-fib-id <nn>]\n"                     \
15202   "  [action set-ip6-fib-id <nn> | action <n> metadata <nn>] [del]")    \
15203 _(classify_set_interface_ip_table,                                      \
15204   "<intfc> | sw_if_index <nn> table <nn>")                              \
15205 _(classify_set_interface_l2_tables,                                     \
15206   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15207   "  [other-table <nn>]")                                               \
15208 _(get_node_index, "node <node-name")                                    \
15209 _(add_node_next, "node <node-name> next <next-node-name>")              \
15210 _(vxlan_offload_rx,                                                     \
15211   "hw { <interface name> | hw_if_index <nn>} "                          \
15212   "rx { <vxlan tunnel name> | sw_if_index <nn> } [del]")                \
15213 _(vxlan_add_del_tunnel,                                                 \
15214   "src <ip-addr> { dst <ip-addr> | group <mcast-ip-addr>\n"             \
15215   "{ <intfc> | mcast_sw_if_index <nn> } [instance <id>]}\n"             \
15216   "vni <vni> [encap-vrf-id <nn>] [decap-next <l2|nn>] [del]")           \
15217 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
15218 _(gre_tunnel_add_del,                                                   \
15219   "src <ip-addr> dst <ip-addr> [outer-fib-id <nn>] [instance <n>]\n"    \
15220   "[teb | erspan <session-id>] [del]")                                  \
15221 _(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                      \
15222 _(l2_fib_clear_table, "")                                               \
15223 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
15224 _(l2_interface_vlan_tag_rewrite,                                        \
15225   "<intfc> | sw_if_index <nn> \n"                                       \
15226   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
15227   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
15228 _(create_vhost_user_if,                                                 \
15229         "socket <filename> [server] [renumber <dev_instance>] "         \
15230         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
15231         "[mac <mac_address>] [packed]")                                 \
15232 _(modify_vhost_user_if,                                                 \
15233         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
15234         "[server] [renumber <dev_instance>] [gso] [packed]")            \
15235 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
15236 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
15237 _(show_version, "")                                                     \
15238 _(show_threads, "")                                                     \
15239 _(vxlan_gpe_add_del_tunnel,                                             \
15240   "local <addr> remote <addr>  | group <mcast-ip-addr>\n"               \
15241   "{ <intfc> | mcast_sw_if_index <nn> } }\n"                            \
15242   "vni <nn> [encap-vrf-id <nn>] [decap-vrf-id <nn>]\n"                  \
15243   "[next-ip4][next-ip6][next-ethernet] [next-nsh] [del]\n")             \
15244 _(vxlan_gpe_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                \
15245 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
15246 _(interface_name_renumber,                                              \
15247   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
15248 _(input_acl_set_interface,                                              \
15249   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15250   "  [l2-table <nn>] [del]")                                            \
15251 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
15252 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
15253 _(ip_dump, "ipv4 | ipv6")                                               \
15254 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
15255 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
15256   "  spid_id <n> ")                                                     \
15257 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
15258   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
15259   "  integ_alg <alg> integ_key <hex>")                                  \
15260 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
15261   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
15262   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
15263   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
15264 _(ipsec_tunnel_if_add_del, "local_spi <n> remote_spi <n>\n"             \
15265   "  crypto_alg <alg> local_crypto_key <hex> remote_crypto_key <hex>\n" \
15266   "  integ_alg <alg> local_integ_key <hex> remote_integ_key <hex>\n"    \
15267   "  local_ip <addr> remote_ip <addr> [esn] [anti_replay] [del]\n"      \
15268   "  [instance <n>]")     \
15269 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
15270 _(ipsec_tunnel_if_set_sa, "<intfc> sa_id <n> <inbound|outbound>\n")     \
15271 _(delete_loopback,"sw_if_index <nn>")                                   \
15272 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
15273 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
15274 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
15275 _(want_interface_events,  "enable|disable")                             \
15276 _(get_first_msg_id, "client <name>")                                    \
15277 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
15278 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
15279   "fib-id <nn> [ip4][ip6][default]")                                    \
15280 _(get_node_graph, " ")                                                  \
15281 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
15282 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
15283 _(ioam_disable, "")                                                     \
15284 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
15285 _(af_packet_delete, "name <host interface name>")                       \
15286 _(af_packet_dump, "")                                                   \
15287 _(policer_add_del, "name <policer name> <params> [del]")                \
15288 _(policer_dump, "[name <policer name>]")                                \
15289 _(policer_classify_set_interface,                                       \
15290   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15291   "  [l2-table <nn>] [del]")                                            \
15292 _(policer_classify_dump, "type [ip4|ip6|l2]")                           \
15293 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
15294 _(mpls_table_dump, "")                                                  \
15295 _(mpls_route_dump, "table-id <ID>")                                     \
15296 _(classify_table_ids, "")                                               \
15297 _(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
15298 _(classify_table_info, "table_id <nn>")                                 \
15299 _(classify_session_dump, "table_id <nn>")                               \
15300 _(set_ipfix_exporter, "collector_address <ip4> [collector_port <nn>] "  \
15301     "src_address <ip4> [vrf_id <nn>] [path_mtu <nn>] "                  \
15302     "[template_interval <nn>] [udp_checksum]")                          \
15303 _(ipfix_exporter_dump, "")                                              \
15304 _(set_ipfix_classify_stream, "[domain <domain-id>] [src_port <src-port>]") \
15305 _(ipfix_classify_stream_dump, "")                                       \
15306 _(ipfix_classify_table_add_del, "table <table-index> ip4|ip6 [tcp|udp]") \
15307 _(ipfix_classify_table_dump, "")                                        \
15308 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
15309 _(sw_interface_span_dump, "[l2]")                                           \
15310 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
15311 _(pg_create_interface, "if_id <nn> [gso-enabled gso-size <size>]")      \
15312 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
15313 _(pg_enable_disable, "[stream <id>] disable")                           \
15314 _(pg_interface_enable_disable_coalesce, "<intf> | sw_if_index <nn> enable | disable")  \
15315 _(ip_source_and_port_range_check_add_del,                               \
15316   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
15317 _(ip_source_and_port_range_check_interface_add_del,                     \
15318   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
15319   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
15320 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
15321 _(l2_interface_pbb_tag_rewrite,                                         \
15322   "<intfc> | sw_if_index <nn> \n"                                       \
15323   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
15324   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
15325 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
15326 _(flow_classify_set_interface,                                          \
15327   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>] [del]") \
15328 _(flow_classify_dump, "type [ip4|ip6]")                                 \
15329 _(ip_table_dump, "")                                                    \
15330 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
15331 _(ip_mtable_dump, "")                                                   \
15332 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
15333 _(feature_enable_disable, "arc_name <arc_name> "                        \
15334   "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]")   \
15335 _(feature_gso_enable_disable, "<intfc> | sw_if_index <nn> "             \
15336   "[enable | disable] ")                                                \
15337 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
15338 "[disable]")                                                            \
15339 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
15340   "mac <mac-address> [del]")                                            \
15341 _(l2_xconnect_dump, "")                                                 \
15342 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
15343 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
15344 _(p2p_ethernet_add, "<intfc> | sw_if_index <nn> remote_mac <mac-address> sub_id <id>") \
15345 _(p2p_ethernet_del, "<intfc> | sw_if_index <nn> remote_mac <mac-address>") \
15346 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
15347 _(sock_init_shm, "size <nnn>")                                          \
15348 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
15349 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
15350   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
15351 _(session_rules_dump, "")                                               \
15352 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
15353 _(output_acl_set_interface,                                             \
15354   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15355   "  [l2-table <nn>] [del]")                                            \
15356 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
15357
15358 /* List of command functions, CLI names map directly to functions */
15359 #define foreach_cli_function                                    \
15360 _(comment, "usage: comment <ignore-rest-of-line>")              \
15361 _(dump_interface_table, "usage: dump_interface_table")          \
15362 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
15363 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
15364 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
15365 _(dump_macro_table, "usage: dump_macro_table ")                 \
15366 _(dump_node_table, "usage: dump_node_table")                    \
15367 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
15368 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
15369 _(elog_disable, "usage: elog_disable")                          \
15370 _(elog_enable, "usage: elog_enable")                            \
15371 _(elog_save, "usage: elog_save <filename>")                     \
15372 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
15373 _(echo, "usage: echo <message>")                                \
15374 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
15375 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
15376 _(help, "usage: help")                                          \
15377 _(q, "usage: quit")                                             \
15378 _(quit, "usage: quit")                                          \
15379 _(search_node_table, "usage: search_node_table <name>...")      \
15380 _(set, "usage: set <variable-name> <value>")                    \
15381 _(script, "usage: script <file-name>")                          \
15382 _(statseg, "usage: statseg")                                    \
15383 _(unset, "usage: unset <variable-name>")
15384
15385 #define _(N,n)                                  \
15386     static void vl_api_##n##_t_handler_uni      \
15387     (vl_api_##n##_t * mp)                       \
15388     {                                           \
15389         vat_main_t * vam = &vat_main;           \
15390         if (vam->json_output) {                 \
15391             vl_api_##n##_t_handler_json(mp);    \
15392         } else {                                \
15393             vl_api_##n##_t_handler(mp);         \
15394         }                                       \
15395     }
15396 foreach_vpe_api_reply_msg;
15397 #if VPP_API_TEST_BUILTIN == 0
15398 foreach_standalone_reply_msg;
15399 #endif
15400 #undef _
15401
15402 void
15403 vat_api_hookup (vat_main_t * vam)
15404 {
15405 #define _(N,n)                                                  \
15406     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
15407                            vl_api_##n##_t_handler_uni,          \
15408                            vl_noop_handler,                     \
15409                            vl_api_##n##_t_endian,               \
15410                            vl_api_##n##_t_print,                \
15411                            sizeof(vl_api_##n##_t), 1);
15412   foreach_vpe_api_reply_msg;
15413 #if VPP_API_TEST_BUILTIN == 0
15414   foreach_standalone_reply_msg;
15415 #endif
15416 #undef _
15417
15418 #if (VPP_API_TEST_BUILTIN==0)
15419   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
15420
15421   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
15422
15423   vam->function_by_name = hash_create_string (0, sizeof (uword));
15424
15425   vam->help_by_name = hash_create_string (0, sizeof (uword));
15426 #endif
15427
15428   /* API messages we can send */
15429 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
15430   foreach_vpe_api_msg;
15431 #undef _
15432
15433   /* Help strings */
15434 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15435   foreach_vpe_api_msg;
15436 #undef _
15437
15438   /* CLI functions */
15439 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
15440   foreach_cli_function;
15441 #undef _
15442
15443   /* Help strings */
15444 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15445   foreach_cli_function;
15446 #undef _
15447 }
15448
15449 #if VPP_API_TEST_BUILTIN
15450 static clib_error_t *
15451 vat_api_hookup_shim (vlib_main_t * vm)
15452 {
15453   vat_api_hookup (&vat_main);
15454   return 0;
15455 }
15456
15457 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
15458 #endif
15459
15460 /*
15461  * fd.io coding-style-patch-verification: ON
15462  *
15463  * Local Variables:
15464  * eval: (c-set-style "gnu")
15465  * End:
15466  */