policer: use ip dscp
[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/vxlan-gpe/vxlan_gpe.h>
32 #include <vnet/udp/udp_local.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) else if (unformat (input, #f)) *r = IP_DSCP_##f;
534   foreach_ip_dscp
535 #undef _
536     else return 0;
537   return 1;
538 }
539
540 static uword
541 unformat_policer_action_type (unformat_input_t * input, va_list * va)
542 {
543   sse2_qos_pol_action_params_st *a
544     = va_arg (*va, sse2_qos_pol_action_params_st *);
545
546   if (unformat (input, "drop"))
547     a->action_type = SSE2_QOS_ACTION_DROP;
548   else if (unformat (input, "transmit"))
549     a->action_type = SSE2_QOS_ACTION_TRANSMIT;
550   else if (unformat (input, "mark-and-transmit %U", unformat_dscp, &a->dscp))
551     a->action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
552   else
553     return 0;
554   return 1;
555 }
556
557 static uword
558 unformat_policer_classify_table_type (unformat_input_t * input, va_list * va)
559 {
560   u32 *r = va_arg (*va, u32 *);
561   u32 tid;
562
563   if (unformat (input, "ip4"))
564     tid = POLICER_CLASSIFY_TABLE_IP4;
565   else if (unformat (input, "ip6"))
566     tid = POLICER_CLASSIFY_TABLE_IP6;
567   else if (unformat (input, "l2"))
568     tid = POLICER_CLASSIFY_TABLE_L2;
569   else
570     return 0;
571
572   *r = tid;
573   return 1;
574 }
575
576 static uword
577 unformat_flow_classify_table_type (unformat_input_t * input, va_list * va)
578 {
579   u32 *r = va_arg (*va, u32 *);
580   u32 tid;
581
582   if (unformat (input, "ip4"))
583     tid = FLOW_CLASSIFY_TABLE_IP4;
584   else if (unformat (input, "ip6"))
585     tid = FLOW_CLASSIFY_TABLE_IP6;
586   else
587     return 0;
588
589   *r = tid;
590   return 1;
591 }
592
593 #if (VPP_API_TEST_BUILTIN==0)
594
595 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
596 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
597 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
598 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
599
600 uword
601 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
602 {
603   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
604   mfib_itf_attribute_t attr;
605
606   old = *iflags;
607   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
608   {
609     if (unformat (input, mfib_itf_flag_long_names[attr]))
610       *iflags |= (1 << attr);
611   }
612   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
613   {
614     if (unformat (input, mfib_itf_flag_names[attr]))
615       *iflags |= (1 << attr);
616   }
617
618   return (old == *iflags ? 0 : 1);
619 }
620
621 uword
622 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
623 {
624   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
625   mfib_entry_attribute_t attr;
626
627   old = *eflags;
628   FOR_EACH_MFIB_ATTRIBUTE (attr)
629   {
630     if (unformat (input, mfib_flag_long_names[attr]))
631       *eflags |= (1 << attr);
632   }
633   FOR_EACH_MFIB_ATTRIBUTE (attr)
634   {
635     if (unformat (input, mfib_flag_names[attr]))
636       *eflags |= (1 << attr);
637   }
638
639   return (old == *eflags ? 0 : 1);
640 }
641
642 u8 *
643 format_ip4_address (u8 * s, va_list * args)
644 {
645   u8 *a = va_arg (*args, u8 *);
646   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
647 }
648
649 u8 *
650 format_ip6_address (u8 * s, va_list * args)
651 {
652   ip6_address_t *a = va_arg (*args, ip6_address_t *);
653   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
654
655   i_max_n_zero = ARRAY_LEN (a->as_u16);
656   max_n_zeros = 0;
657   i_first_zero = i_max_n_zero;
658   n_zeros = 0;
659   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
660     {
661       u32 is_zero = a->as_u16[i] == 0;
662       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
663         {
664           i_first_zero = i;
665           n_zeros = 0;
666         }
667       n_zeros += is_zero;
668       if ((!is_zero && n_zeros > max_n_zeros)
669           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
670         {
671           i_max_n_zero = i_first_zero;
672           max_n_zeros = n_zeros;
673           i_first_zero = ARRAY_LEN (a->as_u16);
674           n_zeros = 0;
675         }
676     }
677
678   last_double_colon = 0;
679   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
680     {
681       if (i == i_max_n_zero && max_n_zeros > 1)
682         {
683           s = format (s, "::");
684           i += max_n_zeros - 1;
685           last_double_colon = 1;
686         }
687       else
688         {
689           s = format (s, "%s%x",
690                       (last_double_colon || i == 0) ? "" : ":",
691                       clib_net_to_host_u16 (a->as_u16[i]));
692           last_double_colon = 0;
693         }
694     }
695
696   return s;
697 }
698
699 /* Format an IP46 address. */
700 u8 *
701 format_ip46_address (u8 * s, va_list * args)
702 {
703   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
704   ip46_type_t type = va_arg (*args, ip46_type_t);
705   int is_ip4 = 1;
706
707   switch (type)
708     {
709     case IP46_TYPE_ANY:
710       is_ip4 = ip46_address_is_ip4 (ip46);
711       break;
712     case IP46_TYPE_IP4:
713       is_ip4 = 1;
714       break;
715     case IP46_TYPE_IP6:
716       is_ip4 = 0;
717       break;
718     }
719
720   return is_ip4 ?
721     format (s, "%U", format_ip4_address, &ip46->ip4) :
722     format (s, "%U", format_ip6_address, &ip46->ip6);
723 }
724
725 u8 *
726 format_ethernet_address (u8 * s, va_list * args)
727 {
728   u8 *a = va_arg (*args, u8 *);
729
730   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
731                  a[0], a[1], a[2], a[3], a[4], a[5]);
732 }
733 #endif
734
735 static void
736 increment_v4_address (vl_api_ip4_address_t * i)
737 {
738   ip4_address_t *a = (ip4_address_t *) i;
739   u32 v;
740
741   v = ntohl (a->as_u32) + 1;
742   a->as_u32 = ntohl (v);
743 }
744
745 static void
746 increment_v6_address (vl_api_ip6_address_t * i)
747 {
748   ip6_address_t *a = (ip6_address_t *) i;
749   u64 v0, v1;
750
751   v0 = clib_net_to_host_u64 (a->as_u64[0]);
752   v1 = clib_net_to_host_u64 (a->as_u64[1]);
753
754   v1 += 1;
755   if (v1 == 0)
756     v0 += 1;
757   a->as_u64[0] = clib_net_to_host_u64 (v0);
758   a->as_u64[1] = clib_net_to_host_u64 (v1);
759 }
760
761 static void
762 increment_address (vl_api_address_t * a)
763 {
764   if (a->af == ADDRESS_IP4)
765     increment_v4_address (&a->un.ip4);
766   else if (a->af == ADDRESS_IP6)
767     increment_v6_address (&a->un.ip6);
768 }
769
770 static void
771 set_ip4_address (vl_api_address_t * a, u32 v)
772 {
773   if (a->af == ADDRESS_IP4)
774     {
775       ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
776       i->as_u32 = v;
777     }
778 }
779
780 void
781 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
782 {
783   if (is_ip4)
784     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
785   else
786     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
787                       sizeof (ip6_address_t));
788 }
789
790 static void
791 increment_mac_address (u8 * mac)
792 {
793   u64 tmp = *((u64 *) mac);
794   tmp = clib_net_to_host_u64 (tmp);
795   tmp += 1 << 16;               /* skip unused (least significant) octets */
796   tmp = clib_host_to_net_u64 (tmp);
797
798   clib_memcpy (mac, &tmp, 6);
799 }
800
801 static void
802 vat_json_object_add_address (vat_json_node_t * node,
803                              const char *str, const vl_api_address_t * addr)
804 {
805   if (ADDRESS_IP6 == addr->af)
806     {
807       struct in6_addr ip6;
808
809       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
810       vat_json_object_add_ip6 (node, str, ip6);
811     }
812   else
813     {
814       struct in_addr ip4;
815
816       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
817       vat_json_object_add_ip4 (node, str, ip4);
818     }
819 }
820
821 static void
822 vat_json_object_add_prefix (vat_json_node_t * node,
823                             const vl_api_prefix_t * prefix)
824 {
825   vat_json_object_add_uint (node, "len", prefix->len);
826   vat_json_object_add_address (node, "address", &prefix->address);
827 }
828
829 static void vl_api_create_loopback_reply_t_handler
830   (vl_api_create_loopback_reply_t * mp)
831 {
832   vat_main_t *vam = &vat_main;
833   i32 retval = ntohl (mp->retval);
834
835   vam->retval = retval;
836   vam->regenerate_interface_table = 1;
837   vam->sw_if_index = ntohl (mp->sw_if_index);
838   vam->result_ready = 1;
839 }
840
841 static void vl_api_create_loopback_reply_t_handler_json
842   (vl_api_create_loopback_reply_t * mp)
843 {
844   vat_main_t *vam = &vat_main;
845   vat_json_node_t node;
846
847   vat_json_init_object (&node);
848   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
849   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
850
851   vat_json_print (vam->ofp, &node);
852   vat_json_free (&node);
853   vam->retval = ntohl (mp->retval);
854   vam->result_ready = 1;
855 }
856
857 static void vl_api_create_loopback_instance_reply_t_handler
858   (vl_api_create_loopback_instance_reply_t * mp)
859 {
860   vat_main_t *vam = &vat_main;
861   i32 retval = ntohl (mp->retval);
862
863   vam->retval = retval;
864   vam->regenerate_interface_table = 1;
865   vam->sw_if_index = ntohl (mp->sw_if_index);
866   vam->result_ready = 1;
867 }
868
869 static void vl_api_create_loopback_instance_reply_t_handler_json
870   (vl_api_create_loopback_instance_reply_t * mp)
871 {
872   vat_main_t *vam = &vat_main;
873   vat_json_node_t node;
874
875   vat_json_init_object (&node);
876   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
877   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
878
879   vat_json_print (vam->ofp, &node);
880   vat_json_free (&node);
881   vam->retval = ntohl (mp->retval);
882   vam->result_ready = 1;
883 }
884
885 static void vl_api_af_packet_create_reply_t_handler
886   (vl_api_af_packet_create_reply_t * mp)
887 {
888   vat_main_t *vam = &vat_main;
889   i32 retval = ntohl (mp->retval);
890
891   vam->retval = retval;
892   vam->regenerate_interface_table = 1;
893   vam->sw_if_index = ntohl (mp->sw_if_index);
894   vam->result_ready = 1;
895 }
896
897 static void vl_api_af_packet_create_reply_t_handler_json
898   (vl_api_af_packet_create_reply_t * mp)
899 {
900   vat_main_t *vam = &vat_main;
901   vat_json_node_t node;
902
903   vat_json_init_object (&node);
904   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
905   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
906
907   vat_json_print (vam->ofp, &node);
908   vat_json_free (&node);
909
910   vam->retval = ntohl (mp->retval);
911   vam->result_ready = 1;
912 }
913
914 static void vl_api_create_vlan_subif_reply_t_handler
915   (vl_api_create_vlan_subif_reply_t * mp)
916 {
917   vat_main_t *vam = &vat_main;
918   i32 retval = ntohl (mp->retval);
919
920   vam->retval = retval;
921   vam->regenerate_interface_table = 1;
922   vam->sw_if_index = ntohl (mp->sw_if_index);
923   vam->result_ready = 1;
924 }
925
926 static void vl_api_create_vlan_subif_reply_t_handler_json
927   (vl_api_create_vlan_subif_reply_t * mp)
928 {
929   vat_main_t *vam = &vat_main;
930   vat_json_node_t node;
931
932   vat_json_init_object (&node);
933   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
934   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
935
936   vat_json_print (vam->ofp, &node);
937   vat_json_free (&node);
938
939   vam->retval = ntohl (mp->retval);
940   vam->result_ready = 1;
941 }
942
943 static void vl_api_create_subif_reply_t_handler
944   (vl_api_create_subif_reply_t * mp)
945 {
946   vat_main_t *vam = &vat_main;
947   i32 retval = ntohl (mp->retval);
948
949   vam->retval = retval;
950   vam->regenerate_interface_table = 1;
951   vam->sw_if_index = ntohl (mp->sw_if_index);
952   vam->result_ready = 1;
953 }
954
955 static void vl_api_create_subif_reply_t_handler_json
956   (vl_api_create_subif_reply_t * mp)
957 {
958   vat_main_t *vam = &vat_main;
959   vat_json_node_t node;
960
961   vat_json_init_object (&node);
962   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
963   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
964
965   vat_json_print (vam->ofp, &node);
966   vat_json_free (&node);
967
968   vam->retval = ntohl (mp->retval);
969   vam->result_ready = 1;
970 }
971
972 static void vl_api_interface_name_renumber_reply_t_handler
973   (vl_api_interface_name_renumber_reply_t * mp)
974 {
975   vat_main_t *vam = &vat_main;
976   i32 retval = ntohl (mp->retval);
977
978   vam->retval = retval;
979   vam->regenerate_interface_table = 1;
980   vam->result_ready = 1;
981 }
982
983 static void vl_api_interface_name_renumber_reply_t_handler_json
984   (vl_api_interface_name_renumber_reply_t * mp)
985 {
986   vat_main_t *vam = &vat_main;
987   vat_json_node_t node;
988
989   vat_json_init_object (&node);
990   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
991
992   vat_json_print (vam->ofp, &node);
993   vat_json_free (&node);
994
995   vam->retval = ntohl (mp->retval);
996   vam->result_ready = 1;
997 }
998
999 /*
1000  * Special-case: build the interface table, maintain
1001  * the next loopback sw_if_index vbl.
1002  */
1003 static void vl_api_sw_interface_details_t_handler
1004   (vl_api_sw_interface_details_t * mp)
1005 {
1006   vat_main_t *vam = &vat_main;
1007   u8 *s = format (0, "%s%c", mp->interface_name, 0);
1008
1009   hash_set_mem (vam->sw_if_index_by_interface_name, s,
1010                 ntohl (mp->sw_if_index));
1011
1012   /* In sub interface case, fill the sub interface table entry */
1013   if (mp->sw_if_index != mp->sup_sw_if_index)
1014     {
1015       sw_interface_subif_t *sub = NULL;
1016
1017       vec_add2 (vam->sw_if_subif_table, sub, 1);
1018
1019       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
1020       strncpy ((char *) sub->interface_name, (char *) s,
1021                vec_len (sub->interface_name));
1022       sub->sw_if_index = ntohl (mp->sw_if_index);
1023       sub->sub_id = ntohl (mp->sub_id);
1024
1025       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
1026
1027       sub->sub_number_of_tags = mp->sub_number_of_tags;
1028       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
1029       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
1030
1031       /* vlan tag rewrite */
1032       sub->vtr_op = ntohl (mp->vtr_op);
1033       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
1034       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
1035       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
1036     }
1037 }
1038
1039 static void vl_api_sw_interface_details_t_handler_json
1040   (vl_api_sw_interface_details_t * mp)
1041 {
1042   vat_main_t *vam = &vat_main;
1043   vat_json_node_t *node = NULL;
1044
1045   if (VAT_JSON_ARRAY != vam->json_tree.type)
1046     {
1047       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1048       vat_json_init_array (&vam->json_tree);
1049     }
1050   node = vat_json_array_add (&vam->json_tree);
1051
1052   vat_json_init_object (node);
1053   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1054   vat_json_object_add_uint (node, "sup_sw_if_index",
1055                             ntohl (mp->sup_sw_if_index));
1056   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
1057                              sizeof (mp->l2_address));
1058   vat_json_object_add_string_copy (node, "interface_name",
1059                                    mp->interface_name);
1060   vat_json_object_add_string_copy (node, "interface_dev_type",
1061                                    mp->interface_dev_type);
1062   vat_json_object_add_uint (node, "flags", mp->flags);
1063   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
1064   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
1065   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
1066   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
1067   vat_json_object_add_uint (node, "sub_number_of_tags",
1068                             mp->sub_number_of_tags);
1069   vat_json_object_add_uint (node, "sub_outer_vlan_id",
1070                             ntohs (mp->sub_outer_vlan_id));
1071   vat_json_object_add_uint (node, "sub_inner_vlan_id",
1072                             ntohs (mp->sub_inner_vlan_id));
1073   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
1074   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
1075   vat_json_object_add_uint (node, "vtr_push_dot1q",
1076                             ntohl (mp->vtr_push_dot1q));
1077   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
1078   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
1079   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
1080     {
1081       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
1082                                        format (0, "%U",
1083                                                format_ethernet_address,
1084                                                &mp->b_dmac));
1085       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
1086                                        format (0, "%U",
1087                                                format_ethernet_address,
1088                                                &mp->b_smac));
1089       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
1090       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
1091     }
1092 }
1093
1094 #if VPP_API_TEST_BUILTIN == 0
1095 static void vl_api_sw_interface_event_t_handler
1096   (vl_api_sw_interface_event_t * mp)
1097 {
1098   vat_main_t *vam = &vat_main;
1099   if (vam->interface_event_display)
1100     errmsg ("interface flags: sw_if_index %d %s %s",
1101             ntohl (mp->sw_if_index),
1102             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
1103             "admin-up" : "admin-down",
1104             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
1105             "link-up" : "link-down");
1106 }
1107 #endif
1108
1109 __clib_unused static void
1110 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
1111 {
1112   /* JSON output not supported */
1113 }
1114
1115 static void
1116 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
1117 {
1118   vat_main_t *vam = &vat_main;
1119   i32 retval = ntohl (mp->retval);
1120
1121   vam->retval = retval;
1122   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
1123   vam->result_ready = 1;
1124 }
1125
1126 static void
1127 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
1128 {
1129   vat_main_t *vam = &vat_main;
1130   vat_json_node_t node;
1131   void *oldheap;
1132   u8 *reply;
1133
1134   vat_json_init_object (&node);
1135   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1136   vat_json_object_add_uint (&node, "reply_in_shmem",
1137                             ntohl (mp->reply_in_shmem));
1138   /* Toss the shared-memory original... */
1139   oldheap = vl_msg_push_heap ();
1140
1141   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1142   vec_free (reply);
1143
1144   vl_msg_pop_heap (oldheap);
1145
1146   vat_json_print (vam->ofp, &node);
1147   vat_json_free (&node);
1148
1149   vam->retval = ntohl (mp->retval);
1150   vam->result_ready = 1;
1151 }
1152
1153 static void
1154 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
1155 {
1156   vat_main_t *vam = &vat_main;
1157   i32 retval = ntohl (mp->retval);
1158
1159   vec_reset_length (vam->cmd_reply);
1160
1161   vam->retval = retval;
1162   if (retval == 0)
1163     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1164   vam->result_ready = 1;
1165 }
1166
1167 static void
1168 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
1169 {
1170   vat_main_t *vam = &vat_main;
1171   vat_json_node_t node;
1172   u8 *reply = 0;                /* reply vector */
1173
1174   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1175   vec_reset_length (vam->cmd_reply);
1176
1177   vat_json_init_object (&node);
1178   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1179   vat_json_object_add_string_copy (&node, "reply", reply);
1180
1181   vat_json_print (vam->ofp, &node);
1182   vat_json_free (&node);
1183   vec_free (reply);
1184
1185   vam->retval = ntohl (mp->retval);
1186   vam->result_ready = 1;
1187 }
1188
1189 static void vl_api_classify_add_del_table_reply_t_handler
1190   (vl_api_classify_add_del_table_reply_t * mp)
1191 {
1192   vat_main_t *vam = &vat_main;
1193   i32 retval = ntohl (mp->retval);
1194   if (vam->async_mode)
1195     {
1196       vam->async_errors += (retval < 0);
1197     }
1198   else
1199     {
1200       vam->retval = retval;
1201       if (retval == 0 &&
1202           ((mp->new_table_index != 0xFFFFFFFF) ||
1203            (mp->skip_n_vectors != 0xFFFFFFFF) ||
1204            (mp->match_n_vectors != 0xFFFFFFFF)))
1205         /*
1206          * Note: this is just barely thread-safe, depends on
1207          * the main thread spinning waiting for an answer...
1208          */
1209         errmsg ("new index %d, skip_n_vectors %d, match_n_vectors %d",
1210                 ntohl (mp->new_table_index),
1211                 ntohl (mp->skip_n_vectors), ntohl (mp->match_n_vectors));
1212       vam->result_ready = 1;
1213     }
1214 }
1215
1216 static void vl_api_classify_add_del_table_reply_t_handler_json
1217   (vl_api_classify_add_del_table_reply_t * mp)
1218 {
1219   vat_main_t *vam = &vat_main;
1220   vat_json_node_t node;
1221
1222   vat_json_init_object (&node);
1223   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1224   vat_json_object_add_uint (&node, "new_table_index",
1225                             ntohl (mp->new_table_index));
1226   vat_json_object_add_uint (&node, "skip_n_vectors",
1227                             ntohl (mp->skip_n_vectors));
1228   vat_json_object_add_uint (&node, "match_n_vectors",
1229                             ntohl (mp->match_n_vectors));
1230
1231   vat_json_print (vam->ofp, &node);
1232   vat_json_free (&node);
1233
1234   vam->retval = ntohl (mp->retval);
1235   vam->result_ready = 1;
1236 }
1237
1238 static void vl_api_get_node_index_reply_t_handler
1239   (vl_api_get_node_index_reply_t * mp)
1240 {
1241   vat_main_t *vam = &vat_main;
1242   i32 retval = ntohl (mp->retval);
1243   if (vam->async_mode)
1244     {
1245       vam->async_errors += (retval < 0);
1246     }
1247   else
1248     {
1249       vam->retval = retval;
1250       if (retval == 0)
1251         errmsg ("node index %d", ntohl (mp->node_index));
1252       vam->result_ready = 1;
1253     }
1254 }
1255
1256 static void vl_api_get_node_index_reply_t_handler_json
1257   (vl_api_get_node_index_reply_t * mp)
1258 {
1259   vat_main_t *vam = &vat_main;
1260   vat_json_node_t node;
1261
1262   vat_json_init_object (&node);
1263   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1264   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1265
1266   vat_json_print (vam->ofp, &node);
1267   vat_json_free (&node);
1268
1269   vam->retval = ntohl (mp->retval);
1270   vam->result_ready = 1;
1271 }
1272
1273 static void vl_api_get_next_index_reply_t_handler
1274   (vl_api_get_next_index_reply_t * mp)
1275 {
1276   vat_main_t *vam = &vat_main;
1277   i32 retval = ntohl (mp->retval);
1278   if (vam->async_mode)
1279     {
1280       vam->async_errors += (retval < 0);
1281     }
1282   else
1283     {
1284       vam->retval = retval;
1285       if (retval == 0)
1286         errmsg ("next node index %d", ntohl (mp->next_index));
1287       vam->result_ready = 1;
1288     }
1289 }
1290
1291 static void vl_api_get_next_index_reply_t_handler_json
1292   (vl_api_get_next_index_reply_t * mp)
1293 {
1294   vat_main_t *vam = &vat_main;
1295   vat_json_node_t node;
1296
1297   vat_json_init_object (&node);
1298   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1299   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1300
1301   vat_json_print (vam->ofp, &node);
1302   vat_json_free (&node);
1303
1304   vam->retval = ntohl (mp->retval);
1305   vam->result_ready = 1;
1306 }
1307
1308 static void vl_api_add_node_next_reply_t_handler
1309   (vl_api_add_node_next_reply_t * mp)
1310 {
1311   vat_main_t *vam = &vat_main;
1312   i32 retval = ntohl (mp->retval);
1313   if (vam->async_mode)
1314     {
1315       vam->async_errors += (retval < 0);
1316     }
1317   else
1318     {
1319       vam->retval = retval;
1320       if (retval == 0)
1321         errmsg ("next index %d", ntohl (mp->next_index));
1322       vam->result_ready = 1;
1323     }
1324 }
1325
1326 static void vl_api_add_node_next_reply_t_handler_json
1327   (vl_api_add_node_next_reply_t * mp)
1328 {
1329   vat_main_t *vam = &vat_main;
1330   vat_json_node_t node;
1331
1332   vat_json_init_object (&node);
1333   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1334   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1335
1336   vat_json_print (vam->ofp, &node);
1337   vat_json_free (&node);
1338
1339   vam->retval = ntohl (mp->retval);
1340   vam->result_ready = 1;
1341 }
1342
1343 static void vl_api_show_version_reply_t_handler
1344   (vl_api_show_version_reply_t * mp)
1345 {
1346   vat_main_t *vam = &vat_main;
1347   i32 retval = ntohl (mp->retval);
1348
1349   if (retval >= 0)
1350     {
1351       errmsg ("        program: %s", mp->program);
1352       errmsg ("        version: %s", mp->version);
1353       errmsg ("     build date: %s", mp->build_date);
1354       errmsg ("build directory: %s", mp->build_directory);
1355     }
1356   vam->retval = retval;
1357   vam->result_ready = 1;
1358 }
1359
1360 static void vl_api_show_version_reply_t_handler_json
1361   (vl_api_show_version_reply_t * mp)
1362 {
1363   vat_main_t *vam = &vat_main;
1364   vat_json_node_t node;
1365
1366   vat_json_init_object (&node);
1367   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1368   vat_json_object_add_string_copy (&node, "program", mp->program);
1369   vat_json_object_add_string_copy (&node, "version", mp->version);
1370   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1371   vat_json_object_add_string_copy (&node, "build_directory",
1372                                    mp->build_directory);
1373
1374   vat_json_print (vam->ofp, &node);
1375   vat_json_free (&node);
1376
1377   vam->retval = ntohl (mp->retval);
1378   vam->result_ready = 1;
1379 }
1380
1381 static void vl_api_show_threads_reply_t_handler
1382   (vl_api_show_threads_reply_t * mp)
1383 {
1384   vat_main_t *vam = &vat_main;
1385   i32 retval = ntohl (mp->retval);
1386   int i, count = 0;
1387
1388   if (retval >= 0)
1389     count = ntohl (mp->count);
1390
1391   for (i = 0; i < count; i++)
1392     print (vam->ofp,
1393            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1394            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1395            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1396            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1397            ntohl (mp->thread_data[i].cpu_socket));
1398
1399   vam->retval = retval;
1400   vam->result_ready = 1;
1401 }
1402
1403 static void vl_api_show_threads_reply_t_handler_json
1404   (vl_api_show_threads_reply_t * mp)
1405 {
1406   vat_main_t *vam = &vat_main;
1407   vat_json_node_t node;
1408   vl_api_thread_data_t *td;
1409   i32 retval = ntohl (mp->retval);
1410   int i, count = 0;
1411
1412   if (retval >= 0)
1413     count = ntohl (mp->count);
1414
1415   vat_json_init_object (&node);
1416   vat_json_object_add_int (&node, "retval", retval);
1417   vat_json_object_add_uint (&node, "count", count);
1418
1419   for (i = 0; i < count; i++)
1420     {
1421       td = &mp->thread_data[i];
1422       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1423       vat_json_object_add_string_copy (&node, "name", td->name);
1424       vat_json_object_add_string_copy (&node, "type", td->type);
1425       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1426       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1427       vat_json_object_add_int (&node, "core", ntohl (td->id));
1428       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1429     }
1430
1431   vat_json_print (vam->ofp, &node);
1432   vat_json_free (&node);
1433
1434   vam->retval = retval;
1435   vam->result_ready = 1;
1436 }
1437
1438 static int
1439 api_show_threads (vat_main_t * vam)
1440 {
1441   vl_api_show_threads_t *mp;
1442   int ret;
1443
1444   print (vam->ofp,
1445          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1446          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1447
1448   M (SHOW_THREADS, mp);
1449
1450   S (mp);
1451   W (ret);
1452   return ret;
1453 }
1454
1455 static void
1456 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1457 {
1458   u32 n_macs = ntohl (mp->n_macs);
1459   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1460           ntohl (mp->pid), mp->client_index, n_macs);
1461   int i;
1462   for (i = 0; i < n_macs; i++)
1463     {
1464       vl_api_mac_entry_t *mac = &mp->mac[i];
1465       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1466               i + 1, ntohl (mac->sw_if_index),
1467               format_ethernet_address, mac->mac_addr, mac->action);
1468       if (i == 1000)
1469         break;
1470     }
1471 }
1472
1473 static void
1474 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1475 {
1476   /* JSON output not supported */
1477 }
1478
1479 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1480 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1481
1482 /*
1483  * Special-case: build the bridge domain table, maintain
1484  * the next bd id vbl.
1485  */
1486 static void vl_api_bridge_domain_details_t_handler
1487   (vl_api_bridge_domain_details_t * mp)
1488 {
1489   vat_main_t *vam = &vat_main;
1490   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1491   int i;
1492
1493   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1494          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1495
1496   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1497          ntohl (mp->bd_id), mp->learn, mp->forward,
1498          mp->flood, ntohl (mp->bvi_sw_if_index),
1499          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1500
1501   if (n_sw_ifs)
1502     {
1503       vl_api_bridge_domain_sw_if_t *sw_ifs;
1504       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1505              "Interface Name");
1506
1507       sw_ifs = mp->sw_if_details;
1508       for (i = 0; i < n_sw_ifs; i++)
1509         {
1510           u8 *sw_if_name = 0;
1511           u32 sw_if_index;
1512           hash_pair_t *p;
1513
1514           sw_if_index = ntohl (sw_ifs->sw_if_index);
1515
1516           /* *INDENT-OFF* */
1517           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1518                              ({
1519                                if ((u32) p->value[0] == sw_if_index)
1520                                  {
1521                                    sw_if_name = (u8 *)(p->key);
1522                                    break;
1523                                  }
1524                              }));
1525           /* *INDENT-ON* */
1526           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1527                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1528                  "sw_if_index not found!");
1529
1530           sw_ifs++;
1531         }
1532     }
1533 }
1534
1535 static void vl_api_bridge_domain_details_t_handler_json
1536   (vl_api_bridge_domain_details_t * mp)
1537 {
1538   vat_main_t *vam = &vat_main;
1539   vat_json_node_t *node, *array = NULL;
1540   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1541
1542   if (VAT_JSON_ARRAY != vam->json_tree.type)
1543     {
1544       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1545       vat_json_init_array (&vam->json_tree);
1546     }
1547   node = vat_json_array_add (&vam->json_tree);
1548
1549   vat_json_init_object (node);
1550   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1551   vat_json_object_add_uint (node, "flood", mp->flood);
1552   vat_json_object_add_uint (node, "forward", mp->forward);
1553   vat_json_object_add_uint (node, "learn", mp->learn);
1554   vat_json_object_add_uint (node, "bvi_sw_if_index",
1555                             ntohl (mp->bvi_sw_if_index));
1556   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1557   array = vat_json_object_add (node, "sw_if");
1558   vat_json_init_array (array);
1559
1560
1561
1562   if (n_sw_ifs)
1563     {
1564       vl_api_bridge_domain_sw_if_t *sw_ifs;
1565       int i;
1566
1567       sw_ifs = mp->sw_if_details;
1568       for (i = 0; i < n_sw_ifs; i++)
1569         {
1570           node = vat_json_array_add (array);
1571           vat_json_init_object (node);
1572           vat_json_object_add_uint (node, "sw_if_index",
1573                                     ntohl (sw_ifs->sw_if_index));
1574           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1575           sw_ifs++;
1576         }
1577     }
1578 }
1579
1580 static void vl_api_control_ping_reply_t_handler
1581   (vl_api_control_ping_reply_t * mp)
1582 {
1583   vat_main_t *vam = &vat_main;
1584   i32 retval = ntohl (mp->retval);
1585   if (vam->async_mode)
1586     {
1587       vam->async_errors += (retval < 0);
1588     }
1589   else
1590     {
1591       vam->retval = retval;
1592       vam->result_ready = 1;
1593     }
1594   if (vam->socket_client_main)
1595     vam->socket_client_main->control_pings_outstanding--;
1596 }
1597
1598 static void vl_api_control_ping_reply_t_handler_json
1599   (vl_api_control_ping_reply_t * mp)
1600 {
1601   vat_main_t *vam = &vat_main;
1602   i32 retval = ntohl (mp->retval);
1603
1604   if (VAT_JSON_NONE != vam->json_tree.type)
1605     {
1606       vat_json_print (vam->ofp, &vam->json_tree);
1607       vat_json_free (&vam->json_tree);
1608       vam->json_tree.type = VAT_JSON_NONE;
1609     }
1610   else
1611     {
1612       /* just print [] */
1613       vat_json_init_array (&vam->json_tree);
1614       vat_json_print (vam->ofp, &vam->json_tree);
1615       vam->json_tree.type = VAT_JSON_NONE;
1616     }
1617
1618   vam->retval = retval;
1619   vam->result_ready = 1;
1620 }
1621
1622 static void
1623   vl_api_bridge_domain_set_mac_age_reply_t_handler
1624   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1625 {
1626   vat_main_t *vam = &vat_main;
1627   i32 retval = ntohl (mp->retval);
1628   if (vam->async_mode)
1629     {
1630       vam->async_errors += (retval < 0);
1631     }
1632   else
1633     {
1634       vam->retval = retval;
1635       vam->result_ready = 1;
1636     }
1637 }
1638
1639 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1640   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1641 {
1642   vat_main_t *vam = &vat_main;
1643   vat_json_node_t node;
1644
1645   vat_json_init_object (&node);
1646   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1647
1648   vat_json_print (vam->ofp, &node);
1649   vat_json_free (&node);
1650
1651   vam->retval = ntohl (mp->retval);
1652   vam->result_ready = 1;
1653 }
1654
1655 static void
1656 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1657 {
1658   vat_main_t *vam = &vat_main;
1659   i32 retval = ntohl (mp->retval);
1660   if (vam->async_mode)
1661     {
1662       vam->async_errors += (retval < 0);
1663     }
1664   else
1665     {
1666       vam->retval = retval;
1667       vam->result_ready = 1;
1668     }
1669 }
1670
1671 static void vl_api_l2_flags_reply_t_handler_json
1672   (vl_api_l2_flags_reply_t * mp)
1673 {
1674   vat_main_t *vam = &vat_main;
1675   vat_json_node_t node;
1676
1677   vat_json_init_object (&node);
1678   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1679   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1680                             ntohl (mp->resulting_feature_bitmap));
1681
1682   vat_json_print (vam->ofp, &node);
1683   vat_json_free (&node);
1684
1685   vam->retval = ntohl (mp->retval);
1686   vam->result_ready = 1;
1687 }
1688
1689 static void vl_api_bridge_flags_reply_t_handler
1690   (vl_api_bridge_flags_reply_t * mp)
1691 {
1692   vat_main_t *vam = &vat_main;
1693   i32 retval = ntohl (mp->retval);
1694   if (vam->async_mode)
1695     {
1696       vam->async_errors += (retval < 0);
1697     }
1698   else
1699     {
1700       vam->retval = retval;
1701       vam->result_ready = 1;
1702     }
1703 }
1704
1705 static void vl_api_bridge_flags_reply_t_handler_json
1706   (vl_api_bridge_flags_reply_t * mp)
1707 {
1708   vat_main_t *vam = &vat_main;
1709   vat_json_node_t node;
1710
1711   vat_json_init_object (&node);
1712   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1713   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1714                             ntohl (mp->resulting_feature_bitmap));
1715
1716   vat_json_print (vam->ofp, &node);
1717   vat_json_free (&node);
1718
1719   vam->retval = ntohl (mp->retval);
1720   vam->result_ready = 1;
1721 }
1722
1723 static void
1724 vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp)
1725 {
1726   vat_main_t *vam = &vat_main;
1727   i32 retval = ntohl (mp->retval);
1728   if (vam->async_mode)
1729     {
1730       vam->async_errors += (retval < 0);
1731     }
1732   else
1733     {
1734       vam->retval = retval;
1735       vam->sw_if_index = ntohl (mp->sw_if_index);
1736       vam->result_ready = 1;
1737     }
1738
1739 }
1740
1741 static void vl_api_tap_create_v2_reply_t_handler_json
1742   (vl_api_tap_create_v2_reply_t * mp)
1743 {
1744   vat_main_t *vam = &vat_main;
1745   vat_json_node_t node;
1746
1747   vat_json_init_object (&node);
1748   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1749   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1750
1751   vat_json_print (vam->ofp, &node);
1752   vat_json_free (&node);
1753
1754   vam->retval = ntohl (mp->retval);
1755   vam->result_ready = 1;
1756
1757 }
1758
1759 static void
1760 vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp)
1761 {
1762   vat_main_t *vam = &vat_main;
1763   i32 retval = ntohl (mp->retval);
1764   if (vam->async_mode)
1765     {
1766       vam->async_errors += (retval < 0);
1767     }
1768   else
1769     {
1770       vam->retval = retval;
1771       vam->result_ready = 1;
1772     }
1773 }
1774
1775 static void vl_api_tap_delete_v2_reply_t_handler_json
1776   (vl_api_tap_delete_v2_reply_t * mp)
1777 {
1778   vat_main_t *vam = &vat_main;
1779   vat_json_node_t node;
1780
1781   vat_json_init_object (&node);
1782   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1783
1784   vat_json_print (vam->ofp, &node);
1785   vat_json_free (&node);
1786
1787   vam->retval = ntohl (mp->retval);
1788   vam->result_ready = 1;
1789 }
1790
1791 static void
1792 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1793                                           mp)
1794 {
1795   vat_main_t *vam = &vat_main;
1796   i32 retval = ntohl (mp->retval);
1797   if (vam->async_mode)
1798     {
1799       vam->async_errors += (retval < 0);
1800     }
1801   else
1802     {
1803       vam->retval = retval;
1804       vam->sw_if_index = ntohl (mp->sw_if_index);
1805       vam->result_ready = 1;
1806     }
1807 }
1808
1809 static void vl_api_virtio_pci_create_reply_t_handler_json
1810   (vl_api_virtio_pci_create_reply_t * mp)
1811 {
1812   vat_main_t *vam = &vat_main;
1813   vat_json_node_t node;
1814
1815   vat_json_init_object (&node);
1816   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1817   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1818
1819   vat_json_print (vam->ofp, &node);
1820   vat_json_free (&node);
1821
1822   vam->retval = ntohl (mp->retval);
1823   vam->result_ready = 1;
1824
1825 }
1826
1827 static void
1828   vl_api_virtio_pci_create_v2_reply_t_handler
1829   (vl_api_virtio_pci_create_v2_reply_t * mp)
1830 {
1831   vat_main_t *vam = &vat_main;
1832   i32 retval = ntohl (mp->retval);
1833   if (vam->async_mode)
1834     {
1835       vam->async_errors += (retval < 0);
1836     }
1837   else
1838     {
1839       vam->retval = retval;
1840       vam->sw_if_index = ntohl (mp->sw_if_index);
1841       vam->result_ready = 1;
1842     }
1843 }
1844
1845 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1846   (vl_api_virtio_pci_create_v2_reply_t * mp)
1847 {
1848   vat_main_t *vam = &vat_main;
1849   vat_json_node_t node;
1850
1851   vat_json_init_object (&node);
1852   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1853   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1854
1855   vat_json_print (vam->ofp, &node);
1856   vat_json_free (&node);
1857
1858   vam->retval = ntohl (mp->retval);
1859   vam->result_ready = 1;
1860 }
1861
1862 static void
1863 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1864                                           mp)
1865 {
1866   vat_main_t *vam = &vat_main;
1867   i32 retval = ntohl (mp->retval);
1868   if (vam->async_mode)
1869     {
1870       vam->async_errors += (retval < 0);
1871     }
1872   else
1873     {
1874       vam->retval = retval;
1875       vam->result_ready = 1;
1876     }
1877 }
1878
1879 static void vl_api_virtio_pci_delete_reply_t_handler_json
1880   (vl_api_virtio_pci_delete_reply_t * mp)
1881 {
1882   vat_main_t *vam = &vat_main;
1883   vat_json_node_t node;
1884
1885   vat_json_init_object (&node);
1886   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1887
1888   vat_json_print (vam->ofp, &node);
1889   vat_json_free (&node);
1890
1891   vam->retval = ntohl (mp->retval);
1892   vam->result_ready = 1;
1893 }
1894
1895 static void
1896 vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
1897 {
1898   vat_main_t *vam = &vat_main;
1899   i32 retval = ntohl (mp->retval);
1900
1901   if (vam->async_mode)
1902     {
1903       vam->async_errors += (retval < 0);
1904     }
1905   else
1906     {
1907       vam->retval = retval;
1908       vam->sw_if_index = ntohl (mp->sw_if_index);
1909       vam->result_ready = 1;
1910     }
1911 }
1912
1913 static void vl_api_bond_create_reply_t_handler_json
1914   (vl_api_bond_create_reply_t * mp)
1915 {
1916   vat_main_t *vam = &vat_main;
1917   vat_json_node_t node;
1918
1919   vat_json_init_object (&node);
1920   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1921   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1922
1923   vat_json_print (vam->ofp, &node);
1924   vat_json_free (&node);
1925
1926   vam->retval = ntohl (mp->retval);
1927   vam->result_ready = 1;
1928 }
1929
1930 static void
1931 vl_api_bond_create2_reply_t_handler (vl_api_bond_create2_reply_t * mp)
1932 {
1933   vat_main_t *vam = &vat_main;
1934   i32 retval = ntohl (mp->retval);
1935
1936   if (vam->async_mode)
1937     {
1938       vam->async_errors += (retval < 0);
1939     }
1940   else
1941     {
1942       vam->retval = retval;
1943       vam->sw_if_index = ntohl (mp->sw_if_index);
1944       vam->result_ready = 1;
1945     }
1946 }
1947
1948 static void vl_api_bond_create2_reply_t_handler_json
1949   (vl_api_bond_create2_reply_t * mp)
1950 {
1951   vat_main_t *vam = &vat_main;
1952   vat_json_node_t node;
1953
1954   vat_json_init_object (&node);
1955   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1956   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1957
1958   vat_json_print (vam->ofp, &node);
1959   vat_json_free (&node);
1960
1961   vam->retval = ntohl (mp->retval);
1962   vam->result_ready = 1;
1963 }
1964
1965 static void
1966 vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
1967 {
1968   vat_main_t *vam = &vat_main;
1969   i32 retval = ntohl (mp->retval);
1970
1971   if (vam->async_mode)
1972     {
1973       vam->async_errors += (retval < 0);
1974     }
1975   else
1976     {
1977       vam->retval = retval;
1978       vam->result_ready = 1;
1979     }
1980 }
1981
1982 static void vl_api_bond_delete_reply_t_handler_json
1983   (vl_api_bond_delete_reply_t * mp)
1984 {
1985   vat_main_t *vam = &vat_main;
1986   vat_json_node_t node;
1987
1988   vat_json_init_object (&node);
1989   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1990
1991   vat_json_print (vam->ofp, &node);
1992   vat_json_free (&node);
1993
1994   vam->retval = ntohl (mp->retval);
1995   vam->result_ready = 1;
1996 }
1997
1998 static void
1999 vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t * mp)
2000 {
2001   vat_main_t *vam = &vat_main;
2002   i32 retval = ntohl (mp->retval);
2003
2004   if (vam->async_mode)
2005     {
2006       vam->async_errors += (retval < 0);
2007     }
2008   else
2009     {
2010       vam->retval = retval;
2011       vam->result_ready = 1;
2012     }
2013 }
2014
2015 static void vl_api_bond_add_member_reply_t_handler_json
2016   (vl_api_bond_add_member_reply_t * mp)
2017 {
2018   vat_main_t *vam = &vat_main;
2019   vat_json_node_t node;
2020
2021   vat_json_init_object (&node);
2022   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2023
2024   vat_json_print (vam->ofp, &node);
2025   vat_json_free (&node);
2026
2027   vam->retval = ntohl (mp->retval);
2028   vam->result_ready = 1;
2029 }
2030
2031 static void
2032 vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *
2033                                            mp)
2034 {
2035   vat_main_t *vam = &vat_main;
2036   i32 retval = ntohl (mp->retval);
2037
2038   if (vam->async_mode)
2039     {
2040       vam->async_errors += (retval < 0);
2041     }
2042   else
2043     {
2044       vam->retval = retval;
2045       vam->result_ready = 1;
2046     }
2047 }
2048
2049 static void vl_api_bond_detach_member_reply_t_handler_json
2050   (vl_api_bond_detach_member_reply_t * mp)
2051 {
2052   vat_main_t *vam = &vat_main;
2053   vat_json_node_t node;
2054
2055   vat_json_init_object (&node);
2056   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2057
2058   vat_json_print (vam->ofp, &node);
2059   vat_json_free (&node);
2060
2061   vam->retval = ntohl (mp->retval);
2062   vam->result_ready = 1;
2063 }
2064
2065 static int
2066 api_sw_interface_set_bond_weight (vat_main_t * vam)
2067 {
2068   unformat_input_t *i = vam->input;
2069   vl_api_sw_interface_set_bond_weight_t *mp;
2070   u32 sw_if_index = ~0;
2071   u32 weight = 0;
2072   u8 weight_enter = 0;
2073   int ret;
2074
2075   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2076     {
2077       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2078         ;
2079       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2080         ;
2081       else if (unformat (i, "weight %u", &weight))
2082         weight_enter = 1;
2083       else
2084         break;
2085     }
2086
2087   if (sw_if_index == ~0)
2088     {
2089       errmsg ("missing interface name or sw_if_index");
2090       return -99;
2091     }
2092   if (weight_enter == 0)
2093     {
2094       errmsg ("missing valid weight");
2095       return -99;
2096     }
2097
2098   /* Construct the API message */
2099   M (SW_INTERFACE_SET_BOND_WEIGHT, mp);
2100   mp->sw_if_index = ntohl (sw_if_index);
2101   mp->weight = ntohl (weight);
2102
2103   S (mp);
2104   W (ret);
2105   return ret;
2106 }
2107
2108 static void vl_api_sw_bond_interface_details_t_handler
2109   (vl_api_sw_bond_interface_details_t * mp)
2110 {
2111   vat_main_t *vam = &vat_main;
2112
2113   print (vam->ofp,
2114          "%-16s %-12d %-12U %-13U %-14u %-14u",
2115          mp->interface_name, ntohl (mp->sw_if_index),
2116          format_bond_mode, ntohl (mp->mode), format_bond_load_balance,
2117          ntohl (mp->lb), ntohl (mp->active_members), ntohl (mp->members));
2118 }
2119
2120 static void vl_api_sw_bond_interface_details_t_handler_json
2121   (vl_api_sw_bond_interface_details_t * mp)
2122 {
2123   vat_main_t *vam = &vat_main;
2124   vat_json_node_t *node = NULL;
2125
2126   if (VAT_JSON_ARRAY != vam->json_tree.type)
2127     {
2128       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2129       vat_json_init_array (&vam->json_tree);
2130     }
2131   node = vat_json_array_add (&vam->json_tree);
2132
2133   vat_json_init_object (node);
2134   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2135   vat_json_object_add_string_copy (node, "interface_name",
2136                                    mp->interface_name);
2137   vat_json_object_add_uint (node, "mode", ntohl (mp->mode));
2138   vat_json_object_add_uint (node, "load_balance", ntohl (mp->lb));
2139   vat_json_object_add_uint (node, "active_members",
2140                             ntohl (mp->active_members));
2141   vat_json_object_add_uint (node, "members", ntohl (mp->members));
2142 }
2143
2144 static int
2145 api_sw_bond_interface_dump (vat_main_t * vam)
2146 {
2147   unformat_input_t *i = vam->input;
2148   vl_api_sw_bond_interface_dump_t *mp;
2149   vl_api_control_ping_t *mp_ping;
2150   int ret;
2151   u32 sw_if_index = ~0;
2152
2153   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2154     {
2155       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2156         ;
2157       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2158         ;
2159       else
2160         break;
2161     }
2162
2163   print (vam->ofp,
2164          "\n%-16s %-12s %-12s %-13s %-14s %-14s",
2165          "interface name", "sw_if_index", "mode", "load balance",
2166          "active members", "members");
2167
2168   /* Get list of bond interfaces */
2169   M (SW_BOND_INTERFACE_DUMP, mp);
2170   mp->sw_if_index = ntohl (sw_if_index);
2171   S (mp);
2172
2173   /* Use a control ping for synchronization */
2174   MPING (CONTROL_PING, mp_ping);
2175   S (mp_ping);
2176
2177   W (ret);
2178   return ret;
2179 }
2180
2181 static void vl_api_sw_member_interface_details_t_handler
2182   (vl_api_sw_member_interface_details_t * mp)
2183 {
2184   vat_main_t *vam = &vat_main;
2185
2186   print (vam->ofp,
2187          "%-25s %-12d %-7d %-12d %-10d %-10d", mp->interface_name,
2188          ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout,
2189          ntohl (mp->weight), mp->is_local_numa);
2190 }
2191
2192 static void vl_api_sw_member_interface_details_t_handler_json
2193   (vl_api_sw_member_interface_details_t * mp)
2194 {
2195   vat_main_t *vam = &vat_main;
2196   vat_json_node_t *node = NULL;
2197
2198   if (VAT_JSON_ARRAY != vam->json_tree.type)
2199     {
2200       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2201       vat_json_init_array (&vam->json_tree);
2202     }
2203   node = vat_json_array_add (&vam->json_tree);
2204
2205   vat_json_init_object (node);
2206   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2207   vat_json_object_add_string_copy (node, "interface_name",
2208                                    mp->interface_name);
2209   vat_json_object_add_uint (node, "passive", mp->is_passive);
2210   vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
2211   vat_json_object_add_uint (node, "weight", ntohl (mp->weight));
2212   vat_json_object_add_uint (node, "is_local_numa", mp->is_local_numa);
2213 }
2214
2215 static int
2216 api_sw_member_interface_dump (vat_main_t * vam)
2217 {
2218   unformat_input_t *i = vam->input;
2219   vl_api_sw_member_interface_dump_t *mp;
2220   vl_api_control_ping_t *mp_ping;
2221   u32 sw_if_index = ~0;
2222   u8 sw_if_index_set = 0;
2223   int ret;
2224
2225   /* Parse args required to build the message */
2226   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2227     {
2228       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2229         sw_if_index_set = 1;
2230       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2231         sw_if_index_set = 1;
2232       else
2233         break;
2234     }
2235
2236   if (sw_if_index_set == 0)
2237     {
2238       errmsg ("missing vpp interface name. ");
2239       return -99;
2240     }
2241
2242   print (vam->ofp,
2243          "\n%-25s %-12s %-7s %-12s %-10s %-10s",
2244          "member interface name", "sw_if_index", "passive", "long_timeout",
2245          "weight", "local numa");
2246
2247   /* Get list of bond interfaces */
2248   M (SW_MEMBER_INTERFACE_DUMP, mp);
2249   mp->sw_if_index = ntohl (sw_if_index);
2250   S (mp);
2251
2252   /* Use a control ping for synchronization */
2253   MPING (CONTROL_PING, mp_ping);
2254   S (mp_ping);
2255
2256   W (ret);
2257   return ret;
2258 }
2259
2260 static void vl_api_mpls_tunnel_add_del_reply_t_handler
2261   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2262 {
2263   vat_main_t *vam = &vat_main;
2264   i32 retval = ntohl (mp->retval);
2265   if (vam->async_mode)
2266     {
2267       vam->async_errors += (retval < 0);
2268     }
2269   else
2270     {
2271       vam->retval = retval;
2272       vam->sw_if_index = ntohl (mp->sw_if_index);
2273       vam->result_ready = 1;
2274     }
2275   vam->regenerate_interface_table = 1;
2276 }
2277
2278 static void vl_api_mpls_tunnel_add_del_reply_t_handler_json
2279   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2280 {
2281   vat_main_t *vam = &vat_main;
2282   vat_json_node_t node;
2283
2284   vat_json_init_object (&node);
2285   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2286   vat_json_object_add_uint (&node, "tunnel_sw_if_index",
2287                             ntohl (mp->sw_if_index));
2288
2289   vat_json_print (vam->ofp, &node);
2290   vat_json_free (&node);
2291
2292   vam->retval = ntohl (mp->retval);
2293   vam->result_ready = 1;
2294 }
2295
2296 static void vl_api_vxlan_add_del_tunnel_reply_t_handler
2297   (vl_api_vxlan_add_del_tunnel_reply_t * mp)
2298 {
2299   vat_main_t *vam = &vat_main;
2300   i32 retval = ntohl (mp->retval);
2301   if (vam->async_mode)
2302     {
2303       vam->async_errors += (retval < 0);
2304     }
2305   else
2306     {
2307       vam->retval = retval;
2308       vam->sw_if_index = ntohl (mp->sw_if_index);
2309       vam->result_ready = 1;
2310     }
2311   vam->regenerate_interface_table = 1;
2312 }
2313
2314 static void vl_api_vxlan_add_del_tunnel_reply_t_handler_json
2315   (vl_api_vxlan_add_del_tunnel_reply_t * mp)
2316 {
2317   vat_main_t *vam = &vat_main;
2318   vat_json_node_t node;
2319
2320   vat_json_init_object (&node);
2321   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2322   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2323
2324   vat_json_print (vam->ofp, &node);
2325   vat_json_free (&node);
2326
2327   vam->retval = ntohl (mp->retval);
2328   vam->result_ready = 1;
2329 }
2330
2331 static void vl_api_vxlan_offload_rx_reply_t_handler
2332   (vl_api_vxlan_offload_rx_reply_t * mp)
2333 {
2334   vat_main_t *vam = &vat_main;
2335   i32 retval = ntohl (mp->retval);
2336   if (vam->async_mode)
2337     {
2338       vam->async_errors += (retval < 0);
2339     }
2340   else
2341     {
2342       vam->retval = retval;
2343       vam->result_ready = 1;
2344     }
2345 }
2346
2347 static void vl_api_vxlan_offload_rx_reply_t_handler_json
2348   (vl_api_vxlan_offload_rx_reply_t * mp)
2349 {
2350   vat_main_t *vam = &vat_main;
2351   vat_json_node_t node;
2352
2353   vat_json_init_object (&node);
2354   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2355
2356   vat_json_print (vam->ofp, &node);
2357   vat_json_free (&node);
2358
2359   vam->retval = ntohl (mp->retval);
2360   vam->result_ready = 1;
2361 }
2362
2363 static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler
2364   (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp)
2365 {
2366   vat_main_t *vam = &vat_main;
2367   i32 retval = ntohl (mp->retval);
2368   if (vam->async_mode)
2369     {
2370       vam->async_errors += (retval < 0);
2371     }
2372   else
2373     {
2374       vam->retval = retval;
2375       vam->sw_if_index = ntohl (mp->sw_if_index);
2376       vam->result_ready = 1;
2377     }
2378   vam->regenerate_interface_table = 1;
2379 }
2380
2381 static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler_json
2382   (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp)
2383 {
2384   vat_main_t *vam = &vat_main;
2385   vat_json_node_t node;
2386
2387   vat_json_init_object (&node);
2388   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2389   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2390
2391   vat_json_print (vam->ofp, &node);
2392   vat_json_free (&node);
2393
2394   vam->retval = ntohl (mp->retval);
2395   vam->result_ready = 1;
2396 }
2397
2398 static void vl_api_create_vhost_user_if_reply_t_handler
2399   (vl_api_create_vhost_user_if_reply_t * mp)
2400 {
2401   vat_main_t *vam = &vat_main;
2402   i32 retval = ntohl (mp->retval);
2403   if (vam->async_mode)
2404     {
2405       vam->async_errors += (retval < 0);
2406     }
2407   else
2408     {
2409       vam->retval = retval;
2410       vam->sw_if_index = ntohl (mp->sw_if_index);
2411       vam->result_ready = 1;
2412     }
2413   vam->regenerate_interface_table = 1;
2414 }
2415
2416 static void vl_api_create_vhost_user_if_reply_t_handler_json
2417   (vl_api_create_vhost_user_if_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_v2_reply_t_handler
2434   (vl_api_create_vhost_user_if_v2_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_v2_reply_t_handler_json
2452   (vl_api_create_vhost_user_if_v2_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)                                                               \
2754   case IP_DSCP_##f:                                                           \
2755     return (format (s, "%s", #f));
2756       foreach_ip_dscp
2757 #undef _
2758     }
2759   s = format (s, "%s", t);
2760   return (format (s, "ILLEGAL"));
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 _(modify_vhost_user_if_v2_reply)                        \
3287 _(delete_vhost_user_if_reply)                           \
3288 _(want_l2_macs_events_reply)                            \
3289 _(input_acl_set_interface_reply)                        \
3290 _(ipsec_spd_add_del_reply)                              \
3291 _(ipsec_interface_add_del_spd_reply)                    \
3292 _(ipsec_spd_entry_add_del_reply)                        \
3293 _(ipsec_sad_entry_add_del_reply)                        \
3294 _(delete_loopback_reply)                                \
3295 _(bd_ip_mac_add_del_reply)                              \
3296 _(bd_ip_mac_flush_reply)                                \
3297 _(want_interface_events_reply)                          \
3298 _(cop_interface_enable_disable_reply)                   \
3299 _(cop_whitelist_enable_disable_reply)                   \
3300 _(sw_interface_clear_stats_reply)                       \
3301 _(ioam_enable_reply)                                    \
3302 _(ioam_disable_reply)                                   \
3303 _(af_packet_delete_reply)                               \
3304 _(policer_classify_set_interface_reply)                 \
3305 _(set_ipfix_exporter_reply)                             \
3306 _(set_ipfix_classify_stream_reply)                      \
3307 _(ipfix_classify_table_add_del_reply)                   \
3308 _(flow_classify_set_interface_reply)                    \
3309 _(sw_interface_span_enable_disable_reply)               \
3310 _(pg_capture_reply)                                     \
3311 _(pg_enable_disable_reply)                              \
3312 _(pg_interface_enable_disable_coalesce_reply)           \
3313 _(ip_source_and_port_range_check_add_del_reply)         \
3314 _(ip_source_and_port_range_check_interface_add_del_reply)\
3315 _(delete_subif_reply)                                   \
3316 _(l2_interface_pbb_tag_rewrite_reply)                   \
3317 _(set_punt_reply)                                       \
3318 _(feature_enable_disable_reply)                         \
3319 _(feature_gso_enable_disable_reply)                     \
3320 _(sw_interface_tag_add_del_reply)                       \
3321 _(sw_interface_add_del_mac_address_reply)               \
3322 _(hw_interface_set_mtu_reply)                           \
3323 _(p2p_ethernet_add_reply)                               \
3324 _(p2p_ethernet_del_reply)                               \
3325 _(tcp_configure_src_addresses_reply)                    \
3326 _(session_rule_add_del_reply)                           \
3327 _(ip_container_proxy_add_del_reply)                     \
3328 _(output_acl_set_interface_reply)                       \
3329 _(qos_record_enable_disable_reply)                      \
3330 _(flow_add_reply)
3331
3332 #define _(n)                                    \
3333     static void vl_api_##n##_t_handler          \
3334     (vl_api_##n##_t * mp)                       \
3335     {                                           \
3336         vat_main_t * vam = &vat_main;           \
3337         i32 retval = ntohl(mp->retval);         \
3338         if (vam->async_mode) {                  \
3339             vam->async_errors += (retval < 0);  \
3340         } else {                                \
3341             vam->retval = retval;               \
3342             vam->result_ready = 1;              \
3343         }                                       \
3344     }
3345 foreach_standard_reply_retval_handler;
3346 #undef _
3347
3348 #define _(n)                                    \
3349     static void vl_api_##n##_t_handler_json     \
3350     (vl_api_##n##_t * mp)                       \
3351     {                                           \
3352         vat_main_t * vam = &vat_main;           \
3353         vat_json_node_t node;                   \
3354         vat_json_init_object(&node);            \
3355         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
3356         vat_json_print(vam->ofp, &node);        \
3357         vam->retval = ntohl(mp->retval);        \
3358         vam->result_ready = 1;                  \
3359     }
3360 foreach_standard_reply_retval_handler;
3361 #undef _
3362
3363 /*
3364  * Table of message reply handlers, must include boilerplate handlers
3365  * we just generated
3366  */
3367
3368 #define foreach_vpe_api_reply_msg                                       \
3369 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
3370 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
3371 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
3372 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
3373 _(CONTROL_PING_REPLY, control_ping_reply)                               \
3374 _(CLI_REPLY, cli_reply)                                                 \
3375 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
3376 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
3377   sw_interface_add_del_address_reply)                                   \
3378 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
3379 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
3380 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
3381 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
3382 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
3383 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
3384 _(SW_INTERFACE_SET_VXLAN_BYPASS_REPLY, sw_interface_set_vxlan_bypass_reply) \
3385 _(SW_INTERFACE_SET_VXLAN_GPE_BYPASS_REPLY, sw_interface_set_vxlan_gpe_bypass_reply) \
3386 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
3387   sw_interface_set_l2_xconnect_reply)                                   \
3388 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
3389   sw_interface_set_l2_bridge_reply)                                     \
3390 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
3391 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
3392 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
3393 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
3394 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
3395 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
3396 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
3397 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
3398 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
3399 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
3400 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
3401 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
3402 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
3403 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
3404 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
3405 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
3406 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
3407 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
3408 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
3409 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
3410 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
3411 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
3412 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
3413 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
3414 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
3415 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
3416 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
3417 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
3418 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
3419 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
3420 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
3421 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
3422 _(BIER_ROUTE_ADD_DEL_REPLY, bier_route_add_del_reply)                   \
3423 _(BIER_TABLE_ADD_DEL_REPLY, bier_table_add_del_reply)                   \
3424 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
3425 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
3426   sw_interface_set_unnumbered_reply)                                    \
3427 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
3428 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
3429 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
3430 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
3431   sw_interface_ip6_enable_disable_reply)                                \
3432 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
3433 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
3434 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
3435 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
3436 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
3437 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
3438 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
3439 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
3440 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
3441 _(CLASSIFY_ADD_DEL_TABLE_REPLY, classify_add_del_table_reply)           \
3442 _(CLASSIFY_ADD_DEL_SESSION_REPLY, classify_add_del_session_reply)       \
3443 _(CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY,                                \
3444 classify_set_interface_ip_table_reply)                                  \
3445 _(CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY,                               \
3446   classify_set_interface_l2_tables_reply)                               \
3447 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
3448 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
3449 _(VXLAN_ADD_DEL_TUNNEL_REPLY, vxlan_add_del_tunnel_reply)               \
3450 _(VXLAN_OFFLOAD_RX_REPLY, vxlan_offload_rx_reply)               \
3451 _(VXLAN_TUNNEL_DETAILS, vxlan_tunnel_details)                           \
3452 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
3453 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
3454 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
3455 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
3456 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
3457 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
3458 _(CREATE_VHOST_USER_IF_V2_REPLY, create_vhost_user_if_v2_reply)         \
3459 _(MODIFY_VHOST_USER_IF_V2_REPLY, modify_vhost_user_if_v2_reply)         \
3460 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
3461 _(SHOW_VERSION_REPLY, show_version_reply)                               \
3462 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
3463 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
3464 _(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply)       \
3465 _(VXLAN_GPE_TUNNEL_DETAILS, vxlan_gpe_tunnel_details)                   \
3466 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
3467 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
3468 _(L2_MACS_EVENT, l2_macs_event)                                         \
3469 _(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply)         \
3470 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
3471 _(IP_DETAILS, ip_details)                                               \
3472 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
3473 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
3474 _(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
3475 _(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
3476 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
3477 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
3478 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
3479 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
3480 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
3481 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
3482 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
3483 _(COP_INTERFACE_ENABLE_DISABLE_REPLY, cop_interface_enable_disable_reply) \
3484 _(COP_WHITELIST_ENABLE_DISABLE_REPLY, cop_whitelist_enable_disable_reply) \
3485 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
3486 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
3487 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
3488 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
3489 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
3490 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
3491 _(AF_PACKET_DETAILS, af_packet_details)                                 \
3492 _(POLICER_ADD_DEL_REPLY, policer_add_del_reply)                         \
3493 _(POLICER_DETAILS, policer_details)                                     \
3494 _(POLICER_CLASSIFY_SET_INTERFACE_REPLY, policer_classify_set_interface_reply) \
3495 _(POLICER_CLASSIFY_DETAILS, policer_classify_details)                   \
3496 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
3497 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
3498 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
3499 _(CLASSIFY_TABLE_IDS_REPLY, classify_table_ids_reply)                   \
3500 _(CLASSIFY_TABLE_BY_INTERFACE_REPLY, classify_table_by_interface_reply) \
3501 _(CLASSIFY_TABLE_INFO_REPLY, classify_table_info_reply)                 \
3502 _(CLASSIFY_SESSION_DETAILS, classify_session_details)                   \
3503 _(SET_IPFIX_EXPORTER_REPLY, set_ipfix_exporter_reply)                   \
3504 _(IPFIX_EXPORTER_DETAILS, ipfix_exporter_details)                       \
3505 _(SET_IPFIX_CLASSIFY_STREAM_REPLY, set_ipfix_classify_stream_reply)     \
3506 _(IPFIX_CLASSIFY_STREAM_DETAILS, ipfix_classify_stream_details)         \
3507 _(IPFIX_CLASSIFY_TABLE_ADD_DEL_REPLY, ipfix_classify_table_add_del_reply) \
3508 _(IPFIX_CLASSIFY_TABLE_DETAILS, ipfix_classify_table_details)           \
3509 _(FLOW_CLASSIFY_SET_INTERFACE_REPLY, flow_classify_set_interface_reply) \
3510 _(FLOW_CLASSIFY_DETAILS, flow_classify_details)                         \
3511 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
3512 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
3513 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
3514 _(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply)                 \
3515 _(PG_CAPTURE_REPLY, pg_capture_reply)                                   \
3516 _(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply)                     \
3517 _(PG_INTERFACE_ENABLE_DISABLE_COALESCE_REPLY, pg_interface_enable_disable_coalesce_reply) \
3518 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
3519  ip_source_and_port_range_check_add_del_reply)                          \
3520 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
3521  ip_source_and_port_range_check_interface_add_del_reply)                \
3522 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
3523 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
3524 _(SET_PUNT_REPLY, set_punt_reply)                                       \
3525 _(IP_TABLE_DETAILS, ip_table_details)                                   \
3526 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
3527 _(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply)           \
3528 _(FEATURE_GSO_ENABLE_DISABLE_REPLY, feature_gso_enable_disable_reply)   \
3529 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
3530 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
3531 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
3532 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
3533 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
3534 _(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply)                       \
3535 _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply)                       \
3536 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
3537 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
3538 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
3539 _(SESSION_RULES_DETAILS, session_rules_details)                         \
3540 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
3541 _(OUTPUT_ACL_SET_INTERFACE_REPLY, output_acl_set_interface_reply)       \
3542 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
3543 _(FLOW_ADD_REPLY, flow_add_reply)   \
3544
3545 #define foreach_standalone_reply_msg                                    \
3546 _(SW_INTERFACE_EVENT, sw_interface_event)
3547
3548 typedef struct
3549 {
3550   u8 *name;
3551   u32 value;
3552 } name_sort_t;
3553
3554 #define STR_VTR_OP_CASE(op)     \
3555     case L2_VTR_ ## op:         \
3556         return "" # op;
3557
3558 static const char *
3559 str_vtr_op (u32 vtr_op)
3560 {
3561   switch (vtr_op)
3562     {
3563       STR_VTR_OP_CASE (DISABLED);
3564       STR_VTR_OP_CASE (PUSH_1);
3565       STR_VTR_OP_CASE (PUSH_2);
3566       STR_VTR_OP_CASE (POP_1);
3567       STR_VTR_OP_CASE (POP_2);
3568       STR_VTR_OP_CASE (TRANSLATE_1_1);
3569       STR_VTR_OP_CASE (TRANSLATE_1_2);
3570       STR_VTR_OP_CASE (TRANSLATE_2_1);
3571       STR_VTR_OP_CASE (TRANSLATE_2_2);
3572     }
3573
3574   return "UNKNOWN";
3575 }
3576
3577 static int
3578 dump_sub_interface_table (vat_main_t * vam)
3579 {
3580   const sw_interface_subif_t *sub = NULL;
3581
3582   if (vam->json_output)
3583     {
3584       clib_warning
3585         ("JSON output supported only for VPE API calls and dump_stats_table");
3586       return -99;
3587     }
3588
3589   print (vam->ofp,
3590          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
3591          "Interface", "sw_if_index",
3592          "sub id", "dot1ad", "tags", "outer id",
3593          "inner id", "exact", "default", "outer any", "inner any");
3594
3595   vec_foreach (sub, vam->sw_if_subif_table)
3596   {
3597     print (vam->ofp,
3598            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
3599            sub->interface_name,
3600            sub->sw_if_index,
3601            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
3602            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
3603            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
3604            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
3605     if (sub->vtr_op != L2_VTR_DISABLED)
3606       {
3607         print (vam->ofp,
3608                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
3609                "tag1: %d tag2: %d ]",
3610                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
3611                sub->vtr_tag1, sub->vtr_tag2);
3612       }
3613   }
3614
3615   return 0;
3616 }
3617
3618 static int
3619 name_sort_cmp (void *a1, void *a2)
3620 {
3621   name_sort_t *n1 = a1;
3622   name_sort_t *n2 = a2;
3623
3624   return strcmp ((char *) n1->name, (char *) n2->name);
3625 }
3626
3627 static int
3628 dump_interface_table (vat_main_t * vam)
3629 {
3630   hash_pair_t *p;
3631   name_sort_t *nses = 0, *ns;
3632
3633   if (vam->json_output)
3634     {
3635       clib_warning
3636         ("JSON output supported only for VPE API calls and dump_stats_table");
3637       return -99;
3638     }
3639
3640   /* *INDENT-OFF* */
3641   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3642   ({
3643     vec_add2 (nses, ns, 1);
3644     ns->name = (u8 *)(p->key);
3645     ns->value = (u32) p->value[0];
3646   }));
3647   /* *INDENT-ON* */
3648
3649   vec_sort_with_function (nses, name_sort_cmp);
3650
3651   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
3652   vec_foreach (ns, nses)
3653   {
3654     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
3655   }
3656   vec_free (nses);
3657   return 0;
3658 }
3659
3660 static int
3661 dump_ip_table (vat_main_t * vam, int is_ipv6)
3662 {
3663   const ip_details_t *det = NULL;
3664   const ip_address_details_t *address = NULL;
3665   u32 i = ~0;
3666
3667   print (vam->ofp, "%-12s", "sw_if_index");
3668
3669   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
3670   {
3671     i++;
3672     if (!det->present)
3673       {
3674         continue;
3675       }
3676     print (vam->ofp, "%-12d", i);
3677     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
3678     if (!det->addr)
3679       {
3680         continue;
3681       }
3682     vec_foreach (address, det->addr)
3683     {
3684       print (vam->ofp,
3685              "            %-30U%-13d",
3686              is_ipv6 ? format_ip6_address : format_ip4_address,
3687              address->ip, address->prefix_length);
3688     }
3689   }
3690
3691   return 0;
3692 }
3693
3694 static int
3695 dump_ipv4_table (vat_main_t * vam)
3696 {
3697   if (vam->json_output)
3698     {
3699       clib_warning
3700         ("JSON output supported only for VPE API calls and dump_stats_table");
3701       return -99;
3702     }
3703
3704   return dump_ip_table (vam, 0);
3705 }
3706
3707 static int
3708 dump_ipv6_table (vat_main_t * vam)
3709 {
3710   if (vam->json_output)
3711     {
3712       clib_warning
3713         ("JSON output supported only for VPE API calls and dump_stats_table");
3714       return -99;
3715     }
3716
3717   return dump_ip_table (vam, 1);
3718 }
3719
3720 /*
3721  * Pass CLI buffers directly in the CLI_INBAND API message,
3722  * instead of an additional shared memory area.
3723  */
3724 static int
3725 exec_inband (vat_main_t * vam)
3726 {
3727   vl_api_cli_inband_t *mp;
3728   unformat_input_t *i = vam->input;
3729   int ret;
3730
3731   if (vec_len (i->buffer) == 0)
3732     return -1;
3733
3734   if (vam->exec_mode == 0 && unformat (i, "mode"))
3735     {
3736       vam->exec_mode = 1;
3737       return 0;
3738     }
3739   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
3740     {
3741       vam->exec_mode = 0;
3742       return 0;
3743     }
3744
3745   /*
3746    * In order for the CLI command to work, it
3747    * must be a vector ending in \n, not a C-string ending
3748    * in \n\0.
3749    */
3750   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
3751   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
3752
3753   S (mp);
3754   W (ret);
3755   /* json responses may or may not include a useful reply... */
3756   if (vec_len (vam->cmd_reply))
3757     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
3758   return ret;
3759 }
3760
3761 int
3762 exec (vat_main_t * vam)
3763 {
3764   return exec_inband (vam);
3765 }
3766
3767 static int
3768 api_create_loopback (vat_main_t * vam)
3769 {
3770   unformat_input_t *i = vam->input;
3771   vl_api_create_loopback_t *mp;
3772   vl_api_create_loopback_instance_t *mp_lbi;
3773   u8 mac_address[6];
3774   u8 mac_set = 0;
3775   u8 is_specified = 0;
3776   u32 user_instance = 0;
3777   int ret;
3778
3779   clib_memset (mac_address, 0, sizeof (mac_address));
3780
3781   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3782     {
3783       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
3784         mac_set = 1;
3785       if (unformat (i, "instance %d", &user_instance))
3786         is_specified = 1;
3787       else
3788         break;
3789     }
3790
3791   if (is_specified)
3792     {
3793       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
3794       mp_lbi->is_specified = is_specified;
3795       if (is_specified)
3796         mp_lbi->user_instance = htonl (user_instance);
3797       if (mac_set)
3798         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
3799       S (mp_lbi);
3800     }
3801   else
3802     {
3803       /* Construct the API message */
3804       M (CREATE_LOOPBACK, mp);
3805       if (mac_set)
3806         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
3807       S (mp);
3808     }
3809
3810   W (ret);
3811   return ret;
3812 }
3813
3814 static int
3815 api_delete_loopback (vat_main_t * vam)
3816 {
3817   unformat_input_t *i = vam->input;
3818   vl_api_delete_loopback_t *mp;
3819   u32 sw_if_index = ~0;
3820   int ret;
3821
3822   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3823     {
3824       if (unformat (i, "sw_if_index %d", &sw_if_index))
3825         ;
3826       else
3827         break;
3828     }
3829
3830   if (sw_if_index == ~0)
3831     {
3832       errmsg ("missing sw_if_index");
3833       return -99;
3834     }
3835
3836   /* Construct the API message */
3837   M (DELETE_LOOPBACK, mp);
3838   mp->sw_if_index = ntohl (sw_if_index);
3839
3840   S (mp);
3841   W (ret);
3842   return ret;
3843 }
3844
3845 static int
3846 api_want_interface_events (vat_main_t * vam)
3847 {
3848   unformat_input_t *i = vam->input;
3849   vl_api_want_interface_events_t *mp;
3850   int enable = -1;
3851   int ret;
3852
3853   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3854     {
3855       if (unformat (i, "enable"))
3856         enable = 1;
3857       else if (unformat (i, "disable"))
3858         enable = 0;
3859       else
3860         break;
3861     }
3862
3863   if (enable == -1)
3864     {
3865       errmsg ("missing enable|disable");
3866       return -99;
3867     }
3868
3869   M (WANT_INTERFACE_EVENTS, mp);
3870   mp->enable_disable = enable;
3871
3872   vam->interface_event_display = enable;
3873
3874   S (mp);
3875   W (ret);
3876   return ret;
3877 }
3878
3879
3880 /* Note: non-static, called once to set up the initial intfc table */
3881 int
3882 api_sw_interface_dump (vat_main_t * vam)
3883 {
3884   vl_api_sw_interface_dump_t *mp;
3885   vl_api_control_ping_t *mp_ping;
3886   hash_pair_t *p;
3887   name_sort_t *nses = 0, *ns;
3888   sw_interface_subif_t *sub = NULL;
3889   int ret;
3890
3891   /* Toss the old name table */
3892   /* *INDENT-OFF* */
3893   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3894   ({
3895     vec_add2 (nses, ns, 1);
3896     ns->name = (u8 *)(p->key);
3897     ns->value = (u32) p->value[0];
3898   }));
3899   /* *INDENT-ON* */
3900
3901   hash_free (vam->sw_if_index_by_interface_name);
3902
3903   vec_foreach (ns, nses) vec_free (ns->name);
3904
3905   vec_free (nses);
3906
3907   vec_foreach (sub, vam->sw_if_subif_table)
3908   {
3909     vec_free (sub->interface_name);
3910   }
3911   vec_free (vam->sw_if_subif_table);
3912
3913   /* recreate the interface name hash table */
3914   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3915
3916   /*
3917    * Ask for all interface names. Otherwise, the epic catalog of
3918    * name filters becomes ridiculously long, and vat ends up needing
3919    * to be taught about new interface types.
3920    */
3921   M (SW_INTERFACE_DUMP, mp);
3922   S (mp);
3923
3924   /* Use a control ping for synchronization */
3925   MPING (CONTROL_PING, mp_ping);
3926   S (mp_ping);
3927
3928   W (ret);
3929   return ret;
3930 }
3931
3932 static int
3933 api_sw_interface_set_flags (vat_main_t * vam)
3934 {
3935   unformat_input_t *i = vam->input;
3936   vl_api_sw_interface_set_flags_t *mp;
3937   u32 sw_if_index;
3938   u8 sw_if_index_set = 0;
3939   u8 admin_up = 0;
3940   int ret;
3941
3942   /* Parse args required to build the message */
3943   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3944     {
3945       if (unformat (i, "admin-up"))
3946         admin_up = 1;
3947       else if (unformat (i, "admin-down"))
3948         admin_up = 0;
3949       else
3950         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3951         sw_if_index_set = 1;
3952       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3953         sw_if_index_set = 1;
3954       else
3955         break;
3956     }
3957
3958   if (sw_if_index_set == 0)
3959     {
3960       errmsg ("missing interface name or sw_if_index");
3961       return -99;
3962     }
3963
3964   /* Construct the API message */
3965   M (SW_INTERFACE_SET_FLAGS, mp);
3966   mp->sw_if_index = ntohl (sw_if_index);
3967   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3968
3969   /* send it... */
3970   S (mp);
3971
3972   /* Wait for a reply, return the good/bad news... */
3973   W (ret);
3974   return ret;
3975 }
3976
3977 static int
3978 api_sw_interface_set_rx_mode (vat_main_t * vam)
3979 {
3980   unformat_input_t *i = vam->input;
3981   vl_api_sw_interface_set_rx_mode_t *mp;
3982   u32 sw_if_index;
3983   u8 sw_if_index_set = 0;
3984   int ret;
3985   u8 queue_id_valid = 0;
3986   u32 queue_id;
3987   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
3988
3989   /* Parse args required to build the message */
3990   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3991     {
3992       if (unformat (i, "queue %d", &queue_id))
3993         queue_id_valid = 1;
3994       else if (unformat (i, "polling"))
3995         mode = VNET_HW_IF_RX_MODE_POLLING;
3996       else if (unformat (i, "interrupt"))
3997         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
3998       else if (unformat (i, "adaptive"))
3999         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
4000       else
4001         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4002         sw_if_index_set = 1;
4003       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4004         sw_if_index_set = 1;
4005       else
4006         break;
4007     }
4008
4009   if (sw_if_index_set == 0)
4010     {
4011       errmsg ("missing interface name or sw_if_index");
4012       return -99;
4013     }
4014   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
4015     {
4016       errmsg ("missing rx-mode");
4017       return -99;
4018     }
4019
4020   /* Construct the API message */
4021   M (SW_INTERFACE_SET_RX_MODE, mp);
4022   mp->sw_if_index = ntohl (sw_if_index);
4023   mp->mode = (vl_api_rx_mode_t) mode;
4024   mp->queue_id_valid = queue_id_valid;
4025   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
4026
4027   /* send it... */
4028   S (mp);
4029
4030   /* Wait for a reply, return the good/bad news... */
4031   W (ret);
4032   return ret;
4033 }
4034
4035 static int
4036 api_sw_interface_set_rx_placement (vat_main_t * vam)
4037 {
4038   unformat_input_t *i = vam->input;
4039   vl_api_sw_interface_set_rx_placement_t *mp;
4040   u32 sw_if_index;
4041   u8 sw_if_index_set = 0;
4042   int ret;
4043   u8 is_main = 0;
4044   u32 queue_id, thread_index;
4045
4046   /* Parse args required to build the message */
4047   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4048     {
4049       if (unformat (i, "queue %d", &queue_id))
4050         ;
4051       else if (unformat (i, "main"))
4052         is_main = 1;
4053       else if (unformat (i, "worker %d", &thread_index))
4054         ;
4055       else
4056         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4057         sw_if_index_set = 1;
4058       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4059         sw_if_index_set = 1;
4060       else
4061         break;
4062     }
4063
4064   if (sw_if_index_set == 0)
4065     {
4066       errmsg ("missing interface name or sw_if_index");
4067       return -99;
4068     }
4069
4070   if (is_main)
4071     thread_index = 0;
4072   /* Construct the API message */
4073   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
4074   mp->sw_if_index = ntohl (sw_if_index);
4075   mp->worker_id = ntohl (thread_index);
4076   mp->queue_id = ntohl (queue_id);
4077   mp->is_main = is_main;
4078
4079   /* send it... */
4080   S (mp);
4081   /* Wait for a reply, return the good/bad news... */
4082   W (ret);
4083   return ret;
4084 }
4085
4086 static void vl_api_sw_interface_rx_placement_details_t_handler
4087   (vl_api_sw_interface_rx_placement_details_t * mp)
4088 {
4089   vat_main_t *vam = &vat_main;
4090   u32 worker_id = ntohl (mp->worker_id);
4091
4092   print (vam->ofp,
4093          "\n%-11d %-11s %-6d %-5d %-9s",
4094          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
4095          worker_id, ntohl (mp->queue_id),
4096          (mp->mode ==
4097           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
4098 }
4099
4100 static void vl_api_sw_interface_rx_placement_details_t_handler_json
4101   (vl_api_sw_interface_rx_placement_details_t * mp)
4102 {
4103   vat_main_t *vam = &vat_main;
4104   vat_json_node_t *node = NULL;
4105
4106   if (VAT_JSON_ARRAY != vam->json_tree.type)
4107     {
4108       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4109       vat_json_init_array (&vam->json_tree);
4110     }
4111   node = vat_json_array_add (&vam->json_tree);
4112
4113   vat_json_init_object (node);
4114   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
4115   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
4116   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
4117   vat_json_object_add_uint (node, "mode", mp->mode);
4118 }
4119
4120 static int
4121 api_sw_interface_rx_placement_dump (vat_main_t * vam)
4122 {
4123   unformat_input_t *i = vam->input;
4124   vl_api_sw_interface_rx_placement_dump_t *mp;
4125   vl_api_control_ping_t *mp_ping;
4126   int ret;
4127   u32 sw_if_index;
4128   u8 sw_if_index_set = 0;
4129
4130   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4131     {
4132       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4133         sw_if_index_set++;
4134       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4135         sw_if_index_set++;
4136       else
4137         break;
4138     }
4139
4140   print (vam->ofp,
4141          "\n%-11s %-11s %-6s %-5s %-4s",
4142          "sw_if_index", "main/worker", "thread", "queue", "mode");
4143
4144   /* Dump Interface rx placement */
4145   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
4146
4147   if (sw_if_index_set)
4148     mp->sw_if_index = htonl (sw_if_index);
4149   else
4150     mp->sw_if_index = ~0;
4151
4152   S (mp);
4153
4154   /* Use a control ping for synchronization */
4155   MPING (CONTROL_PING, mp_ping);
4156   S (mp_ping);
4157
4158   W (ret);
4159   return ret;
4160 }
4161
4162 static int
4163 api_sw_interface_clear_stats (vat_main_t * vam)
4164 {
4165   unformat_input_t *i = vam->input;
4166   vl_api_sw_interface_clear_stats_t *mp;
4167   u32 sw_if_index;
4168   u8 sw_if_index_set = 0;
4169   int ret;
4170
4171   /* Parse args required to build the message */
4172   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4173     {
4174       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4175         sw_if_index_set = 1;
4176       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4177         sw_if_index_set = 1;
4178       else
4179         break;
4180     }
4181
4182   /* Construct the API message */
4183   M (SW_INTERFACE_CLEAR_STATS, mp);
4184
4185   if (sw_if_index_set == 1)
4186     mp->sw_if_index = ntohl (sw_if_index);
4187   else
4188     mp->sw_if_index = ~0;
4189
4190   /* send it... */
4191   S (mp);
4192
4193   /* Wait for a reply, return the good/bad news... */
4194   W (ret);
4195   return ret;
4196 }
4197
4198 static int
4199 api_sw_interface_add_del_address (vat_main_t * vam)
4200 {
4201   unformat_input_t *i = vam->input;
4202   vl_api_sw_interface_add_del_address_t *mp;
4203   u32 sw_if_index;
4204   u8 sw_if_index_set = 0;
4205   u8 is_add = 1, del_all = 0;
4206   u32 address_length = 0;
4207   u8 v4_address_set = 0;
4208   u8 v6_address_set = 0;
4209   ip4_address_t v4address;
4210   ip6_address_t v6address;
4211   int ret;
4212
4213   /* Parse args required to build the message */
4214   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4215     {
4216       if (unformat (i, "del-all"))
4217         del_all = 1;
4218       else if (unformat (i, "del"))
4219         is_add = 0;
4220       else
4221         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4222         sw_if_index_set = 1;
4223       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4224         sw_if_index_set = 1;
4225       else if (unformat (i, "%U/%d",
4226                          unformat_ip4_address, &v4address, &address_length))
4227         v4_address_set = 1;
4228       else if (unformat (i, "%U/%d",
4229                          unformat_ip6_address, &v6address, &address_length))
4230         v6_address_set = 1;
4231       else
4232         break;
4233     }
4234
4235   if (sw_if_index_set == 0)
4236     {
4237       errmsg ("missing interface name or sw_if_index");
4238       return -99;
4239     }
4240   if (v4_address_set && v6_address_set)
4241     {
4242       errmsg ("both v4 and v6 addresses set");
4243       return -99;
4244     }
4245   if (!v4_address_set && !v6_address_set && !del_all)
4246     {
4247       errmsg ("no addresses set");
4248       return -99;
4249     }
4250
4251   /* Construct the API message */
4252   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
4253
4254   mp->sw_if_index = ntohl (sw_if_index);
4255   mp->is_add = is_add;
4256   mp->del_all = del_all;
4257   if (v6_address_set)
4258     {
4259       mp->prefix.address.af = ADDRESS_IP6;
4260       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
4261     }
4262   else
4263     {
4264       mp->prefix.address.af = ADDRESS_IP4;
4265       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
4266     }
4267   mp->prefix.len = address_length;
4268
4269   /* send it... */
4270   S (mp);
4271
4272   /* Wait for a reply, return good/bad news  */
4273   W (ret);
4274   return ret;
4275 }
4276
4277 static int
4278 api_sw_interface_set_mpls_enable (vat_main_t * vam)
4279 {
4280   unformat_input_t *i = vam->input;
4281   vl_api_sw_interface_set_mpls_enable_t *mp;
4282   u32 sw_if_index;
4283   u8 sw_if_index_set = 0;
4284   u8 enable = 1;
4285   int ret;
4286
4287   /* Parse args required to build the message */
4288   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4289     {
4290       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4291         sw_if_index_set = 1;
4292       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4293         sw_if_index_set = 1;
4294       else if (unformat (i, "disable"))
4295         enable = 0;
4296       else if (unformat (i, "dis"))
4297         enable = 0;
4298       else
4299         break;
4300     }
4301
4302   if (sw_if_index_set == 0)
4303     {
4304       errmsg ("missing interface name or sw_if_index");
4305       return -99;
4306     }
4307
4308   /* Construct the API message */
4309   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
4310
4311   mp->sw_if_index = ntohl (sw_if_index);
4312   mp->enable = enable;
4313
4314   /* send it... */
4315   S (mp);
4316
4317   /* Wait for a reply... */
4318   W (ret);
4319   return ret;
4320 }
4321
4322 static int
4323 api_sw_interface_set_table (vat_main_t * vam)
4324 {
4325   unformat_input_t *i = vam->input;
4326   vl_api_sw_interface_set_table_t *mp;
4327   u32 sw_if_index, vrf_id = 0;
4328   u8 sw_if_index_set = 0;
4329   u8 is_ipv6 = 0;
4330   int ret;
4331
4332   /* Parse args required to build the message */
4333   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4334     {
4335       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4336         sw_if_index_set = 1;
4337       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4338         sw_if_index_set = 1;
4339       else if (unformat (i, "vrf %d", &vrf_id))
4340         ;
4341       else if (unformat (i, "ipv6"))
4342         is_ipv6 = 1;
4343       else
4344         break;
4345     }
4346
4347   if (sw_if_index_set == 0)
4348     {
4349       errmsg ("missing interface name or sw_if_index");
4350       return -99;
4351     }
4352
4353   /* Construct the API message */
4354   M (SW_INTERFACE_SET_TABLE, mp);
4355
4356   mp->sw_if_index = ntohl (sw_if_index);
4357   mp->is_ipv6 = is_ipv6;
4358   mp->vrf_id = ntohl (vrf_id);
4359
4360   /* send it... */
4361   S (mp);
4362
4363   /* Wait for a reply... */
4364   W (ret);
4365   return ret;
4366 }
4367
4368 static void vl_api_sw_interface_get_table_reply_t_handler
4369   (vl_api_sw_interface_get_table_reply_t * mp)
4370 {
4371   vat_main_t *vam = &vat_main;
4372
4373   print (vam->ofp, "%d", ntohl (mp->vrf_id));
4374
4375   vam->retval = ntohl (mp->retval);
4376   vam->result_ready = 1;
4377
4378 }
4379
4380 static void vl_api_sw_interface_get_table_reply_t_handler_json
4381   (vl_api_sw_interface_get_table_reply_t * mp)
4382 {
4383   vat_main_t *vam = &vat_main;
4384   vat_json_node_t node;
4385
4386   vat_json_init_object (&node);
4387   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
4388   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
4389
4390   vat_json_print (vam->ofp, &node);
4391   vat_json_free (&node);
4392
4393   vam->retval = ntohl (mp->retval);
4394   vam->result_ready = 1;
4395 }
4396
4397 static int
4398 api_sw_interface_get_table (vat_main_t * vam)
4399 {
4400   unformat_input_t *i = vam->input;
4401   vl_api_sw_interface_get_table_t *mp;
4402   u32 sw_if_index;
4403   u8 sw_if_index_set = 0;
4404   u8 is_ipv6 = 0;
4405   int ret;
4406
4407   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4408     {
4409       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4410         sw_if_index_set = 1;
4411       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4412         sw_if_index_set = 1;
4413       else if (unformat (i, "ipv6"))
4414         is_ipv6 = 1;
4415       else
4416         break;
4417     }
4418
4419   if (sw_if_index_set == 0)
4420     {
4421       errmsg ("missing interface name or sw_if_index");
4422       return -99;
4423     }
4424
4425   M (SW_INTERFACE_GET_TABLE, mp);
4426   mp->sw_if_index = htonl (sw_if_index);
4427   mp->is_ipv6 = is_ipv6;
4428
4429   S (mp);
4430   W (ret);
4431   return ret;
4432 }
4433
4434 static int
4435 api_sw_interface_set_vpath (vat_main_t * vam)
4436 {
4437   unformat_input_t *i = vam->input;
4438   vl_api_sw_interface_set_vpath_t *mp;
4439   u32 sw_if_index = 0;
4440   u8 sw_if_index_set = 0;
4441   u8 is_enable = 0;
4442   int ret;
4443
4444   /* Parse args required to build the message */
4445   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4446     {
4447       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4448         sw_if_index_set = 1;
4449       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4450         sw_if_index_set = 1;
4451       else if (unformat (i, "enable"))
4452         is_enable = 1;
4453       else if (unformat (i, "disable"))
4454         is_enable = 0;
4455       else
4456         break;
4457     }
4458
4459   if (sw_if_index_set == 0)
4460     {
4461       errmsg ("missing interface name or sw_if_index");
4462       return -99;
4463     }
4464
4465   /* Construct the API message */
4466   M (SW_INTERFACE_SET_VPATH, mp);
4467
4468   mp->sw_if_index = ntohl (sw_if_index);
4469   mp->enable = is_enable;
4470
4471   /* send it... */
4472   S (mp);
4473
4474   /* Wait for a reply... */
4475   W (ret);
4476   return ret;
4477 }
4478
4479 static int
4480 api_sw_interface_set_vxlan_bypass (vat_main_t * vam)
4481 {
4482   unformat_input_t *i = vam->input;
4483   vl_api_sw_interface_set_vxlan_bypass_t *mp;
4484   u32 sw_if_index = 0;
4485   u8 sw_if_index_set = 0;
4486   u8 is_enable = 1;
4487   u8 is_ipv6 = 0;
4488   int ret;
4489
4490   /* Parse args required to build the message */
4491   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4492     {
4493       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4494         sw_if_index_set = 1;
4495       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4496         sw_if_index_set = 1;
4497       else if (unformat (i, "enable"))
4498         is_enable = 1;
4499       else if (unformat (i, "disable"))
4500         is_enable = 0;
4501       else if (unformat (i, "ip4"))
4502         is_ipv6 = 0;
4503       else if (unformat (i, "ip6"))
4504         is_ipv6 = 1;
4505       else
4506         break;
4507     }
4508
4509   if (sw_if_index_set == 0)
4510     {
4511       errmsg ("missing interface name or sw_if_index");
4512       return -99;
4513     }
4514
4515   /* Construct the API message */
4516   M (SW_INTERFACE_SET_VXLAN_BYPASS, mp);
4517
4518   mp->sw_if_index = ntohl (sw_if_index);
4519   mp->enable = is_enable;
4520   mp->is_ipv6 = is_ipv6;
4521
4522   /* send it... */
4523   S (mp);
4524
4525   /* Wait for a reply... */
4526   W (ret);
4527   return ret;
4528 }
4529
4530 static int
4531 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
4532 {
4533   unformat_input_t *i = vam->input;
4534   vl_api_sw_interface_set_l2_xconnect_t *mp;
4535   u32 rx_sw_if_index;
4536   u8 rx_sw_if_index_set = 0;
4537   u32 tx_sw_if_index;
4538   u8 tx_sw_if_index_set = 0;
4539   u8 enable = 1;
4540   int ret;
4541
4542   /* Parse args required to build the message */
4543   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4544     {
4545       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4546         rx_sw_if_index_set = 1;
4547       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4548         tx_sw_if_index_set = 1;
4549       else if (unformat (i, "rx"))
4550         {
4551           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4552             {
4553               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4554                             &rx_sw_if_index))
4555                 rx_sw_if_index_set = 1;
4556             }
4557           else
4558             break;
4559         }
4560       else if (unformat (i, "tx"))
4561         {
4562           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4563             {
4564               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4565                             &tx_sw_if_index))
4566                 tx_sw_if_index_set = 1;
4567             }
4568           else
4569             break;
4570         }
4571       else if (unformat (i, "enable"))
4572         enable = 1;
4573       else if (unformat (i, "disable"))
4574         enable = 0;
4575       else
4576         break;
4577     }
4578
4579   if (rx_sw_if_index_set == 0)
4580     {
4581       errmsg ("missing rx interface name or rx_sw_if_index");
4582       return -99;
4583     }
4584
4585   if (enable && (tx_sw_if_index_set == 0))
4586     {
4587       errmsg ("missing tx interface name or tx_sw_if_index");
4588       return -99;
4589     }
4590
4591   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
4592
4593   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4594   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4595   mp->enable = enable;
4596
4597   S (mp);
4598   W (ret);
4599   return ret;
4600 }
4601
4602 static int
4603 api_sw_interface_set_l2_bridge (vat_main_t * vam)
4604 {
4605   unformat_input_t *i = vam->input;
4606   vl_api_sw_interface_set_l2_bridge_t *mp;
4607   vl_api_l2_port_type_t port_type;
4608   u32 rx_sw_if_index;
4609   u8 rx_sw_if_index_set = 0;
4610   u32 bd_id;
4611   u8 bd_id_set = 0;
4612   u32 shg = 0;
4613   u8 enable = 1;
4614   int ret;
4615
4616   port_type = L2_API_PORT_TYPE_NORMAL;
4617
4618   /* Parse args required to build the message */
4619   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4620     {
4621       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
4622         rx_sw_if_index_set = 1;
4623       else if (unformat (i, "bd_id %d", &bd_id))
4624         bd_id_set = 1;
4625       else
4626         if (unformat
4627             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
4628         rx_sw_if_index_set = 1;
4629       else if (unformat (i, "shg %d", &shg))
4630         ;
4631       else if (unformat (i, "bvi"))
4632         port_type = L2_API_PORT_TYPE_BVI;
4633       else if (unformat (i, "uu-fwd"))
4634         port_type = L2_API_PORT_TYPE_UU_FWD;
4635       else if (unformat (i, "enable"))
4636         enable = 1;
4637       else if (unformat (i, "disable"))
4638         enable = 0;
4639       else
4640         break;
4641     }
4642
4643   if (rx_sw_if_index_set == 0)
4644     {
4645       errmsg ("missing rx interface name or sw_if_index");
4646       return -99;
4647     }
4648
4649   if (enable && (bd_id_set == 0))
4650     {
4651       errmsg ("missing bridge domain");
4652       return -99;
4653     }
4654
4655   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
4656
4657   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4658   mp->bd_id = ntohl (bd_id);
4659   mp->shg = (u8) shg;
4660   mp->port_type = ntohl (port_type);
4661   mp->enable = enable;
4662
4663   S (mp);
4664   W (ret);
4665   return ret;
4666 }
4667
4668 static int
4669 api_bridge_domain_dump (vat_main_t * vam)
4670 {
4671   unformat_input_t *i = vam->input;
4672   vl_api_bridge_domain_dump_t *mp;
4673   vl_api_control_ping_t *mp_ping;
4674   u32 bd_id = ~0;
4675   int ret;
4676
4677   /* Parse args required to build the message */
4678   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4679     {
4680       if (unformat (i, "bd_id %d", &bd_id))
4681         ;
4682       else
4683         break;
4684     }
4685
4686   M (BRIDGE_DOMAIN_DUMP, mp);
4687   mp->bd_id = ntohl (bd_id);
4688   S (mp);
4689
4690   /* Use a control ping for synchronization */
4691   MPING (CONTROL_PING, mp_ping);
4692   S (mp_ping);
4693
4694   W (ret);
4695   return ret;
4696 }
4697
4698 static int
4699 api_bridge_domain_add_del (vat_main_t * vam)
4700 {
4701   unformat_input_t *i = vam->input;
4702   vl_api_bridge_domain_add_del_t *mp;
4703   u32 bd_id = ~0;
4704   u8 is_add = 1;
4705   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
4706   u8 *bd_tag = NULL;
4707   u32 mac_age = 0;
4708   int ret;
4709
4710   /* Parse args required to build the message */
4711   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4712     {
4713       if (unformat (i, "bd_id %d", &bd_id))
4714         ;
4715       else if (unformat (i, "flood %d", &flood))
4716         ;
4717       else if (unformat (i, "uu-flood %d", &uu_flood))
4718         ;
4719       else if (unformat (i, "forward %d", &forward))
4720         ;
4721       else if (unformat (i, "learn %d", &learn))
4722         ;
4723       else if (unformat (i, "arp-term %d", &arp_term))
4724         ;
4725       else if (unformat (i, "mac-age %d", &mac_age))
4726         ;
4727       else if (unformat (i, "bd-tag %s", &bd_tag))
4728         ;
4729       else if (unformat (i, "del"))
4730         {
4731           is_add = 0;
4732           flood = uu_flood = forward = learn = 0;
4733         }
4734       else
4735         break;
4736     }
4737
4738   if (bd_id == ~0)
4739     {
4740       errmsg ("missing bridge domain");
4741       ret = -99;
4742       goto done;
4743     }
4744
4745   if (mac_age > 255)
4746     {
4747       errmsg ("mac age must be less than 256 ");
4748       ret = -99;
4749       goto done;
4750     }
4751
4752   if ((bd_tag) && (vec_len (bd_tag) > 63))
4753     {
4754       errmsg ("bd-tag cannot be longer than 63");
4755       ret = -99;
4756       goto done;
4757     }
4758
4759   M (BRIDGE_DOMAIN_ADD_DEL, mp);
4760
4761   mp->bd_id = ntohl (bd_id);
4762   mp->flood = flood;
4763   mp->uu_flood = uu_flood;
4764   mp->forward = forward;
4765   mp->learn = learn;
4766   mp->arp_term = arp_term;
4767   mp->is_add = is_add;
4768   mp->mac_age = (u8) mac_age;
4769   if (bd_tag)
4770     {
4771       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
4772       mp->bd_tag[vec_len (bd_tag)] = 0;
4773     }
4774   S (mp);
4775   W (ret);
4776
4777 done:
4778   vec_free (bd_tag);
4779   return ret;
4780 }
4781
4782 static int
4783 api_l2fib_flush_bd (vat_main_t * vam)
4784 {
4785   unformat_input_t *i = vam->input;
4786   vl_api_l2fib_flush_bd_t *mp;
4787   u32 bd_id = ~0;
4788   int ret;
4789
4790   /* Parse args required to build the message */
4791   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4792     {
4793       if (unformat (i, "bd_id %d", &bd_id));
4794       else
4795         break;
4796     }
4797
4798   if (bd_id == ~0)
4799     {
4800       errmsg ("missing bridge domain");
4801       return -99;
4802     }
4803
4804   M (L2FIB_FLUSH_BD, mp);
4805
4806   mp->bd_id = htonl (bd_id);
4807
4808   S (mp);
4809   W (ret);
4810   return ret;
4811 }
4812
4813 static int
4814 api_l2fib_flush_int (vat_main_t * vam)
4815 {
4816   unformat_input_t *i = vam->input;
4817   vl_api_l2fib_flush_int_t *mp;
4818   u32 sw_if_index = ~0;
4819   int ret;
4820
4821   /* Parse args required to build the message */
4822   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4823     {
4824       if (unformat (i, "sw_if_index %d", &sw_if_index));
4825       else
4826         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
4827       else
4828         break;
4829     }
4830
4831   if (sw_if_index == ~0)
4832     {
4833       errmsg ("missing interface name or sw_if_index");
4834       return -99;
4835     }
4836
4837   M (L2FIB_FLUSH_INT, mp);
4838
4839   mp->sw_if_index = ntohl (sw_if_index);
4840
4841   S (mp);
4842   W (ret);
4843   return ret;
4844 }
4845
4846 static int
4847 api_l2fib_add_del (vat_main_t * vam)
4848 {
4849   unformat_input_t *i = vam->input;
4850   vl_api_l2fib_add_del_t *mp;
4851   f64 timeout;
4852   u8 mac[6] = { 0 };
4853   u8 mac_set = 0;
4854   u32 bd_id;
4855   u8 bd_id_set = 0;
4856   u32 sw_if_index = 0;
4857   u8 sw_if_index_set = 0;
4858   u8 is_add = 1;
4859   u8 static_mac = 0;
4860   u8 filter_mac = 0;
4861   u8 bvi_mac = 0;
4862   int count = 1;
4863   f64 before = 0;
4864   int j;
4865
4866   /* Parse args required to build the message */
4867   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4868     {
4869       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
4870         mac_set = 1;
4871       else if (unformat (i, "bd_id %d", &bd_id))
4872         bd_id_set = 1;
4873       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4874         sw_if_index_set = 1;
4875       else if (unformat (i, "sw_if"))
4876         {
4877           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4878             {
4879               if (unformat
4880                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4881                 sw_if_index_set = 1;
4882             }
4883           else
4884             break;
4885         }
4886       else if (unformat (i, "static"))
4887         static_mac = 1;
4888       else if (unformat (i, "filter"))
4889         {
4890           filter_mac = 1;
4891           static_mac = 1;
4892         }
4893       else if (unformat (i, "bvi"))
4894         {
4895           bvi_mac = 1;
4896           static_mac = 1;
4897         }
4898       else if (unformat (i, "del"))
4899         is_add = 0;
4900       else if (unformat (i, "count %d", &count))
4901         ;
4902       else
4903         break;
4904     }
4905
4906   if (mac_set == 0)
4907     {
4908       errmsg ("missing mac address");
4909       return -99;
4910     }
4911
4912   if (bd_id_set == 0)
4913     {
4914       errmsg ("missing bridge domain");
4915       return -99;
4916     }
4917
4918   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
4919     {
4920       errmsg ("missing interface name or sw_if_index");
4921       return -99;
4922     }
4923
4924   if (count > 1)
4925     {
4926       /* Turn on async mode */
4927       vam->async_mode = 1;
4928       vam->async_errors = 0;
4929       before = vat_time_now (vam);
4930     }
4931
4932   for (j = 0; j < count; j++)
4933     {
4934       M (L2FIB_ADD_DEL, mp);
4935
4936       clib_memcpy (mp->mac, mac, 6);
4937       mp->bd_id = ntohl (bd_id);
4938       mp->is_add = is_add;
4939       mp->sw_if_index = ntohl (sw_if_index);
4940
4941       if (is_add)
4942         {
4943           mp->static_mac = static_mac;
4944           mp->filter_mac = filter_mac;
4945           mp->bvi_mac = bvi_mac;
4946         }
4947       increment_mac_address (mac);
4948       /* send it... */
4949       S (mp);
4950     }
4951
4952   if (count > 1)
4953     {
4954       vl_api_control_ping_t *mp_ping;
4955       f64 after;
4956
4957       /* Shut off async mode */
4958       vam->async_mode = 0;
4959
4960       MPING (CONTROL_PING, mp_ping);
4961       S (mp_ping);
4962
4963       timeout = vat_time_now (vam) + 1.0;
4964       while (vat_time_now (vam) < timeout)
4965         if (vam->result_ready == 1)
4966           goto out;
4967       vam->retval = -99;
4968
4969     out:
4970       if (vam->retval == -99)
4971         errmsg ("timeout");
4972
4973       if (vam->async_errors > 0)
4974         {
4975           errmsg ("%d asynchronous errors", vam->async_errors);
4976           vam->retval = -98;
4977         }
4978       vam->async_errors = 0;
4979       after = vat_time_now (vam);
4980
4981       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4982              count, after - before, count / (after - before));
4983     }
4984   else
4985     {
4986       int ret;
4987
4988       /* Wait for a reply... */
4989       W (ret);
4990       return ret;
4991     }
4992   /* Return the good/bad news */
4993   return (vam->retval);
4994 }
4995
4996 static int
4997 api_bridge_domain_set_mac_age (vat_main_t * vam)
4998 {
4999   unformat_input_t *i = vam->input;
5000   vl_api_bridge_domain_set_mac_age_t *mp;
5001   u32 bd_id = ~0;
5002   u32 mac_age = 0;
5003   int ret;
5004
5005   /* Parse args required to build the message */
5006   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5007     {
5008       if (unformat (i, "bd_id %d", &bd_id));
5009       else if (unformat (i, "mac-age %d", &mac_age));
5010       else
5011         break;
5012     }
5013
5014   if (bd_id == ~0)
5015     {
5016       errmsg ("missing bridge domain");
5017       return -99;
5018     }
5019
5020   if (mac_age > 255)
5021     {
5022       errmsg ("mac age must be less than 256 ");
5023       return -99;
5024     }
5025
5026   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
5027
5028   mp->bd_id = htonl (bd_id);
5029   mp->mac_age = (u8) mac_age;
5030
5031   S (mp);
5032   W (ret);
5033   return ret;
5034 }
5035
5036 static int
5037 api_l2_flags (vat_main_t * vam)
5038 {
5039   unformat_input_t *i = vam->input;
5040   vl_api_l2_flags_t *mp;
5041   u32 sw_if_index;
5042   u32 flags = 0;
5043   u8 sw_if_index_set = 0;
5044   u8 is_set = 0;
5045   int ret;
5046
5047   /* Parse args required to build the message */
5048   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5049     {
5050       if (unformat (i, "sw_if_index %d", &sw_if_index))
5051         sw_if_index_set = 1;
5052       else if (unformat (i, "sw_if"))
5053         {
5054           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5055             {
5056               if (unformat
5057                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5058                 sw_if_index_set = 1;
5059             }
5060           else
5061             break;
5062         }
5063       else if (unformat (i, "learn"))
5064         flags |= L2_LEARN;
5065       else if (unformat (i, "forward"))
5066         flags |= L2_FWD;
5067       else if (unformat (i, "flood"))
5068         flags |= L2_FLOOD;
5069       else if (unformat (i, "uu-flood"))
5070         flags |= L2_UU_FLOOD;
5071       else if (unformat (i, "arp-term"))
5072         flags |= L2_ARP_TERM;
5073       else if (unformat (i, "off"))
5074         is_set = 0;
5075       else if (unformat (i, "disable"))
5076         is_set = 0;
5077       else
5078         break;
5079     }
5080
5081   if (sw_if_index_set == 0)
5082     {
5083       errmsg ("missing interface name or sw_if_index");
5084       return -99;
5085     }
5086
5087   M (L2_FLAGS, mp);
5088
5089   mp->sw_if_index = ntohl (sw_if_index);
5090   mp->feature_bitmap = ntohl (flags);
5091   mp->is_set = is_set;
5092
5093   S (mp);
5094   W (ret);
5095   return ret;
5096 }
5097
5098 static int
5099 api_bridge_flags (vat_main_t * vam)
5100 {
5101   unformat_input_t *i = vam->input;
5102   vl_api_bridge_flags_t *mp;
5103   u32 bd_id;
5104   u8 bd_id_set = 0;
5105   u8 is_set = 1;
5106   bd_flags_t flags = 0;
5107   int ret;
5108
5109   /* Parse args required to build the message */
5110   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5111     {
5112       if (unformat (i, "bd_id %d", &bd_id))
5113         bd_id_set = 1;
5114       else if (unformat (i, "learn"))
5115         flags |= BRIDGE_API_FLAG_LEARN;
5116       else if (unformat (i, "forward"))
5117         flags |= BRIDGE_API_FLAG_FWD;
5118       else if (unformat (i, "flood"))
5119         flags |= BRIDGE_API_FLAG_FLOOD;
5120       else if (unformat (i, "uu-flood"))
5121         flags |= BRIDGE_API_FLAG_UU_FLOOD;
5122       else if (unformat (i, "arp-term"))
5123         flags |= BRIDGE_API_FLAG_ARP_TERM;
5124       else if (unformat (i, "off"))
5125         is_set = 0;
5126       else if (unformat (i, "disable"))
5127         is_set = 0;
5128       else
5129         break;
5130     }
5131
5132   if (bd_id_set == 0)
5133     {
5134       errmsg ("missing bridge domain");
5135       return -99;
5136     }
5137
5138   M (BRIDGE_FLAGS, mp);
5139
5140   mp->bd_id = ntohl (bd_id);
5141   mp->flags = ntohl (flags);
5142   mp->is_set = is_set;
5143
5144   S (mp);
5145   W (ret);
5146   return ret;
5147 }
5148
5149 static int
5150 api_bd_ip_mac_add_del (vat_main_t * vam)
5151 {
5152   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
5153   vl_api_mac_address_t mac = { 0 };
5154   unformat_input_t *i = vam->input;
5155   vl_api_bd_ip_mac_add_del_t *mp;
5156   u32 bd_id;
5157   u8 is_add = 1;
5158   u8 bd_id_set = 0;
5159   u8 ip_set = 0;
5160   u8 mac_set = 0;
5161   int ret;
5162
5163
5164   /* Parse args required to build the message */
5165   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5166     {
5167       if (unformat (i, "bd_id %d", &bd_id))
5168         {
5169           bd_id_set++;
5170         }
5171       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
5172         {
5173           ip_set++;
5174         }
5175       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
5176         {
5177           mac_set++;
5178         }
5179       else if (unformat (i, "del"))
5180         is_add = 0;
5181       else
5182         break;
5183     }
5184
5185   if (bd_id_set == 0)
5186     {
5187       errmsg ("missing bridge domain");
5188       return -99;
5189     }
5190   else if (ip_set == 0)
5191     {
5192       errmsg ("missing IP address");
5193       return -99;
5194     }
5195   else if (mac_set == 0)
5196     {
5197       errmsg ("missing MAC address");
5198       return -99;
5199     }
5200
5201   M (BD_IP_MAC_ADD_DEL, mp);
5202
5203   mp->entry.bd_id = ntohl (bd_id);
5204   mp->is_add = is_add;
5205
5206   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
5207   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
5208
5209   S (mp);
5210   W (ret);
5211   return ret;
5212 }
5213
5214 static int
5215 api_bd_ip_mac_flush (vat_main_t * vam)
5216 {
5217   unformat_input_t *i = vam->input;
5218   vl_api_bd_ip_mac_flush_t *mp;
5219   u32 bd_id;
5220   u8 bd_id_set = 0;
5221   int ret;
5222
5223   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5224     {
5225       if (unformat (i, "bd_id %d", &bd_id))
5226         {
5227           bd_id_set++;
5228         }
5229       else
5230         break;
5231     }
5232
5233   if (bd_id_set == 0)
5234     {
5235       errmsg ("missing bridge domain");
5236       return -99;
5237     }
5238
5239   M (BD_IP_MAC_FLUSH, mp);
5240
5241   mp->bd_id = ntohl (bd_id);
5242
5243   S (mp);
5244   W (ret);
5245   return ret;
5246 }
5247
5248 static void vl_api_bd_ip_mac_details_t_handler
5249   (vl_api_bd_ip_mac_details_t * mp)
5250 {
5251   vat_main_t *vam = &vat_main;
5252
5253   print (vam->ofp,
5254          "\n%-5d %U %U",
5255          ntohl (mp->entry.bd_id),
5256          format_vl_api_mac_address, mp->entry.mac,
5257          format_vl_api_address, &mp->entry.ip);
5258 }
5259
5260 static void vl_api_bd_ip_mac_details_t_handler_json
5261   (vl_api_bd_ip_mac_details_t * mp)
5262 {
5263   vat_main_t *vam = &vat_main;
5264   vat_json_node_t *node = NULL;
5265
5266   if (VAT_JSON_ARRAY != vam->json_tree.type)
5267     {
5268       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5269       vat_json_init_array (&vam->json_tree);
5270     }
5271   node = vat_json_array_add (&vam->json_tree);
5272
5273   vat_json_init_object (node);
5274   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
5275   vat_json_object_add_string_copy (node, "mac_address",
5276                                    format (0, "%U", format_vl_api_mac_address,
5277                                            &mp->entry.mac));
5278   u8 *ip = 0;
5279
5280   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
5281   vat_json_object_add_string_copy (node, "ip_address", ip);
5282   vec_free (ip);
5283 }
5284
5285 static int
5286 api_bd_ip_mac_dump (vat_main_t * vam)
5287 {
5288   unformat_input_t *i = vam->input;
5289   vl_api_bd_ip_mac_dump_t *mp;
5290   vl_api_control_ping_t *mp_ping;
5291   int ret;
5292   u32 bd_id;
5293   u8 bd_id_set = 0;
5294
5295   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5296     {
5297       if (unformat (i, "bd_id %d", &bd_id))
5298         {
5299           bd_id_set++;
5300         }
5301       else
5302         break;
5303     }
5304
5305   print (vam->ofp,
5306          "\n%-5s %-7s %-20s %-30s",
5307          "bd_id", "is_ipv6", "mac_address", "ip_address");
5308
5309   /* Dump Bridge Domain Ip to Mac entries */
5310   M (BD_IP_MAC_DUMP, mp);
5311
5312   if (bd_id_set)
5313     mp->bd_id = htonl (bd_id);
5314   else
5315     mp->bd_id = ~0;
5316
5317   S (mp);
5318
5319   /* Use a control ping for synchronization */
5320   MPING (CONTROL_PING, mp_ping);
5321   S (mp_ping);
5322
5323   W (ret);
5324   return ret;
5325 }
5326
5327 static int
5328 api_tap_create_v2 (vat_main_t * vam)
5329 {
5330   unformat_input_t *i = vam->input;
5331   vl_api_tap_create_v2_t *mp;
5332   u8 mac_address[6];
5333   u8 random_mac = 1;
5334   u32 id = ~0;
5335   u32 num_rx_queues = 0;
5336   u8 *host_if_name = 0;
5337   u8 host_if_name_set = 0;
5338   u8 *host_ns = 0;
5339   u8 host_ns_set = 0;
5340   u8 host_mac_addr[6];
5341   u8 host_mac_addr_set = 0;
5342   u8 *host_bridge = 0;
5343   u8 host_bridge_set = 0;
5344   u8 host_ip4_prefix_set = 0;
5345   u8 host_ip6_prefix_set = 0;
5346   ip4_address_t host_ip4_addr;
5347   ip4_address_t host_ip4_gw;
5348   u8 host_ip4_gw_set = 0;
5349   u32 host_ip4_prefix_len = 0;
5350   ip6_address_t host_ip6_addr;
5351   ip6_address_t host_ip6_gw;
5352   u8 host_ip6_gw_set = 0;
5353   u32 host_ip6_prefix_len = 0;
5354   u32 host_mtu_size = 0;
5355   u8 host_mtu_set = 0;
5356   u32 tap_flags = 0;
5357   int ret;
5358   u32 rx_ring_sz = 0, tx_ring_sz = 0;
5359
5360   clib_memset (mac_address, 0, sizeof (mac_address));
5361
5362   /* Parse args required to build the message */
5363   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5364     {
5365       if (unformat (i, "id %u", &id))
5366         ;
5367       else
5368         if (unformat
5369             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5370         random_mac = 0;
5371       else if (unformat (i, "host-if-name %s", &host_if_name))
5372         host_if_name_set = 1;
5373       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
5374         ;
5375       else if (unformat (i, "host-ns %s", &host_ns))
5376         host_ns_set = 1;
5377       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
5378                          host_mac_addr))
5379         host_mac_addr_set = 1;
5380       else if (unformat (i, "host-bridge %s", &host_bridge))
5381         host_bridge_set = 1;
5382       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
5383                          &host_ip4_addr, &host_ip4_prefix_len))
5384         host_ip4_prefix_set = 1;
5385       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
5386                          &host_ip6_addr, &host_ip6_prefix_len))
5387         host_ip6_prefix_set = 1;
5388       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
5389                          &host_ip4_gw))
5390         host_ip4_gw_set = 1;
5391       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
5392                          &host_ip6_gw))
5393         host_ip6_gw_set = 1;
5394       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
5395         ;
5396       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
5397         ;
5398       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
5399         host_mtu_set = 1;
5400       else if (unformat (i, "no-gso"))
5401         tap_flags &= ~TAP_API_FLAG_GSO;
5402       else if (unformat (i, "gso"))
5403         tap_flags |= TAP_API_FLAG_GSO;
5404       else if (unformat (i, "csum-offload"))
5405         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
5406       else if (unformat (i, "persist"))
5407         tap_flags |= TAP_API_FLAG_PERSIST;
5408       else if (unformat (i, "attach"))
5409         tap_flags |= TAP_API_FLAG_ATTACH;
5410       else if (unformat (i, "tun"))
5411         tap_flags |= TAP_API_FLAG_TUN;
5412       else if (unformat (i, "gro-coalesce"))
5413         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
5414       else if (unformat (i, "packed"))
5415         tap_flags |= TAP_API_FLAG_PACKED;
5416       else if (unformat (i, "in-order"))
5417         tap_flags |= TAP_API_FLAG_IN_ORDER;
5418       else
5419         break;
5420     }
5421
5422   if (vec_len (host_if_name) > 63)
5423     {
5424       errmsg ("tap name too long. ");
5425       return -99;
5426     }
5427   if (vec_len (host_ns) > 63)
5428     {
5429       errmsg ("host name space too long. ");
5430       return -99;
5431     }
5432   if (vec_len (host_bridge) > 63)
5433     {
5434       errmsg ("host bridge name too long. ");
5435       return -99;
5436     }
5437   if (host_ip4_prefix_len > 32)
5438     {
5439       errmsg ("host ip4 prefix length not valid. ");
5440       return -99;
5441     }
5442   if (host_ip6_prefix_len > 128)
5443     {
5444       errmsg ("host ip6 prefix length not valid. ");
5445       return -99;
5446     }
5447   if (!is_pow2 (rx_ring_sz))
5448     {
5449       errmsg ("rx ring size must be power of 2. ");
5450       return -99;
5451     }
5452   if (rx_ring_sz > 32768)
5453     {
5454       errmsg ("rx ring size must be 32768 or lower. ");
5455       return -99;
5456     }
5457   if (!is_pow2 (tx_ring_sz))
5458     {
5459       errmsg ("tx ring size must be power of 2. ");
5460       return -99;
5461     }
5462   if (tx_ring_sz > 32768)
5463     {
5464       errmsg ("tx ring size must be 32768 or lower. ");
5465       return -99;
5466     }
5467   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
5468     {
5469       errmsg ("host MTU size must be in between 64 and 65355. ");
5470       return -99;
5471     }
5472
5473   /* Construct the API message */
5474   M (TAP_CREATE_V2, mp);
5475
5476   mp->id = ntohl (id);
5477   mp->use_random_mac = random_mac;
5478   mp->num_rx_queues = (u8) num_rx_queues;
5479   mp->tx_ring_sz = ntohs (tx_ring_sz);
5480   mp->rx_ring_sz = ntohs (rx_ring_sz);
5481   mp->host_mtu_set = host_mtu_set;
5482   mp->host_mtu_size = ntohl (host_mtu_size);
5483   mp->host_mac_addr_set = host_mac_addr_set;
5484   mp->host_ip4_prefix_set = host_ip4_prefix_set;
5485   mp->host_ip6_prefix_set = host_ip6_prefix_set;
5486   mp->host_ip4_gw_set = host_ip4_gw_set;
5487   mp->host_ip6_gw_set = host_ip6_gw_set;
5488   mp->tap_flags = ntohl (tap_flags);
5489   mp->host_namespace_set = host_ns_set;
5490   mp->host_if_name_set = host_if_name_set;
5491   mp->host_bridge_set = host_bridge_set;
5492
5493   if (random_mac == 0)
5494     clib_memcpy (mp->mac_address, mac_address, 6);
5495   if (host_mac_addr_set)
5496     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
5497   if (host_if_name_set)
5498     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
5499   if (host_ns_set)
5500     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
5501   if (host_bridge_set)
5502     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
5503   if (host_ip4_prefix_set)
5504     {
5505       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
5506       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
5507     }
5508   if (host_ip6_prefix_set)
5509     {
5510       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
5511       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
5512     }
5513   if (host_ip4_gw_set)
5514     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
5515   if (host_ip6_gw_set)
5516     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
5517
5518   vec_free (host_ns);
5519   vec_free (host_if_name);
5520   vec_free (host_bridge);
5521
5522   /* send it... */
5523   S (mp);
5524
5525   /* Wait for a reply... */
5526   W (ret);
5527   return ret;
5528 }
5529
5530 static int
5531 api_tap_delete_v2 (vat_main_t * vam)
5532 {
5533   unformat_input_t *i = vam->input;
5534   vl_api_tap_delete_v2_t *mp;
5535   u32 sw_if_index = ~0;
5536   u8 sw_if_index_set = 0;
5537   int ret;
5538
5539   /* Parse args required to build the message */
5540   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5541     {
5542       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5543         sw_if_index_set = 1;
5544       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5545         sw_if_index_set = 1;
5546       else
5547         break;
5548     }
5549
5550   if (sw_if_index_set == 0)
5551     {
5552       errmsg ("missing vpp interface name. ");
5553       return -99;
5554     }
5555
5556   /* Construct the API message */
5557   M (TAP_DELETE_V2, mp);
5558
5559   mp->sw_if_index = ntohl (sw_if_index);
5560
5561   /* send it... */
5562   S (mp);
5563
5564   /* Wait for a reply... */
5565   W (ret);
5566   return ret;
5567 }
5568
5569 uword
5570 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
5571 {
5572   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
5573   u32 x[4];
5574
5575   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
5576     return 0;
5577
5578   addr->domain = x[0];
5579   addr->bus = x[1];
5580   addr->slot = x[2];
5581   addr->function = x[3];
5582
5583   return 1;
5584 }
5585
5586 static int
5587 api_virtio_pci_create_v2 (vat_main_t * vam)
5588 {
5589   unformat_input_t *i = vam->input;
5590   vl_api_virtio_pci_create_v2_t *mp;
5591   u8 mac_address[6];
5592   u8 random_mac = 1;
5593   u32 pci_addr = 0;
5594   u64 features = (u64) ~ (0ULL);
5595   u32 virtio_flags = 0;
5596   int ret;
5597
5598   clib_memset (mac_address, 0, sizeof (mac_address));
5599
5600   /* Parse args required to build the message */
5601   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5602     {
5603       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5604         {
5605           random_mac = 0;
5606         }
5607       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
5608         ;
5609       else if (unformat (i, "features 0x%llx", &features))
5610         ;
5611       else if (unformat (i, "gso-enabled"))
5612         virtio_flags |= VIRTIO_API_FLAG_GSO;
5613       else if (unformat (i, "csum-offload-enabled"))
5614         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
5615       else if (unformat (i, "gro-coalesce"))
5616         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
5617       else if (unformat (i, "packed"))
5618         virtio_flags |= VIRTIO_API_FLAG_PACKED;
5619       else if (unformat (i, "in-order"))
5620         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
5621       else if (unformat (i, "buffering"))
5622         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
5623       else
5624         break;
5625     }
5626
5627   if (pci_addr == 0)
5628     {
5629       errmsg ("pci address must be non zero. ");
5630       return -99;
5631     }
5632
5633   /* Construct the API message */
5634   M (VIRTIO_PCI_CREATE_V2, mp);
5635
5636   mp->use_random_mac = random_mac;
5637
5638   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
5639   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
5640   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
5641   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
5642
5643   mp->features = clib_host_to_net_u64 (features);
5644   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
5645
5646   if (random_mac == 0)
5647     clib_memcpy (mp->mac_address, mac_address, 6);
5648
5649   /* send it... */
5650   S (mp);
5651
5652   /* Wait for a reply... */
5653   W (ret);
5654   return ret;
5655 }
5656
5657 static int
5658 api_virtio_pci_delete (vat_main_t * vam)
5659 {
5660   unformat_input_t *i = vam->input;
5661   vl_api_virtio_pci_delete_t *mp;
5662   u32 sw_if_index = ~0;
5663   u8 sw_if_index_set = 0;
5664   int ret;
5665
5666   /* Parse args required to build the message */
5667   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5668     {
5669       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5670         sw_if_index_set = 1;
5671       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5672         sw_if_index_set = 1;
5673       else
5674         break;
5675     }
5676
5677   if (sw_if_index_set == 0)
5678     {
5679       errmsg ("missing vpp interface name. ");
5680       return -99;
5681     }
5682
5683   /* Construct the API message */
5684   M (VIRTIO_PCI_DELETE, mp);
5685
5686   mp->sw_if_index = htonl (sw_if_index);
5687
5688   /* send it... */
5689   S (mp);
5690
5691   /* Wait for a reply... */
5692   W (ret);
5693   return ret;
5694 }
5695
5696 static int
5697 api_bond_create (vat_main_t * vam)
5698 {
5699   unformat_input_t *i = vam->input;
5700   vl_api_bond_create_t *mp;
5701   u8 mac_address[6];
5702   u8 custom_mac = 0;
5703   int ret;
5704   u8 mode;
5705   u8 lb;
5706   u8 mode_is_set = 0;
5707   u32 id = ~0;
5708   u8 numa_only = 0;
5709
5710   clib_memset (mac_address, 0, sizeof (mac_address));
5711   lb = BOND_LB_L2;
5712
5713   /* Parse args required to build the message */
5714   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5715     {
5716       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5717         mode_is_set = 1;
5718       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5719                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5720         ;
5721       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5722                          mac_address))
5723         custom_mac = 1;
5724       else if (unformat (i, "numa-only"))
5725         numa_only = 1;
5726       else if (unformat (i, "id %u", &id))
5727         ;
5728       else
5729         break;
5730     }
5731
5732   if (mode_is_set == 0)
5733     {
5734       errmsg ("Missing bond mode. ");
5735       return -99;
5736     }
5737
5738   /* Construct the API message */
5739   M (BOND_CREATE, mp);
5740
5741   mp->use_custom_mac = custom_mac;
5742
5743   mp->mode = htonl (mode);
5744   mp->lb = htonl (lb);
5745   mp->id = htonl (id);
5746   mp->numa_only = numa_only;
5747
5748   if (custom_mac)
5749     clib_memcpy (mp->mac_address, mac_address, 6);
5750
5751   /* send it... */
5752   S (mp);
5753
5754   /* Wait for a reply... */
5755   W (ret);
5756   return ret;
5757 }
5758
5759 static int
5760 api_bond_create2 (vat_main_t * vam)
5761 {
5762   unformat_input_t *i = vam->input;
5763   vl_api_bond_create2_t *mp;
5764   u8 mac_address[6];
5765   u8 custom_mac = 0;
5766   int ret;
5767   u8 mode;
5768   u8 lb;
5769   u8 mode_is_set = 0;
5770   u32 id = ~0;
5771   u8 numa_only = 0;
5772   u8 gso = 0;
5773
5774   clib_memset (mac_address, 0, sizeof (mac_address));
5775   lb = BOND_LB_L2;
5776
5777   /* Parse args required to build the message */
5778   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5779     {
5780       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5781         mode_is_set = 1;
5782       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5783                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5784         ;
5785       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5786                          mac_address))
5787         custom_mac = 1;
5788       else if (unformat (i, "numa-only"))
5789         numa_only = 1;
5790       else if (unformat (i, "gso"))
5791         gso = 1;
5792       else if (unformat (i, "id %u", &id))
5793         ;
5794       else
5795         break;
5796     }
5797
5798   if (mode_is_set == 0)
5799     {
5800       errmsg ("Missing bond mode. ");
5801       return -99;
5802     }
5803
5804   /* Construct the API message */
5805   M (BOND_CREATE2, mp);
5806
5807   mp->use_custom_mac = custom_mac;
5808
5809   mp->mode = htonl (mode);
5810   mp->lb = htonl (lb);
5811   mp->id = htonl (id);
5812   mp->numa_only = numa_only;
5813   mp->enable_gso = gso;
5814
5815   if (custom_mac)
5816     clib_memcpy (mp->mac_address, mac_address, 6);
5817
5818   /* send it... */
5819   S (mp);
5820
5821   /* Wait for a reply... */
5822   W (ret);
5823   return ret;
5824 }
5825
5826 static int
5827 api_bond_delete (vat_main_t * vam)
5828 {
5829   unformat_input_t *i = vam->input;
5830   vl_api_bond_delete_t *mp;
5831   u32 sw_if_index = ~0;
5832   u8 sw_if_index_set = 0;
5833   int ret;
5834
5835   /* Parse args required to build the message */
5836   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5837     {
5838       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5839         sw_if_index_set = 1;
5840       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5841         sw_if_index_set = 1;
5842       else
5843         break;
5844     }
5845
5846   if (sw_if_index_set == 0)
5847     {
5848       errmsg ("missing vpp interface name. ");
5849       return -99;
5850     }
5851
5852   /* Construct the API message */
5853   M (BOND_DELETE, mp);
5854
5855   mp->sw_if_index = ntohl (sw_if_index);
5856
5857   /* send it... */
5858   S (mp);
5859
5860   /* Wait for a reply... */
5861   W (ret);
5862   return ret;
5863 }
5864
5865 static int
5866 api_bond_add_member (vat_main_t * vam)
5867 {
5868   unformat_input_t *i = vam->input;
5869   vl_api_bond_add_member_t *mp;
5870   u32 bond_sw_if_index;
5871   int ret;
5872   u8 is_passive;
5873   u8 is_long_timeout;
5874   u32 bond_sw_if_index_is_set = 0;
5875   u32 sw_if_index;
5876   u8 sw_if_index_is_set = 0;
5877
5878   /* Parse args required to build the message */
5879   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5880     {
5881       if (unformat (i, "sw_if_index %d", &sw_if_index))
5882         sw_if_index_is_set = 1;
5883       else if (unformat (i, "bond %u", &bond_sw_if_index))
5884         bond_sw_if_index_is_set = 1;
5885       else if (unformat (i, "passive %d", &is_passive))
5886         ;
5887       else if (unformat (i, "long-timeout %d", &is_long_timeout))
5888         ;
5889       else
5890         break;
5891     }
5892
5893   if (bond_sw_if_index_is_set == 0)
5894     {
5895       errmsg ("Missing bond sw_if_index. ");
5896       return -99;
5897     }
5898   if (sw_if_index_is_set == 0)
5899     {
5900       errmsg ("Missing member sw_if_index. ");
5901       return -99;
5902     }
5903
5904   /* Construct the API message */
5905   M (BOND_ADD_MEMBER, mp);
5906
5907   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
5908   mp->sw_if_index = ntohl (sw_if_index);
5909   mp->is_long_timeout = is_long_timeout;
5910   mp->is_passive = is_passive;
5911
5912   /* send it... */
5913   S (mp);
5914
5915   /* Wait for a reply... */
5916   W (ret);
5917   return ret;
5918 }
5919
5920 static int
5921 api_bond_detach_member (vat_main_t * vam)
5922 {
5923   unformat_input_t *i = vam->input;
5924   vl_api_bond_detach_member_t *mp;
5925   u32 sw_if_index = ~0;
5926   u8 sw_if_index_set = 0;
5927   int ret;
5928
5929   /* Parse args required to build the message */
5930   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5931     {
5932       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5933         sw_if_index_set = 1;
5934       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5935         sw_if_index_set = 1;
5936       else
5937         break;
5938     }
5939
5940   if (sw_if_index_set == 0)
5941     {
5942       errmsg ("missing vpp interface name. ");
5943       return -99;
5944     }
5945
5946   /* Construct the API message */
5947   M (BOND_DETACH_MEMBER, mp);
5948
5949   mp->sw_if_index = ntohl (sw_if_index);
5950
5951   /* send it... */
5952   S (mp);
5953
5954   /* Wait for a reply... */
5955   W (ret);
5956   return ret;
5957 }
5958
5959 static int
5960 api_ip_table_add_del (vat_main_t * vam)
5961 {
5962   unformat_input_t *i = vam->input;
5963   vl_api_ip_table_add_del_t *mp;
5964   u32 table_id = ~0;
5965   u8 is_ipv6 = 0;
5966   u8 is_add = 1;
5967   int ret = 0;
5968
5969   /* Parse args required to build the message */
5970   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5971     {
5972       if (unformat (i, "ipv6"))
5973         is_ipv6 = 1;
5974       else if (unformat (i, "del"))
5975         is_add = 0;
5976       else if (unformat (i, "add"))
5977         is_add = 1;
5978       else if (unformat (i, "table %d", &table_id))
5979         ;
5980       else
5981         {
5982           clib_warning ("parse error '%U'", format_unformat_error, i);
5983           return -99;
5984         }
5985     }
5986
5987   if (~0 == table_id)
5988     {
5989       errmsg ("missing table-ID");
5990       return -99;
5991     }
5992
5993   /* Construct the API message */
5994   M (IP_TABLE_ADD_DEL, mp);
5995
5996   mp->table.table_id = ntohl (table_id);
5997   mp->table.is_ip6 = is_ipv6;
5998   mp->is_add = is_add;
5999
6000   /* send it... */
6001   S (mp);
6002
6003   /* Wait for a reply... */
6004   W (ret);
6005
6006   return ret;
6007 }
6008
6009 uword
6010 unformat_fib_path (unformat_input_t * input, va_list * args)
6011 {
6012   vat_main_t *vam = va_arg (*args, vat_main_t *);
6013   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
6014   u32 weight, preference;
6015   mpls_label_t out_label;
6016
6017   clib_memset (path, 0, sizeof (*path));
6018   path->weight = 1;
6019   path->sw_if_index = ~0;
6020   path->rpf_id = ~0;
6021   path->n_labels = 0;
6022
6023   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6024     {
6025       if (unformat (input, "%U %U",
6026                     unformat_vl_api_ip4_address,
6027                     &path->nh.address.ip4,
6028                     api_unformat_sw_if_index, vam, &path->sw_if_index))
6029         {
6030           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6031         }
6032       else if (unformat (input, "%U %U",
6033                          unformat_vl_api_ip6_address,
6034                          &path->nh.address.ip6,
6035                          api_unformat_sw_if_index, vam, &path->sw_if_index))
6036         {
6037           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6038         }
6039       else if (unformat (input, "weight %u", &weight))
6040         {
6041           path->weight = weight;
6042         }
6043       else if (unformat (input, "preference %u", &preference))
6044         {
6045           path->preference = preference;
6046         }
6047       else if (unformat (input, "%U next-hop-table %d",
6048                          unformat_vl_api_ip4_address,
6049                          &path->nh.address.ip4, &path->table_id))
6050         {
6051           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6052         }
6053       else if (unformat (input, "%U next-hop-table %d",
6054                          unformat_vl_api_ip6_address,
6055                          &path->nh.address.ip6, &path->table_id))
6056         {
6057           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6058         }
6059       else if (unformat (input, "%U",
6060                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
6061         {
6062           /*
6063            * the recursive next-hops are by default in the default table
6064            */
6065           path->table_id = 0;
6066           path->sw_if_index = ~0;
6067           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6068         }
6069       else if (unformat (input, "%U",
6070                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
6071         {
6072           /*
6073            * the recursive next-hops are by default in the default table
6074            */
6075           path->table_id = 0;
6076           path->sw_if_index = ~0;
6077           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6078         }
6079       else if (unformat (input, "resolve-via-host"))
6080         {
6081           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
6082         }
6083       else if (unformat (input, "resolve-via-attached"))
6084         {
6085           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
6086         }
6087       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
6088         {
6089           path->type = FIB_API_PATH_TYPE_LOCAL;
6090           path->sw_if_index = ~0;
6091           path->proto = FIB_API_PATH_NH_PROTO_IP4;
6092         }
6093       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
6094         {
6095           path->type = FIB_API_PATH_TYPE_LOCAL;
6096           path->sw_if_index = ~0;
6097           path->proto = FIB_API_PATH_NH_PROTO_IP6;
6098         }
6099       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
6100         ;
6101       else if (unformat (input, "via-label %d", &path->nh.via_label))
6102         {
6103           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
6104           path->sw_if_index = ~0;
6105         }
6106       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
6107         {
6108           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
6109           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
6110         }
6111       else if (unformat (input, "local"))
6112         {
6113           path->type = FIB_API_PATH_TYPE_LOCAL;
6114         }
6115       else if (unformat (input, "out-labels"))
6116         {
6117           while (unformat (input, "%d", &out_label))
6118             {
6119               path->label_stack[path->n_labels].label = out_label;
6120               path->label_stack[path->n_labels].is_uniform = 0;
6121               path->label_stack[path->n_labels].ttl = 64;
6122               path->n_labels++;
6123             }
6124         }
6125       else if (unformat (input, "via"))
6126         {
6127           /* new path, back up and return */
6128           unformat_put_input (input);
6129           unformat_put_input (input);
6130           unformat_put_input (input);
6131           unformat_put_input (input);
6132           break;
6133         }
6134       else
6135         {
6136           return (0);
6137         }
6138     }
6139
6140   path->proto = ntohl (path->proto);
6141   path->type = ntohl (path->type);
6142   path->flags = ntohl (path->flags);
6143   path->table_id = ntohl (path->table_id);
6144   path->sw_if_index = ntohl (path->sw_if_index);
6145
6146   return (1);
6147 }
6148
6149 static int
6150 api_ip_route_add_del (vat_main_t * vam)
6151 {
6152   unformat_input_t *i = vam->input;
6153   vl_api_ip_route_add_del_t *mp;
6154   u32 vrf_id = 0;
6155   u8 is_add = 1;
6156   u8 is_multipath = 0;
6157   u8 prefix_set = 0;
6158   u8 path_count = 0;
6159   vl_api_prefix_t pfx = { };
6160   vl_api_fib_path_t paths[8];
6161   int count = 1;
6162   int j;
6163   f64 before = 0;
6164   u32 random_add_del = 0;
6165   u32 *random_vector = 0;
6166   u32 random_seed = 0xdeaddabe;
6167
6168   /* Parse args required to build the message */
6169   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6170     {
6171       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6172         prefix_set = 1;
6173       else if (unformat (i, "del"))
6174         is_add = 0;
6175       else if (unformat (i, "add"))
6176         is_add = 1;
6177       else if (unformat (i, "vrf %d", &vrf_id))
6178         ;
6179       else if (unformat (i, "count %d", &count))
6180         ;
6181       else if (unformat (i, "random"))
6182         random_add_del = 1;
6183       else if (unformat (i, "multipath"))
6184         is_multipath = 1;
6185       else if (unformat (i, "seed %d", &random_seed))
6186         ;
6187       else
6188         if (unformat
6189             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6190         {
6191           path_count++;
6192           if (8 == path_count)
6193             {
6194               errmsg ("max 8 paths");
6195               return -99;
6196             }
6197         }
6198       else
6199         {
6200           clib_warning ("parse error '%U'", format_unformat_error, i);
6201           return -99;
6202         }
6203     }
6204
6205   if (!path_count)
6206     {
6207       errmsg ("specify a path; via ...");
6208       return -99;
6209     }
6210   if (prefix_set == 0)
6211     {
6212       errmsg ("missing prefix");
6213       return -99;
6214     }
6215
6216   /* Generate a pile of unique, random routes */
6217   if (random_add_del)
6218     {
6219       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
6220       u32 this_random_address;
6221       uword *random_hash;
6222
6223       random_hash = hash_create (count, sizeof (uword));
6224
6225       hash_set (random_hash, i->as_u32, 1);
6226       for (j = 0; j <= count; j++)
6227         {
6228           do
6229             {
6230               this_random_address = random_u32 (&random_seed);
6231               this_random_address =
6232                 clib_host_to_net_u32 (this_random_address);
6233             }
6234           while (hash_get (random_hash, this_random_address));
6235           vec_add1 (random_vector, this_random_address);
6236           hash_set (random_hash, this_random_address, 1);
6237         }
6238       hash_free (random_hash);
6239       set_ip4_address (&pfx.address, random_vector[0]);
6240     }
6241
6242   if (count > 1)
6243     {
6244       /* Turn on async mode */
6245       vam->async_mode = 1;
6246       vam->async_errors = 0;
6247       before = vat_time_now (vam);
6248     }
6249
6250   for (j = 0; j < count; j++)
6251     {
6252       /* Construct the API message */
6253       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6254
6255       mp->is_add = is_add;
6256       mp->is_multipath = is_multipath;
6257
6258       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6259       mp->route.table_id = ntohl (vrf_id);
6260       mp->route.n_paths = path_count;
6261
6262       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
6263
6264       if (random_add_del)
6265         set_ip4_address (&pfx.address, random_vector[j + 1]);
6266       else
6267         increment_address (&pfx.address);
6268       /* send it... */
6269       S (mp);
6270       /* If we receive SIGTERM, stop now... */
6271       if (vam->do_exit)
6272         break;
6273     }
6274
6275   /* When testing multiple add/del ops, use a control-ping to sync */
6276   if (count > 1)
6277     {
6278       vl_api_control_ping_t *mp_ping;
6279       f64 after;
6280       f64 timeout;
6281
6282       /* Shut off async mode */
6283       vam->async_mode = 0;
6284
6285       MPING (CONTROL_PING, mp_ping);
6286       S (mp_ping);
6287
6288       timeout = vat_time_now (vam) + 1.0;
6289       while (vat_time_now (vam) < timeout)
6290         if (vam->result_ready == 1)
6291           goto out;
6292       vam->retval = -99;
6293
6294     out:
6295       if (vam->retval == -99)
6296         errmsg ("timeout");
6297
6298       if (vam->async_errors > 0)
6299         {
6300           errmsg ("%d asynchronous errors", vam->async_errors);
6301           vam->retval = -98;
6302         }
6303       vam->async_errors = 0;
6304       after = vat_time_now (vam);
6305
6306       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6307       if (j > 0)
6308         count = j;
6309
6310       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6311              count, after - before, count / (after - before));
6312     }
6313   else
6314     {
6315       int ret;
6316
6317       /* Wait for a reply... */
6318       W (ret);
6319       return ret;
6320     }
6321
6322   /* Return the good/bad news */
6323   return (vam->retval);
6324 }
6325
6326 static int
6327 api_ip_mroute_add_del (vat_main_t * vam)
6328 {
6329   unformat_input_t *i = vam->input;
6330   u8 path_set = 0, prefix_set = 0, is_add = 1;
6331   vl_api_ip_mroute_add_del_t *mp;
6332   mfib_entry_flags_t eflags = 0;
6333   vl_api_mfib_path_t path;
6334   vl_api_mprefix_t pfx = { };
6335   u32 vrf_id = 0;
6336   int ret;
6337
6338   /* Parse args required to build the message */
6339   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6340     {
6341       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
6342         {
6343           prefix_set = 1;
6344           pfx.grp_address_length = htons (pfx.grp_address_length);
6345         }
6346       else if (unformat (i, "del"))
6347         is_add = 0;
6348       else if (unformat (i, "add"))
6349         is_add = 1;
6350       else if (unformat (i, "vrf %d", &vrf_id))
6351         ;
6352       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
6353         path.itf_flags = htonl (path.itf_flags);
6354       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
6355         ;
6356       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
6357         path_set = 1;
6358       else
6359         {
6360           clib_warning ("parse error '%U'", format_unformat_error, i);
6361           return -99;
6362         }
6363     }
6364
6365   if (prefix_set == 0)
6366     {
6367       errmsg ("missing addresses\n");
6368       return -99;
6369     }
6370   if (path_set == 0)
6371     {
6372       errmsg ("missing path\n");
6373       return -99;
6374     }
6375
6376   /* Construct the API message */
6377   M (IP_MROUTE_ADD_DEL, mp);
6378
6379   mp->is_add = is_add;
6380   mp->is_multipath = 1;
6381
6382   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
6383   mp->route.table_id = htonl (vrf_id);
6384   mp->route.n_paths = 1;
6385   mp->route.entry_flags = htonl (eflags);
6386
6387   clib_memcpy (&mp->route.paths, &path, sizeof (path));
6388
6389   /* send it... */
6390   S (mp);
6391   /* Wait for a reply... */
6392   W (ret);
6393   return ret;
6394 }
6395
6396 static int
6397 api_mpls_table_add_del (vat_main_t * vam)
6398 {
6399   unformat_input_t *i = vam->input;
6400   vl_api_mpls_table_add_del_t *mp;
6401   u32 table_id = ~0;
6402   u8 is_add = 1;
6403   int ret = 0;
6404
6405   /* Parse args required to build the message */
6406   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6407     {
6408       if (unformat (i, "table %d", &table_id))
6409         ;
6410       else if (unformat (i, "del"))
6411         is_add = 0;
6412       else if (unformat (i, "add"))
6413         is_add = 1;
6414       else
6415         {
6416           clib_warning ("parse error '%U'", format_unformat_error, i);
6417           return -99;
6418         }
6419     }
6420
6421   if (~0 == table_id)
6422     {
6423       errmsg ("missing table-ID");
6424       return -99;
6425     }
6426
6427   /* Construct the API message */
6428   M (MPLS_TABLE_ADD_DEL, mp);
6429
6430   mp->mt_table.mt_table_id = ntohl (table_id);
6431   mp->mt_is_add = is_add;
6432
6433   /* send it... */
6434   S (mp);
6435
6436   /* Wait for a reply... */
6437   W (ret);
6438
6439   return ret;
6440 }
6441
6442 static int
6443 api_mpls_route_add_del (vat_main_t * vam)
6444 {
6445   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
6446   mpls_label_t local_label = MPLS_LABEL_INVALID;
6447   unformat_input_t *i = vam->input;
6448   vl_api_mpls_route_add_del_t *mp;
6449   vl_api_fib_path_t paths[8];
6450   int count = 1, j;
6451   f64 before = 0;
6452
6453   /* Parse args required to build the message */
6454   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6455     {
6456       if (unformat (i, "%d", &local_label))
6457         ;
6458       else if (unformat (i, "eos"))
6459         is_eos = 1;
6460       else if (unformat (i, "non-eos"))
6461         is_eos = 0;
6462       else if (unformat (i, "del"))
6463         is_add = 0;
6464       else if (unformat (i, "add"))
6465         is_add = 1;
6466       else if (unformat (i, "multipath"))
6467         is_multipath = 1;
6468       else if (unformat (i, "count %d", &count))
6469         ;
6470       else
6471         if (unformat
6472             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6473         {
6474           path_count++;
6475           if (8 == path_count)
6476             {
6477               errmsg ("max 8 paths");
6478               return -99;
6479             }
6480         }
6481       else
6482         {
6483           clib_warning ("parse error '%U'", format_unformat_error, i);
6484           return -99;
6485         }
6486     }
6487
6488   if (!path_count)
6489     {
6490       errmsg ("specify a path; via ...");
6491       return -99;
6492     }
6493
6494   if (MPLS_LABEL_INVALID == local_label)
6495     {
6496       errmsg ("missing label");
6497       return -99;
6498     }
6499
6500   if (count > 1)
6501     {
6502       /* Turn on async mode */
6503       vam->async_mode = 1;
6504       vam->async_errors = 0;
6505       before = vat_time_now (vam);
6506     }
6507
6508   for (j = 0; j < count; j++)
6509     {
6510       /* Construct the API message */
6511       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6512
6513       mp->mr_is_add = is_add;
6514       mp->mr_is_multipath = is_multipath;
6515
6516       mp->mr_route.mr_label = local_label;
6517       mp->mr_route.mr_eos = is_eos;
6518       mp->mr_route.mr_table_id = 0;
6519       mp->mr_route.mr_n_paths = path_count;
6520
6521       clib_memcpy (&mp->mr_route.mr_paths, paths,
6522                    sizeof (paths[0]) * path_count);
6523
6524       local_label++;
6525
6526       /* send it... */
6527       S (mp);
6528       /* If we receive SIGTERM, stop now... */
6529       if (vam->do_exit)
6530         break;
6531     }
6532
6533   /* When testing multiple add/del ops, use a control-ping to sync */
6534   if (count > 1)
6535     {
6536       vl_api_control_ping_t *mp_ping;
6537       f64 after;
6538       f64 timeout;
6539
6540       /* Shut off async mode */
6541       vam->async_mode = 0;
6542
6543       MPING (CONTROL_PING, mp_ping);
6544       S (mp_ping);
6545
6546       timeout = vat_time_now (vam) + 1.0;
6547       while (vat_time_now (vam) < timeout)
6548         if (vam->result_ready == 1)
6549           goto out;
6550       vam->retval = -99;
6551
6552     out:
6553       if (vam->retval == -99)
6554         errmsg ("timeout");
6555
6556       if (vam->async_errors > 0)
6557         {
6558           errmsg ("%d asynchronous errors", vam->async_errors);
6559           vam->retval = -98;
6560         }
6561       vam->async_errors = 0;
6562       after = vat_time_now (vam);
6563
6564       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6565       if (j > 0)
6566         count = j;
6567
6568       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6569              count, after - before, count / (after - before));
6570     }
6571   else
6572     {
6573       int ret;
6574
6575       /* Wait for a reply... */
6576       W (ret);
6577       return ret;
6578     }
6579
6580   /* Return the good/bad news */
6581   return (vam->retval);
6582   return (0);
6583 }
6584
6585 static int
6586 api_mpls_ip_bind_unbind (vat_main_t * vam)
6587 {
6588   unformat_input_t *i = vam->input;
6589   vl_api_mpls_ip_bind_unbind_t *mp;
6590   u32 ip_table_id = 0;
6591   u8 is_bind = 1;
6592   vl_api_prefix_t pfx;
6593   u8 prefix_set = 0;
6594   mpls_label_t local_label = MPLS_LABEL_INVALID;
6595   int ret;
6596
6597   /* Parse args required to build the message */
6598   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6599     {
6600       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6601         prefix_set = 1;
6602       else if (unformat (i, "%d", &local_label))
6603         ;
6604       else if (unformat (i, "table-id %d", &ip_table_id))
6605         ;
6606       else if (unformat (i, "unbind"))
6607         is_bind = 0;
6608       else if (unformat (i, "bind"))
6609         is_bind = 1;
6610       else
6611         {
6612           clib_warning ("parse error '%U'", format_unformat_error, i);
6613           return -99;
6614         }
6615     }
6616
6617   if (!prefix_set)
6618     {
6619       errmsg ("IP prefix not set");
6620       return -99;
6621     }
6622
6623   if (MPLS_LABEL_INVALID == local_label)
6624     {
6625       errmsg ("missing label");
6626       return -99;
6627     }
6628
6629   /* Construct the API message */
6630   M (MPLS_IP_BIND_UNBIND, mp);
6631
6632   mp->mb_is_bind = is_bind;
6633   mp->mb_ip_table_id = ntohl (ip_table_id);
6634   mp->mb_mpls_table_id = 0;
6635   mp->mb_label = ntohl (local_label);
6636   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
6637
6638   /* send it... */
6639   S (mp);
6640
6641   /* Wait for a reply... */
6642   W (ret);
6643   return ret;
6644   return (0);
6645 }
6646
6647 static int
6648 api_sr_mpls_policy_add (vat_main_t * vam)
6649 {
6650   unformat_input_t *i = vam->input;
6651   vl_api_sr_mpls_policy_add_t *mp;
6652   u32 bsid = 0;
6653   u32 weight = 1;
6654   u8 type = 0;
6655   u8 n_segments = 0;
6656   u32 sid;
6657   u32 *segments = NULL;
6658   int ret;
6659
6660   /* Parse args required to build the message */
6661   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6662     {
6663       if (unformat (i, "bsid %d", &bsid))
6664         ;
6665       else if (unformat (i, "weight %d", &weight))
6666         ;
6667       else if (unformat (i, "spray"))
6668         type = 1;
6669       else if (unformat (i, "next %d", &sid))
6670         {
6671           n_segments += 1;
6672           vec_add1 (segments, htonl (sid));
6673         }
6674       else
6675         {
6676           clib_warning ("parse error '%U'", format_unformat_error, i);
6677           return -99;
6678         }
6679     }
6680
6681   if (bsid == 0)
6682     {
6683       errmsg ("bsid not set");
6684       return -99;
6685     }
6686
6687   if (n_segments == 0)
6688     {
6689       errmsg ("no sid in segment stack");
6690       return -99;
6691     }
6692
6693   /* Construct the API message */
6694   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
6695
6696   mp->bsid = htonl (bsid);
6697   mp->weight = htonl (weight);
6698   mp->is_spray = type;
6699   mp->n_segments = n_segments;
6700   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
6701   vec_free (segments);
6702
6703   /* send it... */
6704   S (mp);
6705
6706   /* Wait for a reply... */
6707   W (ret);
6708   return ret;
6709 }
6710
6711 static int
6712 api_sr_mpls_policy_del (vat_main_t * vam)
6713 {
6714   unformat_input_t *i = vam->input;
6715   vl_api_sr_mpls_policy_del_t *mp;
6716   u32 bsid = 0;
6717   int ret;
6718
6719   /* Parse args required to build the message */
6720   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6721     {
6722       if (unformat (i, "bsid %d", &bsid))
6723         ;
6724       else
6725         {
6726           clib_warning ("parse error '%U'", format_unformat_error, i);
6727           return -99;
6728         }
6729     }
6730
6731   if (bsid == 0)
6732     {
6733       errmsg ("bsid not set");
6734       return -99;
6735     }
6736
6737   /* Construct the API message */
6738   M (SR_MPLS_POLICY_DEL, mp);
6739
6740   mp->bsid = htonl (bsid);
6741
6742   /* send it... */
6743   S (mp);
6744
6745   /* Wait for a reply... */
6746   W (ret);
6747   return ret;
6748 }
6749
6750 static int
6751 api_bier_table_add_del (vat_main_t * vam)
6752 {
6753   unformat_input_t *i = vam->input;
6754   vl_api_bier_table_add_del_t *mp;
6755   u8 is_add = 1;
6756   u32 set = 0, sub_domain = 0, hdr_len = 3;
6757   mpls_label_t local_label = MPLS_LABEL_INVALID;
6758   int ret;
6759
6760   /* Parse args required to build the message */
6761   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6762     {
6763       if (unformat (i, "sub-domain %d", &sub_domain))
6764         ;
6765       else if (unformat (i, "set %d", &set))
6766         ;
6767       else if (unformat (i, "label %d", &local_label))
6768         ;
6769       else if (unformat (i, "hdr-len %d", &hdr_len))
6770         ;
6771       else if (unformat (i, "add"))
6772         is_add = 1;
6773       else if (unformat (i, "del"))
6774         is_add = 0;
6775       else
6776         {
6777           clib_warning ("parse error '%U'", format_unformat_error, i);
6778           return -99;
6779         }
6780     }
6781
6782   if (MPLS_LABEL_INVALID == local_label)
6783     {
6784       errmsg ("missing label\n");
6785       return -99;
6786     }
6787
6788   /* Construct the API message */
6789   M (BIER_TABLE_ADD_DEL, mp);
6790
6791   mp->bt_is_add = is_add;
6792   mp->bt_label = ntohl (local_label);
6793   mp->bt_tbl_id.bt_set = set;
6794   mp->bt_tbl_id.bt_sub_domain = sub_domain;
6795   mp->bt_tbl_id.bt_hdr_len_id = hdr_len;
6796
6797   /* send it... */
6798   S (mp);
6799
6800   /* Wait for a reply... */
6801   W (ret);
6802
6803   return (ret);
6804 }
6805
6806 static int
6807 api_bier_route_add_del (vat_main_t * vam)
6808 {
6809   unformat_input_t *i = vam->input;
6810   vl_api_bier_route_add_del_t *mp;
6811   u8 is_add = 1;
6812   u32 set = 0, sub_domain = 0, hdr_len = 3, bp = 0;
6813   ip4_address_t v4_next_hop_address;
6814   ip6_address_t v6_next_hop_address;
6815   u8 next_hop_set = 0;
6816   u8 next_hop_proto_is_ip4 = 1;
6817   mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID;
6818   int ret;
6819
6820   /* Parse args required to build the message */
6821   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6822     {
6823       if (unformat (i, "%U", unformat_ip4_address, &v4_next_hop_address))
6824         {
6825           next_hop_proto_is_ip4 = 1;
6826           next_hop_set = 1;
6827         }
6828       else if (unformat (i, "%U", unformat_ip6_address, &v6_next_hop_address))
6829         {
6830           next_hop_proto_is_ip4 = 0;
6831           next_hop_set = 1;
6832         }
6833       if (unformat (i, "sub-domain %d", &sub_domain))
6834         ;
6835       else if (unformat (i, "set %d", &set))
6836         ;
6837       else if (unformat (i, "hdr-len %d", &hdr_len))
6838         ;
6839       else if (unformat (i, "bp %d", &bp))
6840         ;
6841       else if (unformat (i, "add"))
6842         is_add = 1;
6843       else if (unformat (i, "del"))
6844         is_add = 0;
6845       else if (unformat (i, "out-label %d", &next_hop_out_label))
6846         ;
6847       else
6848         {
6849           clib_warning ("parse error '%U'", format_unformat_error, i);
6850           return -99;
6851         }
6852     }
6853
6854   if (!next_hop_set || (MPLS_LABEL_INVALID == next_hop_out_label))
6855     {
6856       errmsg ("next hop / label set\n");
6857       return -99;
6858     }
6859   if (0 == bp)
6860     {
6861       errmsg ("bit=position not set\n");
6862       return -99;
6863     }
6864
6865   /* Construct the API message */
6866   M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t));
6867
6868   mp->br_is_add = is_add;
6869   mp->br_route.br_tbl_id.bt_set = set;
6870   mp->br_route.br_tbl_id.bt_sub_domain = sub_domain;
6871   mp->br_route.br_tbl_id.bt_hdr_len_id = hdr_len;
6872   mp->br_route.br_bp = ntohs (bp);
6873   mp->br_route.br_n_paths = 1;
6874   mp->br_route.br_paths[0].n_labels = 1;
6875   mp->br_route.br_paths[0].label_stack[0].label = ntohl (next_hop_out_label);
6876   mp->br_route.br_paths[0].proto = (next_hop_proto_is_ip4 ?
6877                                     FIB_API_PATH_NH_PROTO_IP4 :
6878                                     FIB_API_PATH_NH_PROTO_IP6);
6879
6880   if (next_hop_proto_is_ip4)
6881     {
6882       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip4,
6883                    &v4_next_hop_address, sizeof (v4_next_hop_address));
6884     }
6885   else
6886     {
6887       clib_memcpy (&mp->br_route.br_paths[0].nh.address.ip6,
6888                    &v6_next_hop_address, sizeof (v6_next_hop_address));
6889     }
6890
6891   /* send it... */
6892   S (mp);
6893
6894   /* Wait for a reply... */
6895   W (ret);
6896
6897   return (ret);
6898 }
6899
6900 static int
6901 api_mpls_tunnel_add_del (vat_main_t * vam)
6902 {
6903   unformat_input_t *i = vam->input;
6904   vl_api_mpls_tunnel_add_del_t *mp;
6905
6906   vl_api_fib_path_t paths[8];
6907   u32 sw_if_index = ~0;
6908   u8 path_count = 0;
6909   u8 l2_only = 0;
6910   u8 is_add = 1;
6911   int ret;
6912
6913   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6914     {
6915       if (unformat (i, "add"))
6916         is_add = 1;
6917       else
6918         if (unformat
6919             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
6920         is_add = 0;
6921       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
6922         is_add = 0;
6923       else if (unformat (i, "l2-only"))
6924         l2_only = 1;
6925       else
6926         if (unformat
6927             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6928         {
6929           path_count++;
6930           if (8 == path_count)
6931             {
6932               errmsg ("max 8 paths");
6933               return -99;
6934             }
6935         }
6936       else
6937         {
6938           clib_warning ("parse error '%U'", format_unformat_error, i);
6939           return -99;
6940         }
6941     }
6942
6943   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6944
6945   mp->mt_is_add = is_add;
6946   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
6947   mp->mt_tunnel.mt_l2_only = l2_only;
6948   mp->mt_tunnel.mt_is_multicast = 0;
6949   mp->mt_tunnel.mt_n_paths = path_count;
6950
6951   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
6952                sizeof (paths[0]) * path_count);
6953
6954   S (mp);
6955   W (ret);
6956   return ret;
6957 }
6958
6959 static int
6960 api_sw_interface_set_unnumbered (vat_main_t * vam)
6961 {
6962   unformat_input_t *i = vam->input;
6963   vl_api_sw_interface_set_unnumbered_t *mp;
6964   u32 sw_if_index;
6965   u32 unnum_sw_index = ~0;
6966   u8 is_add = 1;
6967   u8 sw_if_index_set = 0;
6968   int ret;
6969
6970   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6971     {
6972       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6973         sw_if_index_set = 1;
6974       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6975         sw_if_index_set = 1;
6976       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
6977         ;
6978       else if (unformat (i, "del"))
6979         is_add = 0;
6980       else
6981         {
6982           clib_warning ("parse error '%U'", format_unformat_error, i);
6983           return -99;
6984         }
6985     }
6986
6987   if (sw_if_index_set == 0)
6988     {
6989       errmsg ("missing interface name or sw_if_index");
6990       return -99;
6991     }
6992
6993   M (SW_INTERFACE_SET_UNNUMBERED, mp);
6994
6995   mp->sw_if_index = ntohl (sw_if_index);
6996   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
6997   mp->is_add = is_add;
6998
6999   S (mp);
7000   W (ret);
7001   return ret;
7002 }
7003
7004
7005 static int
7006 api_create_vlan_subif (vat_main_t * vam)
7007 {
7008   unformat_input_t *i = vam->input;
7009   vl_api_create_vlan_subif_t *mp;
7010   u32 sw_if_index;
7011   u8 sw_if_index_set = 0;
7012   u32 vlan_id;
7013   u8 vlan_id_set = 0;
7014   int ret;
7015
7016   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7017     {
7018       if (unformat (i, "sw_if_index %d", &sw_if_index))
7019         sw_if_index_set = 1;
7020       else
7021         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7022         sw_if_index_set = 1;
7023       else if (unformat (i, "vlan %d", &vlan_id))
7024         vlan_id_set = 1;
7025       else
7026         {
7027           clib_warning ("parse error '%U'", format_unformat_error, i);
7028           return -99;
7029         }
7030     }
7031
7032   if (sw_if_index_set == 0)
7033     {
7034       errmsg ("missing interface name or sw_if_index");
7035       return -99;
7036     }
7037
7038   if (vlan_id_set == 0)
7039     {
7040       errmsg ("missing vlan_id");
7041       return -99;
7042     }
7043   M (CREATE_VLAN_SUBIF, mp);
7044
7045   mp->sw_if_index = ntohl (sw_if_index);
7046   mp->vlan_id = ntohl (vlan_id);
7047
7048   S (mp);
7049   W (ret);
7050   return ret;
7051 }
7052
7053 #define foreach_create_subif_bit                \
7054 _(no_tags)                                      \
7055 _(one_tag)                                      \
7056 _(two_tags)                                     \
7057 _(dot1ad)                                       \
7058 _(exact_match)                                  \
7059 _(default_sub)                                  \
7060 _(outer_vlan_id_any)                            \
7061 _(inner_vlan_id_any)
7062
7063 #define foreach_create_subif_flag               \
7064 _(0, "no_tags")                                 \
7065 _(1, "one_tag")                                 \
7066 _(2, "two_tags")                                \
7067 _(3, "dot1ad")                                  \
7068 _(4, "exact_match")                             \
7069 _(5, "default_sub")                             \
7070 _(6, "outer_vlan_id_any")                       \
7071 _(7, "inner_vlan_id_any")
7072
7073 static int
7074 api_create_subif (vat_main_t * vam)
7075 {
7076   unformat_input_t *i = vam->input;
7077   vl_api_create_subif_t *mp;
7078   u32 sw_if_index;
7079   u8 sw_if_index_set = 0;
7080   u32 sub_id;
7081   u8 sub_id_set = 0;
7082   u32 __attribute__ ((unused)) no_tags = 0;
7083   u32 __attribute__ ((unused)) one_tag = 0;
7084   u32 __attribute__ ((unused)) two_tags = 0;
7085   u32 __attribute__ ((unused)) dot1ad = 0;
7086   u32 __attribute__ ((unused)) exact_match = 0;
7087   u32 __attribute__ ((unused)) default_sub = 0;
7088   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
7089   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
7090   u32 tmp;
7091   u16 outer_vlan_id = 0;
7092   u16 inner_vlan_id = 0;
7093   int ret;
7094
7095   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7096     {
7097       if (unformat (i, "sw_if_index %d", &sw_if_index))
7098         sw_if_index_set = 1;
7099       else
7100         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7101         sw_if_index_set = 1;
7102       else if (unformat (i, "sub_id %d", &sub_id))
7103         sub_id_set = 1;
7104       else if (unformat (i, "outer_vlan_id %d", &tmp))
7105         outer_vlan_id = tmp;
7106       else if (unformat (i, "inner_vlan_id %d", &tmp))
7107         inner_vlan_id = tmp;
7108
7109 #define _(a) else if (unformat (i, #a)) a = 1 ;
7110       foreach_create_subif_bit
7111 #undef _
7112         else
7113         {
7114           clib_warning ("parse error '%U'", format_unformat_error, i);
7115           return -99;
7116         }
7117     }
7118
7119   if (sw_if_index_set == 0)
7120     {
7121       errmsg ("missing interface name or sw_if_index");
7122       return -99;
7123     }
7124
7125   if (sub_id_set == 0)
7126     {
7127       errmsg ("missing sub_id");
7128       return -99;
7129     }
7130   M (CREATE_SUBIF, mp);
7131
7132   mp->sw_if_index = ntohl (sw_if_index);
7133   mp->sub_id = ntohl (sub_id);
7134
7135 #define _(a,b) mp->sub_if_flags |= (1 << a);
7136   foreach_create_subif_flag;
7137 #undef _
7138
7139   mp->outer_vlan_id = ntohs (outer_vlan_id);
7140   mp->inner_vlan_id = ntohs (inner_vlan_id);
7141
7142   S (mp);
7143   W (ret);
7144   return ret;
7145 }
7146
7147 static int
7148 api_ip_table_replace_begin (vat_main_t * vam)
7149 {
7150   unformat_input_t *i = vam->input;
7151   vl_api_ip_table_replace_begin_t *mp;
7152   u32 table_id = 0;
7153   u8 is_ipv6 = 0;
7154
7155   int ret;
7156   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7157     {
7158       if (unformat (i, "table %d", &table_id))
7159         ;
7160       else if (unformat (i, "ipv6"))
7161         is_ipv6 = 1;
7162       else
7163         {
7164           clib_warning ("parse error '%U'", format_unformat_error, i);
7165           return -99;
7166         }
7167     }
7168
7169   M (IP_TABLE_REPLACE_BEGIN, mp);
7170
7171   mp->table.table_id = ntohl (table_id);
7172   mp->table.is_ip6 = is_ipv6;
7173
7174   S (mp);
7175   W (ret);
7176   return ret;
7177 }
7178
7179 static int
7180 api_ip_table_flush (vat_main_t * vam)
7181 {
7182   unformat_input_t *i = vam->input;
7183   vl_api_ip_table_flush_t *mp;
7184   u32 table_id = 0;
7185   u8 is_ipv6 = 0;
7186
7187   int ret;
7188   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7189     {
7190       if (unformat (i, "table %d", &table_id))
7191         ;
7192       else if (unformat (i, "ipv6"))
7193         is_ipv6 = 1;
7194       else
7195         {
7196           clib_warning ("parse error '%U'", format_unformat_error, i);
7197           return -99;
7198         }
7199     }
7200
7201   M (IP_TABLE_FLUSH, mp);
7202
7203   mp->table.table_id = ntohl (table_id);
7204   mp->table.is_ip6 = is_ipv6;
7205
7206   S (mp);
7207   W (ret);
7208   return ret;
7209 }
7210
7211 static int
7212 api_ip_table_replace_end (vat_main_t * vam)
7213 {
7214   unformat_input_t *i = vam->input;
7215   vl_api_ip_table_replace_end_t *mp;
7216   u32 table_id = 0;
7217   u8 is_ipv6 = 0;
7218
7219   int ret;
7220   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7221     {
7222       if (unformat (i, "table %d", &table_id))
7223         ;
7224       else if (unformat (i, "ipv6"))
7225         is_ipv6 = 1;
7226       else
7227         {
7228           clib_warning ("parse error '%U'", format_unformat_error, i);
7229           return -99;
7230         }
7231     }
7232
7233   M (IP_TABLE_REPLACE_END, mp);
7234
7235   mp->table.table_id = ntohl (table_id);
7236   mp->table.is_ip6 = is_ipv6;
7237
7238   S (mp);
7239   W (ret);
7240   return ret;
7241 }
7242
7243 static int
7244 api_set_ip_flow_hash (vat_main_t * vam)
7245 {
7246   unformat_input_t *i = vam->input;
7247   vl_api_set_ip_flow_hash_t *mp;
7248   u32 vrf_id = 0;
7249   u8 is_ipv6 = 0;
7250   u8 vrf_id_set = 0;
7251   u8 src = 0;
7252   u8 dst = 0;
7253   u8 sport = 0;
7254   u8 dport = 0;
7255   u8 proto = 0;
7256   u8 reverse = 0;
7257   int ret;
7258
7259   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7260     {
7261       if (unformat (i, "vrf %d", &vrf_id))
7262         vrf_id_set = 1;
7263       else if (unformat (i, "ipv6"))
7264         is_ipv6 = 1;
7265       else if (unformat (i, "src"))
7266         src = 1;
7267       else if (unformat (i, "dst"))
7268         dst = 1;
7269       else if (unformat (i, "sport"))
7270         sport = 1;
7271       else if (unformat (i, "dport"))
7272         dport = 1;
7273       else if (unformat (i, "proto"))
7274         proto = 1;
7275       else if (unformat (i, "reverse"))
7276         reverse = 1;
7277
7278       else
7279         {
7280           clib_warning ("parse error '%U'", format_unformat_error, i);
7281           return -99;
7282         }
7283     }
7284
7285   if (vrf_id_set == 0)
7286     {
7287       errmsg ("missing vrf id");
7288       return -99;
7289     }
7290
7291   M (SET_IP_FLOW_HASH, mp);
7292   mp->src = src;
7293   mp->dst = dst;
7294   mp->sport = sport;
7295   mp->dport = dport;
7296   mp->proto = proto;
7297   mp->reverse = reverse;
7298   mp->vrf_id = ntohl (vrf_id);
7299   mp->is_ipv6 = is_ipv6;
7300
7301   S (mp);
7302   W (ret);
7303   return ret;
7304 }
7305
7306 static int
7307 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
7308 {
7309   unformat_input_t *i = vam->input;
7310   vl_api_sw_interface_ip6_enable_disable_t *mp;
7311   u32 sw_if_index;
7312   u8 sw_if_index_set = 0;
7313   u8 enable = 0;
7314   int ret;
7315
7316   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7317     {
7318       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
7319         sw_if_index_set = 1;
7320       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7321         sw_if_index_set = 1;
7322       else if (unformat (i, "enable"))
7323         enable = 1;
7324       else if (unformat (i, "disable"))
7325         enable = 0;
7326       else
7327         {
7328           clib_warning ("parse error '%U'", format_unformat_error, i);
7329           return -99;
7330         }
7331     }
7332
7333   if (sw_if_index_set == 0)
7334     {
7335       errmsg ("missing interface name or sw_if_index");
7336       return -99;
7337     }
7338
7339   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
7340
7341   mp->sw_if_index = ntohl (sw_if_index);
7342   mp->enable = enable;
7343
7344   S (mp);
7345   W (ret);
7346   return ret;
7347 }
7348
7349
7350 static int
7351 api_l2_patch_add_del (vat_main_t * vam)
7352 {
7353   unformat_input_t *i = vam->input;
7354   vl_api_l2_patch_add_del_t *mp;
7355   u32 rx_sw_if_index;
7356   u8 rx_sw_if_index_set = 0;
7357   u32 tx_sw_if_index;
7358   u8 tx_sw_if_index_set = 0;
7359   u8 is_add = 1;
7360   int ret;
7361
7362   /* Parse args required to build the message */
7363   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7364     {
7365       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
7366         rx_sw_if_index_set = 1;
7367       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
7368         tx_sw_if_index_set = 1;
7369       else if (unformat (i, "rx"))
7370         {
7371           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7372             {
7373               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7374                             &rx_sw_if_index))
7375                 rx_sw_if_index_set = 1;
7376             }
7377           else
7378             break;
7379         }
7380       else if (unformat (i, "tx"))
7381         {
7382           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7383             {
7384               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
7385                             &tx_sw_if_index))
7386                 tx_sw_if_index_set = 1;
7387             }
7388           else
7389             break;
7390         }
7391       else if (unformat (i, "del"))
7392         is_add = 0;
7393       else
7394         break;
7395     }
7396
7397   if (rx_sw_if_index_set == 0)
7398     {
7399       errmsg ("missing rx interface name or rx_sw_if_index");
7400       return -99;
7401     }
7402
7403   if (tx_sw_if_index_set == 0)
7404     {
7405       errmsg ("missing tx interface name or tx_sw_if_index");
7406       return -99;
7407     }
7408
7409   M (L2_PATCH_ADD_DEL, mp);
7410
7411   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
7412   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
7413   mp->is_add = is_add;
7414
7415   S (mp);
7416   W (ret);
7417   return ret;
7418 }
7419
7420 u8 is_del;
7421 u8 localsid_addr[16];
7422 u8 end_psp;
7423 u8 behavior;
7424 u32 sw_if_index;
7425 u32 vlan_index;
7426 u32 fib_table;
7427 u8 nh_addr[16];
7428
7429 static int
7430 api_sr_localsid_add_del (vat_main_t * vam)
7431 {
7432   unformat_input_t *i = vam->input;
7433   vl_api_sr_localsid_add_del_t *mp;
7434
7435   u8 is_del;
7436   ip6_address_t localsid;
7437   u8 end_psp = 0;
7438   u8 behavior = ~0;
7439   u32 sw_if_index;
7440   u32 fib_table = ~(u32) 0;
7441   ip46_address_t nh_addr;
7442   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
7443
7444   bool nexthop_set = 0;
7445
7446   int ret;
7447
7448   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7449     {
7450       if (unformat (i, "del"))
7451         is_del = 1;
7452       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
7453       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
7454         nexthop_set = 1;
7455       else if (unformat (i, "behavior %u", &behavior));
7456       else if (unformat (i, "sw_if_index %u", &sw_if_index));
7457       else if (unformat (i, "fib-table %u", &fib_table));
7458       else if (unformat (i, "end.psp %u", &behavior));
7459       else
7460         break;
7461     }
7462
7463   M (SR_LOCALSID_ADD_DEL, mp);
7464
7465   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
7466
7467   if (nexthop_set)
7468     {
7469       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
7470     }
7471   mp->behavior = behavior;
7472   mp->sw_if_index = ntohl (sw_if_index);
7473   mp->fib_table = ntohl (fib_table);
7474   mp->end_psp = end_psp;
7475   mp->is_del = is_del;
7476
7477   S (mp);
7478   W (ret);
7479   return ret;
7480 }
7481
7482 static int
7483 api_ioam_enable (vat_main_t * vam)
7484 {
7485   unformat_input_t *input = vam->input;
7486   vl_api_ioam_enable_t *mp;
7487   u32 id = 0;
7488   int has_trace_option = 0;
7489   int has_pot_option = 0;
7490   int has_seqno_option = 0;
7491   int has_analyse_option = 0;
7492   int ret;
7493
7494   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7495     {
7496       if (unformat (input, "trace"))
7497         has_trace_option = 1;
7498       else if (unformat (input, "pot"))
7499         has_pot_option = 1;
7500       else if (unformat (input, "seqno"))
7501         has_seqno_option = 1;
7502       else if (unformat (input, "analyse"))
7503         has_analyse_option = 1;
7504       else
7505         break;
7506     }
7507   M (IOAM_ENABLE, mp);
7508   mp->id = htons (id);
7509   mp->seqno = has_seqno_option;
7510   mp->analyse = has_analyse_option;
7511   mp->pot_enable = has_pot_option;
7512   mp->trace_enable = has_trace_option;
7513
7514   S (mp);
7515   W (ret);
7516   return ret;
7517 }
7518
7519
7520 static int
7521 api_ioam_disable (vat_main_t * vam)
7522 {
7523   vl_api_ioam_disable_t *mp;
7524   int ret;
7525
7526   M (IOAM_DISABLE, mp);
7527   S (mp);
7528   W (ret);
7529   return ret;
7530 }
7531
7532 #define foreach_tcp_proto_field                 \
7533 _(src_port)                                     \
7534 _(dst_port)
7535
7536 #define foreach_udp_proto_field                 \
7537 _(src_port)                                     \
7538 _(dst_port)
7539
7540 #define foreach_ip4_proto_field                 \
7541 _(src_address)                                  \
7542 _(dst_address)                                  \
7543 _(tos)                                          \
7544 _(length)                                       \
7545 _(fragment_id)                                  \
7546 _(ttl)                                          \
7547 _(protocol)                                     \
7548 _(checksum)
7549
7550 typedef struct
7551 {
7552   u16 src_port, dst_port;
7553 } tcpudp_header_t;
7554
7555 #if VPP_API_TEST_BUILTIN == 0
7556 uword
7557 unformat_tcp_mask (unformat_input_t * input, va_list * args)
7558 {
7559   u8 **maskp = va_arg (*args, u8 **);
7560   u8 *mask = 0;
7561   u8 found_something = 0;
7562   tcp_header_t *tcp;
7563
7564 #define _(a) u8 a=0;
7565   foreach_tcp_proto_field;
7566 #undef _
7567
7568   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7569     {
7570       if (0);
7571 #define _(a) else if (unformat (input, #a)) a=1;
7572       foreach_tcp_proto_field
7573 #undef _
7574         else
7575         break;
7576     }
7577
7578 #define _(a) found_something += a;
7579   foreach_tcp_proto_field;
7580 #undef _
7581
7582   if (found_something == 0)
7583     return 0;
7584
7585   vec_validate (mask, sizeof (*tcp) - 1);
7586
7587   tcp = (tcp_header_t *) mask;
7588
7589 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
7590   foreach_tcp_proto_field;
7591 #undef _
7592
7593   *maskp = mask;
7594   return 1;
7595 }
7596
7597 uword
7598 unformat_udp_mask (unformat_input_t * input, va_list * args)
7599 {
7600   u8 **maskp = va_arg (*args, u8 **);
7601   u8 *mask = 0;
7602   u8 found_something = 0;
7603   udp_header_t *udp;
7604
7605 #define _(a) u8 a=0;
7606   foreach_udp_proto_field;
7607 #undef _
7608
7609   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7610     {
7611       if (0);
7612 #define _(a) else if (unformat (input, #a)) a=1;
7613       foreach_udp_proto_field
7614 #undef _
7615         else
7616         break;
7617     }
7618
7619 #define _(a) found_something += a;
7620   foreach_udp_proto_field;
7621 #undef _
7622
7623   if (found_something == 0)
7624     return 0;
7625
7626   vec_validate (mask, sizeof (*udp) - 1);
7627
7628   udp = (udp_header_t *) mask;
7629
7630 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
7631   foreach_udp_proto_field;
7632 #undef _
7633
7634   *maskp = mask;
7635   return 1;
7636 }
7637
7638 uword
7639 unformat_l4_mask (unformat_input_t * input, va_list * args)
7640 {
7641   u8 **maskp = va_arg (*args, u8 **);
7642   u16 src_port = 0, dst_port = 0;
7643   tcpudp_header_t *tcpudp;
7644
7645   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7646     {
7647       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
7648         return 1;
7649       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
7650         return 1;
7651       else if (unformat (input, "src_port"))
7652         src_port = 0xFFFF;
7653       else if (unformat (input, "dst_port"))
7654         dst_port = 0xFFFF;
7655       else
7656         return 0;
7657     }
7658
7659   if (!src_port && !dst_port)
7660     return 0;
7661
7662   u8 *mask = 0;
7663   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
7664
7665   tcpudp = (tcpudp_header_t *) mask;
7666   tcpudp->src_port = src_port;
7667   tcpudp->dst_port = dst_port;
7668
7669   *maskp = mask;
7670
7671   return 1;
7672 }
7673
7674 uword
7675 unformat_ip4_mask (unformat_input_t * input, va_list * args)
7676 {
7677   u8 **maskp = va_arg (*args, u8 **);
7678   u8 *mask = 0;
7679   u8 found_something = 0;
7680   ip4_header_t *ip;
7681
7682 #define _(a) u8 a=0;
7683   foreach_ip4_proto_field;
7684 #undef _
7685   u8 version = 0;
7686   u8 hdr_length = 0;
7687
7688
7689   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7690     {
7691       if (unformat (input, "version"))
7692         version = 1;
7693       else if (unformat (input, "hdr_length"))
7694         hdr_length = 1;
7695       else if (unformat (input, "src"))
7696         src_address = 1;
7697       else if (unformat (input, "dst"))
7698         dst_address = 1;
7699       else if (unformat (input, "proto"))
7700         protocol = 1;
7701
7702 #define _(a) else if (unformat (input, #a)) a=1;
7703       foreach_ip4_proto_field
7704 #undef _
7705         else
7706         break;
7707     }
7708
7709 #define _(a) found_something += a;
7710   foreach_ip4_proto_field;
7711 #undef _
7712
7713   if (found_something == 0)
7714     return 0;
7715
7716   vec_validate (mask, sizeof (*ip) - 1);
7717
7718   ip = (ip4_header_t *) mask;
7719
7720 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7721   foreach_ip4_proto_field;
7722 #undef _
7723
7724   ip->ip_version_and_header_length = 0;
7725
7726   if (version)
7727     ip->ip_version_and_header_length |= 0xF0;
7728
7729   if (hdr_length)
7730     ip->ip_version_and_header_length |= 0x0F;
7731
7732   *maskp = mask;
7733   return 1;
7734 }
7735
7736 #define foreach_ip6_proto_field                 \
7737 _(src_address)                                  \
7738 _(dst_address)                                  \
7739 _(payload_length)                               \
7740 _(hop_limit)                                    \
7741 _(protocol)
7742
7743 uword
7744 unformat_ip6_mask (unformat_input_t * input, va_list * args)
7745 {
7746   u8 **maskp = va_arg (*args, u8 **);
7747   u8 *mask = 0;
7748   u8 found_something = 0;
7749   ip6_header_t *ip;
7750   u32 ip_version_traffic_class_and_flow_label;
7751
7752 #define _(a) u8 a=0;
7753   foreach_ip6_proto_field;
7754 #undef _
7755   u8 version = 0;
7756   u8 traffic_class = 0;
7757   u8 flow_label = 0;
7758
7759   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7760     {
7761       if (unformat (input, "version"))
7762         version = 1;
7763       else if (unformat (input, "traffic-class"))
7764         traffic_class = 1;
7765       else if (unformat (input, "flow-label"))
7766         flow_label = 1;
7767       else if (unformat (input, "src"))
7768         src_address = 1;
7769       else if (unformat (input, "dst"))
7770         dst_address = 1;
7771       else if (unformat (input, "proto"))
7772         protocol = 1;
7773
7774 #define _(a) else if (unformat (input, #a)) a=1;
7775       foreach_ip6_proto_field
7776 #undef _
7777         else
7778         break;
7779     }
7780
7781 #define _(a) found_something += a;
7782   foreach_ip6_proto_field;
7783 #undef _
7784
7785   if (found_something == 0)
7786     return 0;
7787
7788   vec_validate (mask, sizeof (*ip) - 1);
7789
7790   ip = (ip6_header_t *) mask;
7791
7792 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7793   foreach_ip6_proto_field;
7794 #undef _
7795
7796   ip_version_traffic_class_and_flow_label = 0;
7797
7798   if (version)
7799     ip_version_traffic_class_and_flow_label |= 0xF0000000;
7800
7801   if (traffic_class)
7802     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
7803
7804   if (flow_label)
7805     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
7806
7807   ip->ip_version_traffic_class_and_flow_label =
7808     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7809
7810   *maskp = mask;
7811   return 1;
7812 }
7813
7814 uword
7815 unformat_l3_mask (unformat_input_t * input, va_list * args)
7816 {
7817   u8 **maskp = va_arg (*args, u8 **);
7818
7819   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7820     {
7821       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
7822         return 1;
7823       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
7824         return 1;
7825       else
7826         break;
7827     }
7828   return 0;
7829 }
7830
7831 uword
7832 unformat_l2_mask (unformat_input_t * input, va_list * args)
7833 {
7834   u8 **maskp = va_arg (*args, u8 **);
7835   u8 *mask = 0;
7836   u8 src = 0;
7837   u8 dst = 0;
7838   u8 proto = 0;
7839   u8 tag1 = 0;
7840   u8 tag2 = 0;
7841   u8 ignore_tag1 = 0;
7842   u8 ignore_tag2 = 0;
7843   u8 cos1 = 0;
7844   u8 cos2 = 0;
7845   u8 dot1q = 0;
7846   u8 dot1ad = 0;
7847   int len = 14;
7848
7849   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7850     {
7851       if (unformat (input, "src"))
7852         src = 1;
7853       else if (unformat (input, "dst"))
7854         dst = 1;
7855       else if (unformat (input, "proto"))
7856         proto = 1;
7857       else if (unformat (input, "tag1"))
7858         tag1 = 1;
7859       else if (unformat (input, "tag2"))
7860         tag2 = 1;
7861       else if (unformat (input, "ignore-tag1"))
7862         ignore_tag1 = 1;
7863       else if (unformat (input, "ignore-tag2"))
7864         ignore_tag2 = 1;
7865       else if (unformat (input, "cos1"))
7866         cos1 = 1;
7867       else if (unformat (input, "cos2"))
7868         cos2 = 1;
7869       else if (unformat (input, "dot1q"))
7870         dot1q = 1;
7871       else if (unformat (input, "dot1ad"))
7872         dot1ad = 1;
7873       else
7874         break;
7875     }
7876   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7877        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7878     return 0;
7879
7880   if (tag1 || ignore_tag1 || cos1 || dot1q)
7881     len = 18;
7882   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7883     len = 22;
7884
7885   vec_validate (mask, len - 1);
7886
7887   if (dst)
7888     clib_memset (mask, 0xff, 6);
7889
7890   if (src)
7891     clib_memset (mask + 6, 0xff, 6);
7892
7893   if (tag2 || dot1ad)
7894     {
7895       /* inner vlan tag */
7896       if (tag2)
7897         {
7898           mask[19] = 0xff;
7899           mask[18] = 0x0f;
7900         }
7901       if (cos2)
7902         mask[18] |= 0xe0;
7903       if (proto)
7904         mask[21] = mask[20] = 0xff;
7905       if (tag1)
7906         {
7907           mask[15] = 0xff;
7908           mask[14] = 0x0f;
7909         }
7910       if (cos1)
7911         mask[14] |= 0xe0;
7912       *maskp = mask;
7913       return 1;
7914     }
7915   if (tag1 | dot1q)
7916     {
7917       if (tag1)
7918         {
7919           mask[15] = 0xff;
7920           mask[14] = 0x0f;
7921         }
7922       if (cos1)
7923         mask[14] |= 0xe0;
7924       if (proto)
7925         mask[16] = mask[17] = 0xff;
7926
7927       *maskp = mask;
7928       return 1;
7929     }
7930   if (cos2)
7931     mask[18] |= 0xe0;
7932   if (cos1)
7933     mask[14] |= 0xe0;
7934   if (proto)
7935     mask[12] = mask[13] = 0xff;
7936
7937   *maskp = mask;
7938   return 1;
7939 }
7940
7941 uword
7942 unformat_classify_mask (unformat_input_t * input, va_list * args)
7943 {
7944   u8 **maskp = va_arg (*args, u8 **);
7945   u32 *skipp = va_arg (*args, u32 *);
7946   u32 *matchp = va_arg (*args, u32 *);
7947   u32 match;
7948   u8 *mask = 0;
7949   u8 *l2 = 0;
7950   u8 *l3 = 0;
7951   u8 *l4 = 0;
7952   int i;
7953
7954   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7955     {
7956       if (unformat (input, "hex %U", unformat_hex_string, &mask))
7957         ;
7958       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7959         ;
7960       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7961         ;
7962       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
7963         ;
7964       else
7965         break;
7966     }
7967
7968   if (l4 && !l3)
7969     {
7970       vec_free (mask);
7971       vec_free (l2);
7972       vec_free (l4);
7973       return 0;
7974     }
7975
7976   if (mask || l2 || l3 || l4)
7977     {
7978       if (l2 || l3 || l4)
7979         {
7980           /* "With a free Ethernet header in every package" */
7981           if (l2 == 0)
7982             vec_validate (l2, 13);
7983           mask = l2;
7984           if (vec_len (l3))
7985             {
7986               vec_append (mask, l3);
7987               vec_free (l3);
7988             }
7989           if (vec_len (l4))
7990             {
7991               vec_append (mask, l4);
7992               vec_free (l4);
7993             }
7994         }
7995
7996       /* Scan forward looking for the first significant mask octet */
7997       for (i = 0; i < vec_len (mask); i++)
7998         if (mask[i])
7999           break;
8000
8001       /* compute (skip, match) params */
8002       *skipp = i / sizeof (u32x4);
8003       vec_delete (mask, *skipp * sizeof (u32x4), 0);
8004
8005       /* Pad mask to an even multiple of the vector size */
8006       while (vec_len (mask) % sizeof (u32x4))
8007         vec_add1 (mask, 0);
8008
8009       match = vec_len (mask) / sizeof (u32x4);
8010
8011       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
8012         {
8013           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
8014           if (*tmp || *(tmp + 1))
8015             break;
8016           match--;
8017         }
8018       if (match == 0)
8019         clib_warning ("BUG: match 0");
8020
8021       _vec_len (mask) = match * sizeof (u32x4);
8022
8023       *matchp = match;
8024       *maskp = mask;
8025
8026       return 1;
8027     }
8028
8029   return 0;
8030 }
8031 #endif /* VPP_API_TEST_BUILTIN */
8032
8033 #define foreach_l2_next                         \
8034 _(drop, DROP)                                   \
8035 _(ethernet, ETHERNET_INPUT)                     \
8036 _(ip4, IP4_INPUT)                               \
8037 _(ip6, IP6_INPUT)
8038
8039 uword
8040 unformat_l2_next_index (unformat_input_t * input, va_list * args)
8041 {
8042   u32 *miss_next_indexp = va_arg (*args, u32 *);
8043   u32 next_index = 0;
8044   u32 tmp;
8045
8046 #define _(n,N) \
8047   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
8048   foreach_l2_next;
8049 #undef _
8050
8051   if (unformat (input, "%d", &tmp))
8052     {
8053       next_index = tmp;
8054       goto out;
8055     }
8056
8057   return 0;
8058
8059 out:
8060   *miss_next_indexp = next_index;
8061   return 1;
8062 }
8063
8064 #define foreach_ip_next                         \
8065 _(drop, DROP)                                   \
8066 _(local, LOCAL)                                 \
8067 _(rewrite, REWRITE)
8068
8069 uword
8070 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
8071 {
8072   u32 *miss_next_indexp = va_arg (*args, u32 *);
8073   u32 next_index = 0;
8074   u32 tmp;
8075
8076 #define _(n,N) \
8077   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
8078   foreach_ip_next;
8079 #undef _
8080
8081   if (unformat (input, "%d", &tmp))
8082     {
8083       next_index = tmp;
8084       goto out;
8085     }
8086
8087   return 0;
8088
8089 out:
8090   *miss_next_indexp = next_index;
8091   return 1;
8092 }
8093
8094 #define foreach_acl_next                        \
8095 _(deny, DENY)
8096
8097 uword
8098 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
8099 {
8100   u32 *miss_next_indexp = va_arg (*args, u32 *);
8101   u32 next_index = 0;
8102   u32 tmp;
8103
8104 #define _(n,N) \
8105   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
8106   foreach_acl_next;
8107 #undef _
8108
8109   if (unformat (input, "permit"))
8110     {
8111       next_index = ~0;
8112       goto out;
8113     }
8114   else if (unformat (input, "%d", &tmp))
8115     {
8116       next_index = tmp;
8117       goto out;
8118     }
8119
8120   return 0;
8121
8122 out:
8123   *miss_next_indexp = next_index;
8124   return 1;
8125 }
8126
8127 uword
8128 unformat_policer_precolor (unformat_input_t * input, va_list * args)
8129 {
8130   u32 *r = va_arg (*args, u32 *);
8131
8132   if (unformat (input, "conform-color"))
8133     *r = POLICE_CONFORM;
8134   else if (unformat (input, "exceed-color"))
8135     *r = POLICE_EXCEED;
8136   else
8137     return 0;
8138
8139   return 1;
8140 }
8141
8142 static int
8143 api_classify_add_del_table (vat_main_t * vam)
8144 {
8145   unformat_input_t *i = vam->input;
8146   vl_api_classify_add_del_table_t *mp;
8147
8148   u32 nbuckets = 2;
8149   u32 skip = ~0;
8150   u32 match = ~0;
8151   int is_add = 1;
8152   int del_chain = 0;
8153   u32 table_index = ~0;
8154   u32 next_table_index = ~0;
8155   u32 miss_next_index = ~0;
8156   u32 memory_size = 32 << 20;
8157   u8 *mask = 0;
8158   u32 current_data_flag = 0;
8159   int current_data_offset = 0;
8160   int ret;
8161
8162   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8163     {
8164       if (unformat (i, "del"))
8165         is_add = 0;
8166       else if (unformat (i, "del-chain"))
8167         {
8168           is_add = 0;
8169           del_chain = 1;
8170         }
8171       else if (unformat (i, "buckets %d", &nbuckets))
8172         ;
8173       else if (unformat (i, "memory_size %d", &memory_size))
8174         ;
8175       else if (unformat (i, "skip %d", &skip))
8176         ;
8177       else if (unformat (i, "match %d", &match))
8178         ;
8179       else if (unformat (i, "table %d", &table_index))
8180         ;
8181       else if (unformat (i, "mask %U", unformat_classify_mask,
8182                          &mask, &skip, &match))
8183         ;
8184       else if (unformat (i, "next-table %d", &next_table_index))
8185         ;
8186       else if (unformat (i, "miss-next %U", api_unformat_ip_next_index,
8187                          &miss_next_index))
8188         ;
8189       else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
8190                          &miss_next_index))
8191         ;
8192       else if (unformat (i, "acl-miss-next %U", api_unformat_acl_next_index,
8193                          &miss_next_index))
8194         ;
8195       else if (unformat (i, "current-data-flag %d", &current_data_flag))
8196         ;
8197       else if (unformat (i, "current-data-offset %d", &current_data_offset))
8198         ;
8199       else
8200         break;
8201     }
8202
8203   if (is_add && mask == 0)
8204     {
8205       errmsg ("Mask required");
8206       return -99;
8207     }
8208
8209   if (is_add && skip == ~0)
8210     {
8211       errmsg ("skip count required");
8212       return -99;
8213     }
8214
8215   if (is_add && match == ~0)
8216     {
8217       errmsg ("match count required");
8218       return -99;
8219     }
8220
8221   if (!is_add && table_index == ~0)
8222     {
8223       errmsg ("table index required for delete");
8224       return -99;
8225     }
8226
8227   M2 (CLASSIFY_ADD_DEL_TABLE, mp, vec_len (mask));
8228
8229   mp->is_add = is_add;
8230   mp->del_chain = del_chain;
8231   mp->table_index = ntohl (table_index);
8232   mp->nbuckets = ntohl (nbuckets);
8233   mp->memory_size = ntohl (memory_size);
8234   mp->skip_n_vectors = ntohl (skip);
8235   mp->match_n_vectors = ntohl (match);
8236   mp->next_table_index = ntohl (next_table_index);
8237   mp->miss_next_index = ntohl (miss_next_index);
8238   mp->current_data_flag = ntohl (current_data_flag);
8239   mp->current_data_offset = ntohl (current_data_offset);
8240   mp->mask_len = ntohl (vec_len (mask));
8241   clib_memcpy (mp->mask, mask, vec_len (mask));
8242
8243   vec_free (mask);
8244
8245   S (mp);
8246   W (ret);
8247   return ret;
8248 }
8249
8250 #if VPP_API_TEST_BUILTIN == 0
8251 uword
8252 unformat_l4_match (unformat_input_t * input, va_list * args)
8253 {
8254   u8 **matchp = va_arg (*args, u8 **);
8255
8256   u8 *proto_header = 0;
8257   int src_port = 0;
8258   int dst_port = 0;
8259
8260   tcpudp_header_t h;
8261
8262   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8263     {
8264       if (unformat (input, "src_port %d", &src_port))
8265         ;
8266       else if (unformat (input, "dst_port %d", &dst_port))
8267         ;
8268       else
8269         return 0;
8270     }
8271
8272   h.src_port = clib_host_to_net_u16 (src_port);
8273   h.dst_port = clib_host_to_net_u16 (dst_port);
8274   vec_validate (proto_header, sizeof (h) - 1);
8275   memcpy (proto_header, &h, sizeof (h));
8276
8277   *matchp = proto_header;
8278
8279   return 1;
8280 }
8281
8282 uword
8283 unformat_ip4_match (unformat_input_t * input, va_list * args)
8284 {
8285   u8 **matchp = va_arg (*args, u8 **);
8286   u8 *match = 0;
8287   ip4_header_t *ip;
8288   int version = 0;
8289   u32 version_val;
8290   int hdr_length = 0;
8291   u32 hdr_length_val;
8292   int src = 0, dst = 0;
8293   ip4_address_t src_val, dst_val;
8294   int proto = 0;
8295   u32 proto_val;
8296   int tos = 0;
8297   u32 tos_val;
8298   int length = 0;
8299   u32 length_val;
8300   int fragment_id = 0;
8301   u32 fragment_id_val;
8302   int ttl = 0;
8303   int ttl_val;
8304   int checksum = 0;
8305   u32 checksum_val;
8306
8307   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8308     {
8309       if (unformat (input, "version %d", &version_val))
8310         version = 1;
8311       else if (unformat (input, "hdr_length %d", &hdr_length_val))
8312         hdr_length = 1;
8313       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
8314         src = 1;
8315       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
8316         dst = 1;
8317       else if (unformat (input, "proto %d", &proto_val))
8318         proto = 1;
8319       else if (unformat (input, "tos %d", &tos_val))
8320         tos = 1;
8321       else if (unformat (input, "length %d", &length_val))
8322         length = 1;
8323       else if (unformat (input, "fragment_id %d", &fragment_id_val))
8324         fragment_id = 1;
8325       else if (unformat (input, "ttl %d", &ttl_val))
8326         ttl = 1;
8327       else if (unformat (input, "checksum %d", &checksum_val))
8328         checksum = 1;
8329       else
8330         break;
8331     }
8332
8333   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
8334       + ttl + checksum == 0)
8335     return 0;
8336
8337   /*
8338    * Aligned because we use the real comparison functions
8339    */
8340   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8341
8342   ip = (ip4_header_t *) match;
8343
8344   /* These are realistically matched in practice */
8345   if (src)
8346     ip->src_address.as_u32 = src_val.as_u32;
8347
8348   if (dst)
8349     ip->dst_address.as_u32 = dst_val.as_u32;
8350
8351   if (proto)
8352     ip->protocol = proto_val;
8353
8354
8355   /* These are not, but they're included for completeness */
8356   if (version)
8357     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
8358
8359   if (hdr_length)
8360     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
8361
8362   if (tos)
8363     ip->tos = tos_val;
8364
8365   if (length)
8366     ip->length = clib_host_to_net_u16 (length_val);
8367
8368   if (ttl)
8369     ip->ttl = ttl_val;
8370
8371   if (checksum)
8372     ip->checksum = clib_host_to_net_u16 (checksum_val);
8373
8374   *matchp = match;
8375   return 1;
8376 }
8377
8378 uword
8379 unformat_ip6_match (unformat_input_t * input, va_list * args)
8380 {
8381   u8 **matchp = va_arg (*args, u8 **);
8382   u8 *match = 0;
8383   ip6_header_t *ip;
8384   int version = 0;
8385   u32 version_val;
8386   u8 traffic_class = 0;
8387   u32 traffic_class_val = 0;
8388   u8 flow_label = 0;
8389   u8 flow_label_val;
8390   int src = 0, dst = 0;
8391   ip6_address_t src_val, dst_val;
8392   int proto = 0;
8393   u32 proto_val;
8394   int payload_length = 0;
8395   u32 payload_length_val;
8396   int hop_limit = 0;
8397   int hop_limit_val;
8398   u32 ip_version_traffic_class_and_flow_label;
8399
8400   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8401     {
8402       if (unformat (input, "version %d", &version_val))
8403         version = 1;
8404       else if (unformat (input, "traffic_class %d", &traffic_class_val))
8405         traffic_class = 1;
8406       else if (unformat (input, "flow_label %d", &flow_label_val))
8407         flow_label = 1;
8408       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
8409         src = 1;
8410       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
8411         dst = 1;
8412       else if (unformat (input, "proto %d", &proto_val))
8413         proto = 1;
8414       else if (unformat (input, "payload_length %d", &payload_length_val))
8415         payload_length = 1;
8416       else if (unformat (input, "hop_limit %d", &hop_limit_val))
8417         hop_limit = 1;
8418       else
8419         break;
8420     }
8421
8422   if (version + traffic_class + flow_label + src + dst + proto +
8423       payload_length + hop_limit == 0)
8424     return 0;
8425
8426   /*
8427    * Aligned because we use the real comparison functions
8428    */
8429   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
8430
8431   ip = (ip6_header_t *) match;
8432
8433   if (src)
8434     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
8435
8436   if (dst)
8437     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
8438
8439   if (proto)
8440     ip->protocol = proto_val;
8441
8442   ip_version_traffic_class_and_flow_label = 0;
8443
8444   if (version)
8445     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
8446
8447   if (traffic_class)
8448     ip_version_traffic_class_and_flow_label |=
8449       (traffic_class_val & 0xFF) << 20;
8450
8451   if (flow_label)
8452     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
8453
8454   ip->ip_version_traffic_class_and_flow_label =
8455     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
8456
8457   if (payload_length)
8458     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
8459
8460   if (hop_limit)
8461     ip->hop_limit = hop_limit_val;
8462
8463   *matchp = match;
8464   return 1;
8465 }
8466
8467 uword
8468 unformat_l3_match (unformat_input_t * input, va_list * args)
8469 {
8470   u8 **matchp = va_arg (*args, u8 **);
8471
8472   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8473     {
8474       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
8475         return 1;
8476       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
8477         return 1;
8478       else
8479         break;
8480     }
8481   return 0;
8482 }
8483
8484 uword
8485 unformat_vlan_tag (unformat_input_t * input, va_list * args)
8486 {
8487   u8 *tagp = va_arg (*args, u8 *);
8488   u32 tag;
8489
8490   if (unformat (input, "%d", &tag))
8491     {
8492       tagp[0] = (tag >> 8) & 0x0F;
8493       tagp[1] = tag & 0xFF;
8494       return 1;
8495     }
8496
8497   return 0;
8498 }
8499
8500 uword
8501 unformat_l2_match (unformat_input_t * input, va_list * args)
8502 {
8503   u8 **matchp = va_arg (*args, u8 **);
8504   u8 *match = 0;
8505   u8 src = 0;
8506   u8 src_val[6];
8507   u8 dst = 0;
8508   u8 dst_val[6];
8509   u8 proto = 0;
8510   u16 proto_val;
8511   u8 tag1 = 0;
8512   u8 tag1_val[2];
8513   u8 tag2 = 0;
8514   u8 tag2_val[2];
8515   int len = 14;
8516   u8 ignore_tag1 = 0;
8517   u8 ignore_tag2 = 0;
8518   u8 cos1 = 0;
8519   u8 cos2 = 0;
8520   u32 cos1_val = 0;
8521   u32 cos2_val = 0;
8522
8523   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8524     {
8525       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
8526         src = 1;
8527       else
8528         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
8529         dst = 1;
8530       else if (unformat (input, "proto %U",
8531                          unformat_ethernet_type_host_byte_order, &proto_val))
8532         proto = 1;
8533       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
8534         tag1 = 1;
8535       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
8536         tag2 = 1;
8537       else if (unformat (input, "ignore-tag1"))
8538         ignore_tag1 = 1;
8539       else if (unformat (input, "ignore-tag2"))
8540         ignore_tag2 = 1;
8541       else if (unformat (input, "cos1 %d", &cos1_val))
8542         cos1 = 1;
8543       else if (unformat (input, "cos2 %d", &cos2_val))
8544         cos2 = 1;
8545       else
8546         break;
8547     }
8548   if ((src + dst + proto + tag1 + tag2 +
8549        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
8550     return 0;
8551
8552   if (tag1 || ignore_tag1 || cos1)
8553     len = 18;
8554   if (tag2 || ignore_tag2 || cos2)
8555     len = 22;
8556
8557   vec_validate_aligned (match, len - 1, sizeof (u32x4));
8558
8559   if (dst)
8560     clib_memcpy (match, dst_val, 6);
8561
8562   if (src)
8563     clib_memcpy (match + 6, src_val, 6);
8564
8565   if (tag2)
8566     {
8567       /* inner vlan tag */
8568       match[19] = tag2_val[1];
8569       match[18] = tag2_val[0];
8570       if (cos2)
8571         match[18] |= (cos2_val & 0x7) << 5;
8572       if (proto)
8573         {
8574           match[21] = proto_val & 0xff;
8575           match[20] = proto_val >> 8;
8576         }
8577       if (tag1)
8578         {
8579           match[15] = tag1_val[1];
8580           match[14] = tag1_val[0];
8581         }
8582       if (cos1)
8583         match[14] |= (cos1_val & 0x7) << 5;
8584       *matchp = match;
8585       return 1;
8586     }
8587   if (tag1)
8588     {
8589       match[15] = tag1_val[1];
8590       match[14] = tag1_val[0];
8591       if (proto)
8592         {
8593           match[17] = proto_val & 0xff;
8594           match[16] = proto_val >> 8;
8595         }
8596       if (cos1)
8597         match[14] |= (cos1_val & 0x7) << 5;
8598
8599       *matchp = match;
8600       return 1;
8601     }
8602   if (cos2)
8603     match[18] |= (cos2_val & 0x7) << 5;
8604   if (cos1)
8605     match[14] |= (cos1_val & 0x7) << 5;
8606   if (proto)
8607     {
8608       match[13] = proto_val & 0xff;
8609       match[12] = proto_val >> 8;
8610     }
8611
8612   *matchp = match;
8613   return 1;
8614 }
8615
8616 uword
8617 unformat_qos_source (unformat_input_t * input, va_list * args)
8618 {
8619   int *qs = va_arg (*args, int *);
8620
8621   if (unformat (input, "ip"))
8622     *qs = QOS_SOURCE_IP;
8623   else if (unformat (input, "mpls"))
8624     *qs = QOS_SOURCE_MPLS;
8625   else if (unformat (input, "ext"))
8626     *qs = QOS_SOURCE_EXT;
8627   else if (unformat (input, "vlan"))
8628     *qs = QOS_SOURCE_VLAN;
8629   else
8630     return 0;
8631
8632   return 1;
8633 }
8634 #endif
8635
8636 uword
8637 api_unformat_classify_match (unformat_input_t * input, va_list * args)
8638 {
8639   u8 **matchp = va_arg (*args, u8 **);
8640   u32 skip_n_vectors = va_arg (*args, u32);
8641   u32 match_n_vectors = va_arg (*args, u32);
8642
8643   u8 *match = 0;
8644   u8 *l2 = 0;
8645   u8 *l3 = 0;
8646   u8 *l4 = 0;
8647
8648   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
8649     {
8650       if (unformat (input, "hex %U", unformat_hex_string, &match))
8651         ;
8652       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
8653         ;
8654       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
8655         ;
8656       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
8657         ;
8658       else
8659         break;
8660     }
8661
8662   if (l4 && !l3)
8663     {
8664       vec_free (match);
8665       vec_free (l2);
8666       vec_free (l4);
8667       return 0;
8668     }
8669
8670   if (match || l2 || l3 || l4)
8671     {
8672       if (l2 || l3 || l4)
8673         {
8674           /* "Win a free Ethernet header in every packet" */
8675           if (l2 == 0)
8676             vec_validate_aligned (l2, 13, sizeof (u32x4));
8677           match = l2;
8678           if (vec_len (l3))
8679             {
8680               vec_append_aligned (match, l3, sizeof (u32x4));
8681               vec_free (l3);
8682             }
8683           if (vec_len (l4))
8684             {
8685               vec_append_aligned (match, l4, sizeof (u32x4));
8686               vec_free (l4);
8687             }
8688         }
8689
8690       /* Make sure the vector is big enough even if key is all 0's */
8691       vec_validate_aligned
8692         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
8693          sizeof (u32x4));
8694
8695       /* Set size, include skipped vectors */
8696       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
8697
8698       *matchp = match;
8699
8700       return 1;
8701     }
8702
8703   return 0;
8704 }
8705
8706 static int
8707 api_classify_add_del_session (vat_main_t * vam)
8708 {
8709   unformat_input_t *i = vam->input;
8710   vl_api_classify_add_del_session_t *mp;
8711   int is_add = 1;
8712   u32 table_index = ~0;
8713   u32 hit_next_index = ~0;
8714   u32 opaque_index = ~0;
8715   u8 *match = 0;
8716   i32 advance = 0;
8717   u32 skip_n_vectors = 0;
8718   u32 match_n_vectors = 0;
8719   u32 action = 0;
8720   u32 metadata = 0;
8721   int ret;
8722
8723   /*
8724    * Warning: you have to supply skip_n and match_n
8725    * because the API client cant simply look at the classify
8726    * table object.
8727    */
8728
8729   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8730     {
8731       if (unformat (i, "del"))
8732         is_add = 0;
8733       else if (unformat (i, "hit-next %U", api_unformat_ip_next_index,
8734                          &hit_next_index))
8735         ;
8736       else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
8737                          &hit_next_index))
8738         ;
8739       else if (unformat (i, "acl-hit-next %U", api_unformat_acl_next_index,
8740                          &hit_next_index))
8741         ;
8742       else if (unformat (i, "policer-hit-next %d", &hit_next_index))
8743         ;
8744       else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index))
8745         ;
8746       else if (unformat (i, "opaque-index %d", &opaque_index))
8747         ;
8748       else if (unformat (i, "skip_n %d", &skip_n_vectors))
8749         ;
8750       else if (unformat (i, "match_n %d", &match_n_vectors))
8751         ;
8752       else if (unformat (i, "match %U", api_unformat_classify_match,
8753                          &match, skip_n_vectors, match_n_vectors))
8754         ;
8755       else if (unformat (i, "advance %d", &advance))
8756         ;
8757       else if (unformat (i, "table-index %d", &table_index))
8758         ;
8759       else if (unformat (i, "action set-ip4-fib-id %d", &metadata))
8760         action = 1;
8761       else if (unformat (i, "action set-ip6-fib-id %d", &metadata))
8762         action = 2;
8763       else if (unformat (i, "action %d", &action))
8764         ;
8765       else if (unformat (i, "metadata %d", &metadata))
8766         ;
8767       else
8768         break;
8769     }
8770
8771   if (table_index == ~0)
8772     {
8773       errmsg ("Table index required");
8774       return -99;
8775     }
8776
8777   if (is_add && match == 0)
8778     {
8779       errmsg ("Match value required");
8780       return -99;
8781     }
8782
8783   M2 (CLASSIFY_ADD_DEL_SESSION, mp, vec_len (match));
8784
8785   mp->is_add = is_add;
8786   mp->table_index = ntohl (table_index);
8787   mp->hit_next_index = ntohl (hit_next_index);
8788   mp->opaque_index = ntohl (opaque_index);
8789   mp->advance = ntohl (advance);
8790   mp->action = action;
8791   mp->metadata = ntohl (metadata);
8792   mp->match_len = ntohl (vec_len (match));
8793   clib_memcpy (mp->match, match, vec_len (match));
8794   vec_free (match);
8795
8796   S (mp);
8797   W (ret);
8798   return ret;
8799 }
8800
8801 static int
8802 api_classify_set_interface_ip_table (vat_main_t * vam)
8803 {
8804   unformat_input_t *i = vam->input;
8805   vl_api_classify_set_interface_ip_table_t *mp;
8806   u32 sw_if_index;
8807   int sw_if_index_set;
8808   u32 table_index = ~0;
8809   u8 is_ipv6 = 0;
8810   int ret;
8811
8812   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8813     {
8814       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8815         sw_if_index_set = 1;
8816       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8817         sw_if_index_set = 1;
8818       else if (unformat (i, "table %d", &table_index))
8819         ;
8820       else
8821         {
8822           clib_warning ("parse error '%U'", format_unformat_error, i);
8823           return -99;
8824         }
8825     }
8826
8827   if (sw_if_index_set == 0)
8828     {
8829       errmsg ("missing interface name or sw_if_index");
8830       return -99;
8831     }
8832
8833
8834   M (CLASSIFY_SET_INTERFACE_IP_TABLE, mp);
8835
8836   mp->sw_if_index = ntohl (sw_if_index);
8837   mp->table_index = ntohl (table_index);
8838   mp->is_ipv6 = is_ipv6;
8839
8840   S (mp);
8841   W (ret);
8842   return ret;
8843 }
8844
8845 static int
8846 api_classify_set_interface_l2_tables (vat_main_t * vam)
8847 {
8848   unformat_input_t *i = vam->input;
8849   vl_api_classify_set_interface_l2_tables_t *mp;
8850   u32 sw_if_index;
8851   int sw_if_index_set;
8852   u32 ip4_table_index = ~0;
8853   u32 ip6_table_index = ~0;
8854   u32 other_table_index = ~0;
8855   u32 is_input = 1;
8856   int ret;
8857
8858   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8859     {
8860       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8861         sw_if_index_set = 1;
8862       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8863         sw_if_index_set = 1;
8864       else if (unformat (i, "ip4-table %d", &ip4_table_index))
8865         ;
8866       else if (unformat (i, "ip6-table %d", &ip6_table_index))
8867         ;
8868       else if (unformat (i, "other-table %d", &other_table_index))
8869         ;
8870       else if (unformat (i, "is-input %d", &is_input))
8871         ;
8872       else
8873         {
8874           clib_warning ("parse error '%U'", format_unformat_error, i);
8875           return -99;
8876         }
8877     }
8878
8879   if (sw_if_index_set == 0)
8880     {
8881       errmsg ("missing interface name or sw_if_index");
8882       return -99;
8883     }
8884
8885
8886   M (CLASSIFY_SET_INTERFACE_L2_TABLES, mp);
8887
8888   mp->sw_if_index = ntohl (sw_if_index);
8889   mp->ip4_table_index = ntohl (ip4_table_index);
8890   mp->ip6_table_index = ntohl (ip6_table_index);
8891   mp->other_table_index = ntohl (other_table_index);
8892   mp->is_input = (u8) is_input;
8893
8894   S (mp);
8895   W (ret);
8896   return ret;
8897 }
8898
8899 static int
8900 api_set_ipfix_exporter (vat_main_t * vam)
8901 {
8902   unformat_input_t *i = vam->input;
8903   vl_api_set_ipfix_exporter_t *mp;
8904   ip4_address_t collector_address;
8905   u8 collector_address_set = 0;
8906   u32 collector_port = ~0;
8907   ip4_address_t src_address;
8908   u8 src_address_set = 0;
8909   u32 vrf_id = ~0;
8910   u32 path_mtu = ~0;
8911   u32 template_interval = ~0;
8912   u8 udp_checksum = 0;
8913   int ret;
8914
8915   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8916     {
8917       if (unformat (i, "collector_address %U", unformat_ip4_address,
8918                     &collector_address))
8919         collector_address_set = 1;
8920       else if (unformat (i, "collector_port %d", &collector_port))
8921         ;
8922       else if (unformat (i, "src_address %U", unformat_ip4_address,
8923                          &src_address))
8924         src_address_set = 1;
8925       else if (unformat (i, "vrf_id %d", &vrf_id))
8926         ;
8927       else if (unformat (i, "path_mtu %d", &path_mtu))
8928         ;
8929       else if (unformat (i, "template_interval %d", &template_interval))
8930         ;
8931       else if (unformat (i, "udp_checksum"))
8932         udp_checksum = 1;
8933       else
8934         break;
8935     }
8936
8937   if (collector_address_set == 0)
8938     {
8939       errmsg ("collector_address required");
8940       return -99;
8941     }
8942
8943   if (src_address_set == 0)
8944     {
8945       errmsg ("src_address required");
8946       return -99;
8947     }
8948
8949   M (SET_IPFIX_EXPORTER, mp);
8950
8951   memcpy (mp->collector_address.un.ip4, collector_address.data,
8952           sizeof (collector_address.data));
8953   mp->collector_port = htons ((u16) collector_port);
8954   memcpy (mp->src_address.un.ip4, src_address.data,
8955           sizeof (src_address.data));
8956   mp->vrf_id = htonl (vrf_id);
8957   mp->path_mtu = htonl (path_mtu);
8958   mp->template_interval = htonl (template_interval);
8959   mp->udp_checksum = udp_checksum;
8960
8961   S (mp);
8962   W (ret);
8963   return ret;
8964 }
8965
8966 static int
8967 api_set_ipfix_classify_stream (vat_main_t * vam)
8968 {
8969   unformat_input_t *i = vam->input;
8970   vl_api_set_ipfix_classify_stream_t *mp;
8971   u32 domain_id = 0;
8972   u32 src_port = UDP_DST_PORT_ipfix;
8973   int ret;
8974
8975   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8976     {
8977       if (unformat (i, "domain %d", &domain_id))
8978         ;
8979       else if (unformat (i, "src_port %d", &src_port))
8980         ;
8981       else
8982         {
8983           errmsg ("unknown input `%U'", format_unformat_error, i);
8984           return -99;
8985         }
8986     }
8987
8988   M (SET_IPFIX_CLASSIFY_STREAM, mp);
8989
8990   mp->domain_id = htonl (domain_id);
8991   mp->src_port = htons ((u16) src_port);
8992
8993   S (mp);
8994   W (ret);
8995   return ret;
8996 }
8997
8998 static int
8999 api_ipfix_classify_table_add_del (vat_main_t * vam)
9000 {
9001   unformat_input_t *i = vam->input;
9002   vl_api_ipfix_classify_table_add_del_t *mp;
9003   int is_add = -1;
9004   u32 classify_table_index = ~0;
9005   u8 ip_version = 0;
9006   u8 transport_protocol = 255;
9007   int ret;
9008
9009   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9010     {
9011       if (unformat (i, "add"))
9012         is_add = 1;
9013       else if (unformat (i, "del"))
9014         is_add = 0;
9015       else if (unformat (i, "table %d", &classify_table_index))
9016         ;
9017       else if (unformat (i, "ip4"))
9018         ip_version = 4;
9019       else if (unformat (i, "ip6"))
9020         ip_version = 6;
9021       else if (unformat (i, "tcp"))
9022         transport_protocol = 6;
9023       else if (unformat (i, "udp"))
9024         transport_protocol = 17;
9025       else
9026         {
9027           errmsg ("unknown input `%U'", format_unformat_error, i);
9028           return -99;
9029         }
9030     }
9031
9032   if (is_add == -1)
9033     {
9034       errmsg ("expecting: add|del");
9035       return -99;
9036     }
9037   if (classify_table_index == ~0)
9038     {
9039       errmsg ("classifier table not specified");
9040       return -99;
9041     }
9042   if (ip_version == 0)
9043     {
9044       errmsg ("IP version not specified");
9045       return -99;
9046     }
9047
9048   M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp);
9049
9050   mp->is_add = is_add;
9051   mp->table_id = htonl (classify_table_index);
9052   mp->ip_version = ip_version;
9053   mp->transport_protocol = transport_protocol;
9054
9055   S (mp);
9056   W (ret);
9057   return ret;
9058 }
9059
9060 static int
9061 api_get_node_index (vat_main_t * vam)
9062 {
9063   unformat_input_t *i = vam->input;
9064   vl_api_get_node_index_t *mp;
9065   u8 *name = 0;
9066   int ret;
9067
9068   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9069     {
9070       if (unformat (i, "node %s", &name))
9071         ;
9072       else
9073         break;
9074     }
9075   if (name == 0)
9076     {
9077       errmsg ("node name required");
9078       return -99;
9079     }
9080   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9081     {
9082       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9083       return -99;
9084     }
9085
9086   M (GET_NODE_INDEX, mp);
9087   clib_memcpy (mp->node_name, name, vec_len (name));
9088   vec_free (name);
9089
9090   S (mp);
9091   W (ret);
9092   return ret;
9093 }
9094
9095 static int
9096 api_get_next_index (vat_main_t * vam)
9097 {
9098   unformat_input_t *i = vam->input;
9099   vl_api_get_next_index_t *mp;
9100   u8 *node_name = 0, *next_node_name = 0;
9101   int ret;
9102
9103   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9104     {
9105       if (unformat (i, "node-name %s", &node_name))
9106         ;
9107       else if (unformat (i, "next-node-name %s", &next_node_name))
9108         break;
9109     }
9110
9111   if (node_name == 0)
9112     {
9113       errmsg ("node name required");
9114       return -99;
9115     }
9116   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
9117     {
9118       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9119       return -99;
9120     }
9121
9122   if (next_node_name == 0)
9123     {
9124       errmsg ("next node name required");
9125       return -99;
9126     }
9127   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
9128     {
9129       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
9130       return -99;
9131     }
9132
9133   M (GET_NEXT_INDEX, mp);
9134   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
9135   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
9136   vec_free (node_name);
9137   vec_free (next_node_name);
9138
9139   S (mp);
9140   W (ret);
9141   return ret;
9142 }
9143
9144 static int
9145 api_add_node_next (vat_main_t * vam)
9146 {
9147   unformat_input_t *i = vam->input;
9148   vl_api_add_node_next_t *mp;
9149   u8 *name = 0;
9150   u8 *next = 0;
9151   int ret;
9152
9153   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9154     {
9155       if (unformat (i, "node %s", &name))
9156         ;
9157       else if (unformat (i, "next %s", &next))
9158         ;
9159       else
9160         break;
9161     }
9162   if (name == 0)
9163     {
9164       errmsg ("node name required");
9165       return -99;
9166     }
9167   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
9168     {
9169       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
9170       return -99;
9171     }
9172   if (next == 0)
9173     {
9174       errmsg ("next node required");
9175       return -99;
9176     }
9177   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
9178     {
9179       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
9180       return -99;
9181     }
9182
9183   M (ADD_NODE_NEXT, mp);
9184   clib_memcpy (mp->node_name, name, vec_len (name));
9185   clib_memcpy (mp->next_name, next, vec_len (next));
9186   vec_free (name);
9187   vec_free (next);
9188
9189   S (mp);
9190   W (ret);
9191   return ret;
9192 }
9193
9194 static void vl_api_sw_interface_tap_v2_details_t_handler
9195   (vl_api_sw_interface_tap_v2_details_t * mp)
9196 {
9197   vat_main_t *vam = &vat_main;
9198
9199   u8 *ip4 =
9200     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
9201             mp->host_ip4_prefix.len);
9202   u8 *ip6 =
9203     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
9204             mp->host_ip6_prefix.len);
9205
9206   print (vam->ofp,
9207          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
9208          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
9209          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9210          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
9211          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
9212
9213   vec_free (ip4);
9214   vec_free (ip6);
9215 }
9216
9217 static void vl_api_sw_interface_tap_v2_details_t_handler_json
9218   (vl_api_sw_interface_tap_v2_details_t * mp)
9219 {
9220   vat_main_t *vam = &vat_main;
9221   vat_json_node_t *node = NULL;
9222
9223   if (VAT_JSON_ARRAY != vam->json_tree.type)
9224     {
9225       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9226       vat_json_init_array (&vam->json_tree);
9227     }
9228   node = vat_json_array_add (&vam->json_tree);
9229
9230   vat_json_init_object (node);
9231   vat_json_object_add_uint (node, "id", ntohl (mp->id));
9232   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9233   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
9234   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
9235   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9236   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9237   vat_json_object_add_string_copy (node, "host_mac_addr",
9238                                    format (0, "%U", format_ethernet_address,
9239                                            &mp->host_mac_addr));
9240   vat_json_object_add_string_copy (node, "host_namespace",
9241                                    mp->host_namespace);
9242   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
9243   vat_json_object_add_string_copy (node, "host_ip4_addr",
9244                                    format (0, "%U/%d", format_ip4_address,
9245                                            mp->host_ip4_prefix.address,
9246                                            mp->host_ip4_prefix.len));
9247   vat_json_object_add_string_copy (node, "host_ip6_prefix",
9248                                    format (0, "%U/%d", format_ip6_address,
9249                                            mp->host_ip6_prefix.address,
9250                                            mp->host_ip6_prefix.len));
9251
9252 }
9253
9254 static int
9255 api_sw_interface_tap_v2_dump (vat_main_t * vam)
9256 {
9257   vl_api_sw_interface_tap_v2_dump_t *mp;
9258   vl_api_control_ping_t *mp_ping;
9259   int ret;
9260
9261   print (vam->ofp,
9262          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
9263          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
9264          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
9265          "host_ip6_addr");
9266
9267   /* Get list of tap interfaces */
9268   M (SW_INTERFACE_TAP_V2_DUMP, mp);
9269   S (mp);
9270
9271   /* Use a control ping for synchronization */
9272   MPING (CONTROL_PING, mp_ping);
9273   S (mp_ping);
9274
9275   W (ret);
9276   return ret;
9277 }
9278
9279 static void vl_api_sw_interface_virtio_pci_details_t_handler
9280   (vl_api_sw_interface_virtio_pci_details_t * mp)
9281 {
9282   vat_main_t *vam = &vat_main;
9283
9284   typedef union
9285   {
9286     struct
9287     {
9288       u16 domain;
9289       u8 bus;
9290       u8 slot:5;
9291       u8 function:3;
9292     };
9293     u32 as_u32;
9294   } pci_addr_t;
9295   pci_addr_t addr;
9296
9297   addr.domain = ntohs (mp->pci_addr.domain);
9298   addr.bus = mp->pci_addr.bus;
9299   addr.slot = mp->pci_addr.slot;
9300   addr.function = mp->pci_addr.function;
9301
9302   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
9303                          addr.slot, addr.function);
9304
9305   print (vam->ofp,
9306          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
9307          pci_addr, ntohl (mp->sw_if_index),
9308          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
9309          format_ethernet_address, mp->mac_addr,
9310          clib_net_to_host_u64 (mp->features));
9311   vec_free (pci_addr);
9312 }
9313
9314 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
9315   (vl_api_sw_interface_virtio_pci_details_t * mp)
9316 {
9317   vat_main_t *vam = &vat_main;
9318   vat_json_node_t *node = NULL;
9319   vlib_pci_addr_t pci_addr;
9320
9321   if (VAT_JSON_ARRAY != vam->json_tree.type)
9322     {
9323       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9324       vat_json_init_array (&vam->json_tree);
9325     }
9326   node = vat_json_array_add (&vam->json_tree);
9327
9328   pci_addr.domain = ntohs (mp->pci_addr.domain);
9329   pci_addr.bus = mp->pci_addr.bus;
9330   pci_addr.slot = mp->pci_addr.slot;
9331   pci_addr.function = mp->pci_addr.function;
9332
9333   vat_json_init_object (node);
9334   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
9335   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9336   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
9337   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
9338   vat_json_object_add_uint (node, "features",
9339                             clib_net_to_host_u64 (mp->features));
9340   vat_json_object_add_string_copy (node, "mac_addr",
9341                                    format (0, "%U", format_ethernet_address,
9342                                            &mp->mac_addr));
9343 }
9344
9345 static int
9346 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
9347 {
9348   vl_api_sw_interface_virtio_pci_dump_t *mp;
9349   vl_api_control_ping_t *mp_ping;
9350   int ret;
9351
9352   print (vam->ofp,
9353          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
9354          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
9355          "mac_addr", "features");
9356
9357   /* Get list of tap interfaces */
9358   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
9359   S (mp);
9360
9361   /* Use a control ping for synchronization */
9362   MPING (CONTROL_PING, mp_ping);
9363   S (mp_ping);
9364
9365   W (ret);
9366   return ret;
9367 }
9368
9369 static int
9370 api_vxlan_offload_rx (vat_main_t * vam)
9371 {
9372   unformat_input_t *line_input = vam->input;
9373   vl_api_vxlan_offload_rx_t *mp;
9374   u32 hw_if_index = ~0, rx_if_index = ~0;
9375   u8 is_add = 1;
9376   int ret;
9377
9378   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9379     {
9380       if (unformat (line_input, "del"))
9381         is_add = 0;
9382       else if (unformat (line_input, "hw %U", api_unformat_hw_if_index, vam,
9383                          &hw_if_index))
9384         ;
9385       else if (unformat (line_input, "hw hw_if_index %u", &hw_if_index))
9386         ;
9387       else if (unformat (line_input, "rx %U", api_unformat_sw_if_index, vam,
9388                          &rx_if_index))
9389         ;
9390       else if (unformat (line_input, "rx sw_if_index %u", &rx_if_index))
9391         ;
9392       else
9393         {
9394           errmsg ("parse error '%U'", format_unformat_error, line_input);
9395           return -99;
9396         }
9397     }
9398
9399   if (hw_if_index == ~0)
9400     {
9401       errmsg ("no hw interface");
9402       return -99;
9403     }
9404
9405   if (rx_if_index == ~0)
9406     {
9407       errmsg ("no rx tunnel");
9408       return -99;
9409     }
9410
9411   M (VXLAN_OFFLOAD_RX, mp);
9412
9413   mp->hw_if_index = ntohl (hw_if_index);
9414   mp->sw_if_index = ntohl (rx_if_index);
9415   mp->enable = is_add;
9416
9417   S (mp);
9418   W (ret);
9419   return ret;
9420 }
9421
9422 static uword unformat_vxlan_decap_next
9423   (unformat_input_t * input, va_list * args)
9424 {
9425   u32 *result = va_arg (*args, u32 *);
9426   u32 tmp;
9427
9428   if (unformat (input, "l2"))
9429     *result = VXLAN_INPUT_NEXT_L2_INPUT;
9430   else if (unformat (input, "%d", &tmp))
9431     *result = tmp;
9432   else
9433     return 0;
9434   return 1;
9435 }
9436
9437 static int
9438 api_vxlan_add_del_tunnel (vat_main_t * vam)
9439 {
9440   unformat_input_t *line_input = vam->input;
9441   vl_api_vxlan_add_del_tunnel_t *mp;
9442   ip46_address_t src, dst;
9443   u8 is_add = 1;
9444   u8 ipv4_set = 0, ipv6_set = 0;
9445   u8 src_set = 0;
9446   u8 dst_set = 0;
9447   u8 grp_set = 0;
9448   u32 instance = ~0;
9449   u32 mcast_sw_if_index = ~0;
9450   u32 encap_vrf_id = 0;
9451   u32 decap_next_index = ~0;
9452   u32 vni = 0;
9453   int ret;
9454
9455   /* Can't "universally zero init" (={0}) due to GCC bug 53119 */
9456   clib_memset (&src, 0, sizeof src);
9457   clib_memset (&dst, 0, sizeof dst);
9458
9459   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9460     {
9461       if (unformat (line_input, "del"))
9462         is_add = 0;
9463       else if (unformat (line_input, "instance %d", &instance))
9464         ;
9465       else
9466         if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
9467         {
9468           ipv4_set = 1;
9469           src_set = 1;
9470         }
9471       else
9472         if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4))
9473         {
9474           ipv4_set = 1;
9475           dst_set = 1;
9476         }
9477       else
9478         if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6))
9479         {
9480           ipv6_set = 1;
9481           src_set = 1;
9482         }
9483       else
9484         if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6))
9485         {
9486           ipv6_set = 1;
9487           dst_set = 1;
9488         }
9489       else if (unformat (line_input, "group %U %U",
9490                          unformat_ip4_address, &dst.ip4,
9491                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9492         {
9493           grp_set = dst_set = 1;
9494           ipv4_set = 1;
9495         }
9496       else if (unformat (line_input, "group %U",
9497                          unformat_ip4_address, &dst.ip4))
9498         {
9499           grp_set = dst_set = 1;
9500           ipv4_set = 1;
9501         }
9502       else if (unformat (line_input, "group %U %U",
9503                          unformat_ip6_address, &dst.ip6,
9504                          api_unformat_sw_if_index, vam, &mcast_sw_if_index))
9505         {
9506           grp_set = dst_set = 1;
9507           ipv6_set = 1;
9508         }
9509       else if (unformat (line_input, "group %U",
9510                          unformat_ip6_address, &dst.ip6))
9511         {
9512           grp_set = dst_set = 1;
9513           ipv6_set = 1;
9514         }
9515       else
9516         if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index))
9517         ;
9518       else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
9519         ;
9520       else if (unformat (line_input, "decap-next %U",
9521                          unformat_vxlan_decap_next, &decap_next_index))
9522         ;
9523       else if (unformat (line_input, "vni %d", &vni))
9524         ;
9525       else
9526         {
9527           errmsg ("parse error '%U'", format_unformat_error, line_input);
9528           return -99;
9529         }
9530     }
9531
9532   if (src_set == 0)
9533     {
9534       errmsg ("tunnel src address not specified");
9535       return -99;
9536     }
9537   if (dst_set == 0)
9538     {
9539       errmsg ("tunnel dst address not specified");
9540       return -99;
9541     }
9542
9543   if (grp_set && !ip46_address_is_multicast (&dst))
9544     {
9545       errmsg ("tunnel group address not multicast");
9546       return -99;
9547     }
9548   if (grp_set && mcast_sw_if_index == ~0)
9549     {
9550       errmsg ("tunnel nonexistent multicast device");
9551       return -99;
9552     }
9553   if (grp_set == 0 && ip46_address_is_multicast (&dst))
9554     {
9555       errmsg ("tunnel dst address must be unicast");
9556       return -99;
9557     }
9558
9559
9560   if (ipv4_set && ipv6_set)
9561     {
9562       errmsg ("both IPv4 and IPv6 addresses specified");
9563       return -99;
9564     }
9565
9566   if ((vni == 0) || (vni >> 24))
9567     {
9568       errmsg ("vni not specified or out of range");
9569       return -99;
9570     }
9571
9572   M (VXLAN_ADD_DEL_TUNNEL, mp);
9573
9574   if (ipv6_set)
9575     {
9576       clib_memcpy (mp->src_address.un.ip6, &src.ip6, sizeof (src.ip6));
9577       clib_memcpy (mp->dst_address.un.ip6, &dst.ip6, sizeof (dst.ip6));
9578     }
9579   else
9580     {
9581       clib_memcpy (mp->src_address.un.ip4, &src.ip4, sizeof (src.ip4));
9582       clib_memcpy (mp->dst_address.un.ip4, &dst.ip4, sizeof (dst.ip4));
9583     }
9584   mp->src_address.af = ipv6_set;
9585   mp->dst_address.af = ipv6_set;
9586
9587   mp->instance = htonl (instance);
9588   mp->encap_vrf_id = ntohl (encap_vrf_id);
9589   mp->decap_next_index = ntohl (decap_next_index);
9590   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
9591   mp->vni = ntohl (vni);
9592   mp->is_add = is_add;
9593
9594   S (mp);
9595   W (ret);
9596   return ret;
9597 }
9598
9599 static void vl_api_vxlan_tunnel_details_t_handler
9600   (vl_api_vxlan_tunnel_details_t * mp)
9601 {
9602   vat_main_t *vam = &vat_main;
9603   ip46_address_t src =
9604     to_ip46 (mp->dst_address.af, (u8 *) & mp->dst_address.un);
9605   ip46_address_t dst =
9606     to_ip46 (mp->dst_address.af, (u8 *) & mp->src_address.un);
9607
9608   print (vam->ofp, "%11d%11d%24U%24U%14d%18d%13d%19d",
9609          ntohl (mp->sw_if_index),
9610          ntohl (mp->instance),
9611          format_ip46_address, &src, IP46_TYPE_ANY,
9612          format_ip46_address, &dst, IP46_TYPE_ANY,
9613          ntohl (mp->encap_vrf_id),
9614          ntohl (mp->decap_next_index), ntohl (mp->vni),
9615          ntohl (mp->mcast_sw_if_index));
9616 }
9617
9618 static void vl_api_vxlan_tunnel_details_t_handler_json
9619   (vl_api_vxlan_tunnel_details_t * mp)
9620 {
9621   vat_main_t *vam = &vat_main;
9622   vat_json_node_t *node = NULL;
9623
9624   if (VAT_JSON_ARRAY != vam->json_tree.type)
9625     {
9626       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9627       vat_json_init_array (&vam->json_tree);
9628     }
9629   node = vat_json_array_add (&vam->json_tree);
9630
9631   vat_json_init_object (node);
9632   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9633
9634   vat_json_object_add_uint (node, "instance", ntohl (mp->instance));
9635
9636   if (mp->src_address.af)
9637     {
9638       struct in6_addr ip6;
9639
9640       clib_memcpy (&ip6, mp->src_address.un.ip6, sizeof (ip6));
9641       vat_json_object_add_ip6 (node, "src_address", ip6);
9642       clib_memcpy (&ip6, mp->dst_address.un.ip6, sizeof (ip6));
9643       vat_json_object_add_ip6 (node, "dst_address", ip6);
9644     }
9645   else
9646     {
9647       struct in_addr ip4;
9648
9649       clib_memcpy (&ip4, mp->src_address.un.ip4, sizeof (ip4));
9650       vat_json_object_add_ip4 (node, "src_address", ip4);
9651       clib_memcpy (&ip4, mp->dst_address.un.ip4, sizeof (ip4));
9652       vat_json_object_add_ip4 (node, "dst_address", ip4);
9653     }
9654   vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id));
9655   vat_json_object_add_uint (node, "decap_next_index",
9656                             ntohl (mp->decap_next_index));
9657   vat_json_object_add_uint (node, "vni", ntohl (mp->vni));
9658   vat_json_object_add_uint (node, "mcast_sw_if_index",
9659                             ntohl (mp->mcast_sw_if_index));
9660 }
9661
9662 static int
9663 api_vxlan_tunnel_dump (vat_main_t * vam)
9664 {
9665   unformat_input_t *i = vam->input;
9666   vl_api_vxlan_tunnel_dump_t *mp;
9667   vl_api_control_ping_t *mp_ping;
9668   u32 sw_if_index;
9669   u8 sw_if_index_set = 0;
9670   int ret;
9671
9672   /* Parse args required to build the message */
9673   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9674     {
9675       if (unformat (i, "sw_if_index %d", &sw_if_index))
9676         sw_if_index_set = 1;
9677       else
9678         break;
9679     }
9680
9681   if (sw_if_index_set == 0)
9682     {
9683       sw_if_index = ~0;
9684     }
9685
9686   if (!vam->json_output)
9687     {
9688       print (vam->ofp, "%11s%11s%24s%24s%14s%18s%13s%19s",
9689              "sw_if_index", "instance", "src_address", "dst_address",
9690              "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index");
9691     }
9692
9693   /* Get list of vxlan-tunnel interfaces */
9694   M (VXLAN_TUNNEL_DUMP, mp);
9695
9696   mp->sw_if_index = htonl (sw_if_index);
9697
9698   S (mp);
9699
9700   /* Use a control ping for synchronization */
9701   MPING (CONTROL_PING, mp_ping);
9702   S (mp_ping);
9703
9704   W (ret);
9705   return ret;
9706 }
9707
9708 static int
9709 api_l2_fib_clear_table (vat_main_t * vam)
9710 {
9711 //  unformat_input_t * i = vam->input;
9712   vl_api_l2_fib_clear_table_t *mp;
9713   int ret;
9714
9715   M (L2_FIB_CLEAR_TABLE, mp);
9716
9717   S (mp);
9718   W (ret);
9719   return ret;
9720 }
9721
9722 static int
9723 api_l2_interface_efp_filter (vat_main_t * vam)
9724 {
9725   unformat_input_t *i = vam->input;
9726   vl_api_l2_interface_efp_filter_t *mp;
9727   u32 sw_if_index;
9728   u8 enable = 1;
9729   u8 sw_if_index_set = 0;
9730   int ret;
9731
9732   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9733     {
9734       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9735         sw_if_index_set = 1;
9736       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9737         sw_if_index_set = 1;
9738       else if (unformat (i, "enable"))
9739         enable = 1;
9740       else if (unformat (i, "disable"))
9741         enable = 0;
9742       else
9743         {
9744           clib_warning ("parse error '%U'", format_unformat_error, i);
9745           return -99;
9746         }
9747     }
9748
9749   if (sw_if_index_set == 0)
9750     {
9751       errmsg ("missing sw_if_index");
9752       return -99;
9753     }
9754
9755   M (L2_INTERFACE_EFP_FILTER, mp);
9756
9757   mp->sw_if_index = ntohl (sw_if_index);
9758   mp->enable_disable = enable;
9759
9760   S (mp);
9761   W (ret);
9762   return ret;
9763 }
9764
9765 #define foreach_vtr_op                          \
9766 _("disable",  L2_VTR_DISABLED)                  \
9767 _("push-1",  L2_VTR_PUSH_1)                     \
9768 _("push-2",  L2_VTR_PUSH_2)                     \
9769 _("pop-1",  L2_VTR_POP_1)                       \
9770 _("pop-2",  L2_VTR_POP_2)                       \
9771 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
9772 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
9773 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
9774 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
9775
9776 static int
9777 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
9778 {
9779   unformat_input_t *i = vam->input;
9780   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
9781   u32 sw_if_index;
9782   u8 sw_if_index_set = 0;
9783   u8 vtr_op_set = 0;
9784   u32 vtr_op = 0;
9785   u32 push_dot1q = 1;
9786   u32 tag1 = ~0;
9787   u32 tag2 = ~0;
9788   int ret;
9789
9790   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9791     {
9792       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9793         sw_if_index_set = 1;
9794       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9795         sw_if_index_set = 1;
9796       else if (unformat (i, "vtr_op %d", &vtr_op))
9797         vtr_op_set = 1;
9798 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
9799       foreach_vtr_op
9800 #undef _
9801         else if (unformat (i, "push_dot1q %d", &push_dot1q))
9802         ;
9803       else if (unformat (i, "tag1 %d", &tag1))
9804         ;
9805       else if (unformat (i, "tag2 %d", &tag2))
9806         ;
9807       else
9808         {
9809           clib_warning ("parse error '%U'", format_unformat_error, i);
9810           return -99;
9811         }
9812     }
9813
9814   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
9815     {
9816       errmsg ("missing vtr operation or sw_if_index");
9817       return -99;
9818     }
9819
9820   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
9821   mp->sw_if_index = ntohl (sw_if_index);
9822   mp->vtr_op = ntohl (vtr_op);
9823   mp->push_dot1q = ntohl (push_dot1q);
9824   mp->tag1 = ntohl (tag1);
9825   mp->tag2 = ntohl (tag2);
9826
9827   S (mp);
9828   W (ret);
9829   return ret;
9830 }
9831
9832 static int
9833 api_create_vhost_user_if (vat_main_t * vam)
9834 {
9835   unformat_input_t *i = vam->input;
9836   vl_api_create_vhost_user_if_t *mp;
9837   u8 *file_name;
9838   u8 is_server = 0;
9839   u8 file_name_set = 0;
9840   u32 custom_dev_instance = ~0;
9841   u8 hwaddr[6];
9842   u8 use_custom_mac = 0;
9843   u8 disable_mrg_rxbuf = 0;
9844   u8 disable_indirect_desc = 0;
9845   u8 *tag = 0;
9846   u8 enable_gso = 0;
9847   u8 enable_packed = 0;
9848   int ret;
9849
9850   /* Shut up coverity */
9851   clib_memset (hwaddr, 0, sizeof (hwaddr));
9852
9853   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9854     {
9855       if (unformat (i, "socket %s", &file_name))
9856         {
9857           file_name_set = 1;
9858         }
9859       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
9860         ;
9861       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
9862         use_custom_mac = 1;
9863       else if (unformat (i, "server"))
9864         is_server = 1;
9865       else if (unformat (i, "disable_mrg_rxbuf"))
9866         disable_mrg_rxbuf = 1;
9867       else if (unformat (i, "disable_indirect_desc"))
9868         disable_indirect_desc = 1;
9869       else if (unformat (i, "gso"))
9870         enable_gso = 1;
9871       else if (unformat (i, "packed"))
9872         enable_packed = 1;
9873       else if (unformat (i, "tag %s", &tag))
9874         ;
9875       else
9876         break;
9877     }
9878
9879   if (file_name_set == 0)
9880     {
9881       errmsg ("missing socket file name");
9882       return -99;
9883     }
9884
9885   if (vec_len (file_name) > 255)
9886     {
9887       errmsg ("socket file name too long");
9888       return -99;
9889     }
9890   vec_add1 (file_name, 0);
9891
9892   M (CREATE_VHOST_USER_IF, mp);
9893
9894   mp->is_server = is_server;
9895   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
9896   mp->disable_indirect_desc = disable_indirect_desc;
9897   mp->enable_gso = enable_gso;
9898   mp->enable_packed = enable_packed;
9899   mp->custom_dev_instance = ntohl (custom_dev_instance);
9900   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
9901   vec_free (file_name);
9902   if (custom_dev_instance != ~0)
9903     mp->renumber = 1;
9904
9905   mp->use_custom_mac = use_custom_mac;
9906   clib_memcpy (mp->mac_address, hwaddr, 6);
9907   if (tag)
9908     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
9909   vec_free (tag);
9910
9911   S (mp);
9912   W (ret);
9913   return ret;
9914 }
9915
9916 static int
9917 api_modify_vhost_user_if (vat_main_t * vam)
9918 {
9919   unformat_input_t *i = vam->input;
9920   vl_api_modify_vhost_user_if_t *mp;
9921   u8 *file_name;
9922   u8 is_server = 0;
9923   u8 file_name_set = 0;
9924   u32 custom_dev_instance = ~0;
9925   u8 sw_if_index_set = 0;
9926   u32 sw_if_index = (u32) ~ 0;
9927   u8 enable_gso = 0;
9928   u8 enable_packed = 0;
9929   int ret;
9930
9931   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9932     {
9933       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9934         sw_if_index_set = 1;
9935       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9936         sw_if_index_set = 1;
9937       else if (unformat (i, "socket %s", &file_name))
9938         {
9939           file_name_set = 1;
9940         }
9941       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
9942         ;
9943       else if (unformat (i, "server"))
9944         is_server = 1;
9945       else if (unformat (i, "gso"))
9946         enable_gso = 1;
9947       else if (unformat (i, "packed"))
9948         enable_packed = 1;
9949       else
9950         break;
9951     }
9952
9953   if (sw_if_index_set == 0)
9954     {
9955       errmsg ("missing sw_if_index or interface name");
9956       return -99;
9957     }
9958
9959   if (file_name_set == 0)
9960     {
9961       errmsg ("missing socket file name");
9962       return -99;
9963     }
9964
9965   if (vec_len (file_name) > 255)
9966     {
9967       errmsg ("socket file name too long");
9968       return -99;
9969     }
9970   vec_add1 (file_name, 0);
9971
9972   M (MODIFY_VHOST_USER_IF, mp);
9973
9974   mp->sw_if_index = ntohl (sw_if_index);
9975   mp->is_server = is_server;
9976   mp->enable_gso = enable_gso;
9977   mp->enable_packed = enable_packed;
9978   mp->custom_dev_instance = ntohl (custom_dev_instance);
9979   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
9980   vec_free (file_name);
9981   if (custom_dev_instance != ~0)
9982     mp->renumber = 1;
9983
9984   S (mp);
9985   W (ret);
9986   return ret;
9987 }
9988
9989 static int
9990 api_create_vhost_user_if_v2 (vat_main_t * vam)
9991 {
9992   unformat_input_t *i = vam->input;
9993   vl_api_create_vhost_user_if_v2_t *mp;
9994   u8 *file_name;
9995   u8 is_server = 0;
9996   u8 file_name_set = 0;
9997   u32 custom_dev_instance = ~0;
9998   u8 hwaddr[6];
9999   u8 use_custom_mac = 0;
10000   u8 disable_mrg_rxbuf = 0;
10001   u8 disable_indirect_desc = 0;
10002   u8 *tag = 0;
10003   u8 enable_gso = 0;
10004   u8 enable_packed = 0;
10005   u8 enable_event_idx = 0;
10006   int ret;
10007
10008   /* Shut up coverity */
10009   clib_memset (hwaddr, 0, sizeof (hwaddr));
10010
10011   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10012     {
10013       if (unformat (i, "socket %s", &file_name))
10014         {
10015           file_name_set = 1;
10016         }
10017       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
10018         ;
10019       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
10020         use_custom_mac = 1;
10021       else if (unformat (i, "server"))
10022         is_server = 1;
10023       else if (unformat (i, "disable_mrg_rxbuf"))
10024         disable_mrg_rxbuf = 1;
10025       else if (unformat (i, "disable_indirect_desc"))
10026         disable_indirect_desc = 1;
10027       else if (unformat (i, "gso"))
10028         enable_gso = 1;
10029       else if (unformat (i, "packed"))
10030         enable_packed = 1;
10031       else if (unformat (i, "event-idx"))
10032         enable_event_idx = 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_V2, 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   mp->enable_event_idx = enable_event_idx;
10060   mp->custom_dev_instance = ntohl (custom_dev_instance);
10061   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10062   vec_free (file_name);
10063   if (custom_dev_instance != ~0)
10064     mp->renumber = 1;
10065
10066   mp->use_custom_mac = use_custom_mac;
10067   clib_memcpy (mp->mac_address, hwaddr, 6);
10068   if (tag)
10069     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
10070   vec_free (tag);
10071
10072   S (mp);
10073   W (ret);
10074   return ret;
10075 }
10076
10077 static int
10078 api_modify_vhost_user_if_v2 (vat_main_t * vam)
10079 {
10080   unformat_input_t *i = vam->input;
10081   vl_api_modify_vhost_user_if_v2_t *mp;
10082   u8 *file_name;
10083   u8 is_server = 0;
10084   u8 file_name_set = 0;
10085   u32 custom_dev_instance = ~0;
10086   u8 sw_if_index_set = 0;
10087   u32 sw_if_index = (u32) ~ 0;
10088   u8 enable_gso = 0;
10089   u8 enable_packed = 0;
10090   u8 enable_event_idx = 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 if (unformat (i, "event-idx"))
10112         enable_event_idx = 1;
10113       else
10114         break;
10115     }
10116
10117   if (sw_if_index_set == 0)
10118     {
10119       errmsg ("missing sw_if_index or interface name");
10120       return -99;
10121     }
10122
10123   if (file_name_set == 0)
10124     {
10125       errmsg ("missing socket file name");
10126       return -99;
10127     }
10128
10129   if (vec_len (file_name) > 255)
10130     {
10131       errmsg ("socket file name too long");
10132       return -99;
10133     }
10134   vec_add1 (file_name, 0);
10135
10136   M (MODIFY_VHOST_USER_IF_V2, mp);
10137
10138   mp->sw_if_index = ntohl (sw_if_index);
10139   mp->is_server = is_server;
10140   mp->enable_gso = enable_gso;
10141   mp->enable_packed = enable_packed;
10142   mp->enable_event_idx = enable_event_idx;
10143   mp->custom_dev_instance = ntohl (custom_dev_instance);
10144   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
10145   vec_free (file_name);
10146   if (custom_dev_instance != ~0)
10147     mp->renumber = 1;
10148
10149   S (mp);
10150   W (ret);
10151   return ret;
10152 }
10153
10154 static int
10155 api_delete_vhost_user_if (vat_main_t * vam)
10156 {
10157   unformat_input_t *i = vam->input;
10158   vl_api_delete_vhost_user_if_t *mp;
10159   u32 sw_if_index = ~0;
10160   u8 sw_if_index_set = 0;
10161   int ret;
10162
10163   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10164     {
10165       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10166         sw_if_index_set = 1;
10167       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10168         sw_if_index_set = 1;
10169       else
10170         break;
10171     }
10172
10173   if (sw_if_index_set == 0)
10174     {
10175       errmsg ("missing sw_if_index or interface name");
10176       return -99;
10177     }
10178
10179
10180   M (DELETE_VHOST_USER_IF, mp);
10181
10182   mp->sw_if_index = ntohl (sw_if_index);
10183
10184   S (mp);
10185   W (ret);
10186   return ret;
10187 }
10188
10189 static void vl_api_sw_interface_vhost_user_details_t_handler
10190   (vl_api_sw_interface_vhost_user_details_t * mp)
10191 {
10192   vat_main_t *vam = &vat_main;
10193   u64 features;
10194
10195   features =
10196     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
10197                                                     clib_net_to_host_u32
10198                                                     (mp->features_last_32) <<
10199                                                     32);
10200
10201   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %16llx %6d %7d %s",
10202          (char *) mp->interface_name, ntohl (mp->sw_if_index),
10203          ntohl (mp->virtio_net_hdr_sz), 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, "Interface name            idx hdr_sz         features "
10257                    "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 void
11180 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
11181 {
11182   vat_main_t *vam = &vat_main;
11183
11184   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
11185          "crypto_key %U integ_alg %u integ_key %U flags %x "
11186          "tunnel_src_addr %U tunnel_dst_addr %U "
11187          "salt %u seq_outbound %lu last_seq_inbound %lu "
11188          "replay_window %lu stat_index %u\n",
11189          ntohl (mp->entry.sad_id),
11190          ntohl (mp->sw_if_index),
11191          ntohl (mp->entry.spi),
11192          ntohl (mp->entry.protocol),
11193          ntohl (mp->entry.crypto_algorithm),
11194          format_hex_bytes, mp->entry.crypto_key.data,
11195          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
11196          format_hex_bytes, mp->entry.integrity_key.data,
11197          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
11198          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
11199          &mp->entry.tunnel_dst, ntohl (mp->salt),
11200          clib_net_to_host_u64 (mp->seq_outbound),
11201          clib_net_to_host_u64 (mp->last_seq_inbound),
11202          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
11203 }
11204
11205 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
11206 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
11207
11208 static void vl_api_ipsec_sa_details_t_handler_json
11209   (vl_api_ipsec_sa_details_t * mp)
11210 {
11211   vat_main_t *vam = &vat_main;
11212   vat_json_node_t *node = NULL;
11213   vl_api_ipsec_sad_flags_t flags;
11214
11215   if (VAT_JSON_ARRAY != vam->json_tree.type)
11216     {
11217       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11218       vat_json_init_array (&vam->json_tree);
11219     }
11220   node = vat_json_array_add (&vam->json_tree);
11221
11222   vat_json_init_object (node);
11223   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
11224   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11225   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
11226   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
11227   vat_json_object_add_uint (node, "crypto_alg",
11228                             ntohl (mp->entry.crypto_algorithm));
11229   vat_json_object_add_uint (node, "integ_alg",
11230                             ntohl (mp->entry.integrity_algorithm));
11231   flags = ntohl (mp->entry.flags);
11232   vat_json_object_add_uint (node, "use_esn",
11233                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
11234   vat_json_object_add_uint (node, "use_anti_replay",
11235                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
11236   vat_json_object_add_uint (node, "is_tunnel",
11237                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
11238   vat_json_object_add_uint (node, "is_tunnel_ip6",
11239                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
11240   vat_json_object_add_uint (node, "udp_encap",
11241                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
11242   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
11243                              mp->entry.crypto_key.length);
11244   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
11245                              mp->entry.integrity_key.length);
11246   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
11247   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
11248   vat_json_object_add_uint (node, "replay_window",
11249                             clib_net_to_host_u64 (mp->replay_window));
11250   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
11251 }
11252
11253 static int
11254 api_ipsec_sa_dump (vat_main_t * vam)
11255 {
11256   unformat_input_t *i = vam->input;
11257   vl_api_ipsec_sa_dump_t *mp;
11258   vl_api_control_ping_t *mp_ping;
11259   u32 sa_id = ~0;
11260   int ret;
11261
11262   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11263     {
11264       if (unformat (i, "sa_id %d", &sa_id))
11265         ;
11266       else
11267         {
11268           clib_warning ("parse error '%U'", format_unformat_error, i);
11269           return -99;
11270         }
11271     }
11272
11273   M (IPSEC_SA_DUMP, mp);
11274
11275   mp->sa_id = ntohl (sa_id);
11276
11277   S (mp);
11278
11279   /* Use a control ping for synchronization */
11280   M (CONTROL_PING, mp_ping);
11281   S (mp_ping);
11282
11283   W (ret);
11284   return ret;
11285 }
11286
11287 static int
11288 api_get_first_msg_id (vat_main_t * vam)
11289 {
11290   vl_api_get_first_msg_id_t *mp;
11291   unformat_input_t *i = vam->input;
11292   u8 *name;
11293   u8 name_set = 0;
11294   int ret;
11295
11296   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11297     {
11298       if (unformat (i, "client %s", &name))
11299         name_set = 1;
11300       else
11301         break;
11302     }
11303
11304   if (name_set == 0)
11305     {
11306       errmsg ("missing client name");
11307       return -99;
11308     }
11309   vec_add1 (name, 0);
11310
11311   if (vec_len (name) > 63)
11312     {
11313       errmsg ("client name too long");
11314       return -99;
11315     }
11316
11317   M (GET_FIRST_MSG_ID, mp);
11318   clib_memcpy (mp->name, name, vec_len (name));
11319   S (mp);
11320   W (ret);
11321   return ret;
11322 }
11323
11324 static int
11325 api_cop_interface_enable_disable (vat_main_t * vam)
11326 {
11327   unformat_input_t *line_input = vam->input;
11328   vl_api_cop_interface_enable_disable_t *mp;
11329   u32 sw_if_index = ~0;
11330   u8 enable_disable = 1;
11331   int ret;
11332
11333   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11334     {
11335       if (unformat (line_input, "disable"))
11336         enable_disable = 0;
11337       if (unformat (line_input, "enable"))
11338         enable_disable = 1;
11339       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11340                          vam, &sw_if_index))
11341         ;
11342       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11343         ;
11344       else
11345         break;
11346     }
11347
11348   if (sw_if_index == ~0)
11349     {
11350       errmsg ("missing interface name or sw_if_index");
11351       return -99;
11352     }
11353
11354   /* Construct the API message */
11355   M (COP_INTERFACE_ENABLE_DISABLE, mp);
11356   mp->sw_if_index = ntohl (sw_if_index);
11357   mp->enable_disable = enable_disable;
11358
11359   /* send it... */
11360   S (mp);
11361   /* Wait for the reply */
11362   W (ret);
11363   return ret;
11364 }
11365
11366 static int
11367 api_cop_whitelist_enable_disable (vat_main_t * vam)
11368 {
11369   unformat_input_t *line_input = vam->input;
11370   vl_api_cop_whitelist_enable_disable_t *mp;
11371   u32 sw_if_index = ~0;
11372   u8 ip4 = 0, ip6 = 0, default_cop = 0;
11373   u32 fib_id = 0;
11374   int ret;
11375
11376   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
11377     {
11378       if (unformat (line_input, "ip4"))
11379         ip4 = 1;
11380       else if (unformat (line_input, "ip6"))
11381         ip6 = 1;
11382       else if (unformat (line_input, "default"))
11383         default_cop = 1;
11384       else if (unformat (line_input, "%U", api_unformat_sw_if_index,
11385                          vam, &sw_if_index))
11386         ;
11387       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
11388         ;
11389       else if (unformat (line_input, "fib-id %d", &fib_id))
11390         ;
11391       else
11392         break;
11393     }
11394
11395   if (sw_if_index == ~0)
11396     {
11397       errmsg ("missing interface name or sw_if_index");
11398       return -99;
11399     }
11400
11401   /* Construct the API message */
11402   M (COP_WHITELIST_ENABLE_DISABLE, mp);
11403   mp->sw_if_index = ntohl (sw_if_index);
11404   mp->fib_id = ntohl (fib_id);
11405   mp->ip4 = ip4;
11406   mp->ip6 = ip6;
11407   mp->default_cop = default_cop;
11408
11409   /* send it... */
11410   S (mp);
11411   /* Wait for the reply */
11412   W (ret);
11413   return ret;
11414 }
11415
11416 static int
11417 api_get_node_graph (vat_main_t * vam)
11418 {
11419   vl_api_get_node_graph_t *mp;
11420   int ret;
11421
11422   M (GET_NODE_GRAPH, mp);
11423
11424   /* send it... */
11425   S (mp);
11426   /* Wait for the reply */
11427   W (ret);
11428   return ret;
11429 }
11430
11431 static int
11432 api_af_packet_create (vat_main_t * vam)
11433 {
11434   unformat_input_t *i = vam->input;
11435   vl_api_af_packet_create_t *mp;
11436   u8 *host_if_name = 0;
11437   u8 hw_addr[6];
11438   u8 random_hw_addr = 1;
11439   int ret;
11440
11441   clib_memset (hw_addr, 0, sizeof (hw_addr));
11442
11443   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11444     {
11445       if (unformat (i, "name %s", &host_if_name))
11446         vec_add1 (host_if_name, 0);
11447       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
11448         random_hw_addr = 0;
11449       else
11450         break;
11451     }
11452
11453   if (!vec_len (host_if_name))
11454     {
11455       errmsg ("host-interface name must be specified");
11456       return -99;
11457     }
11458
11459   if (vec_len (host_if_name) > 64)
11460     {
11461       errmsg ("host-interface name too long");
11462       return -99;
11463     }
11464
11465   M (AF_PACKET_CREATE, mp);
11466
11467   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11468   clib_memcpy (mp->hw_addr, hw_addr, 6);
11469   mp->use_random_hw_addr = random_hw_addr;
11470   vec_free (host_if_name);
11471
11472   S (mp);
11473
11474   /* *INDENT-OFF* */
11475   W2 (ret,
11476       ({
11477         if (ret == 0)
11478           fprintf (vam->ofp ? vam->ofp : stderr,
11479                    " new sw_if_index = %d\n", vam->sw_if_index);
11480       }));
11481   /* *INDENT-ON* */
11482   return ret;
11483 }
11484
11485 static int
11486 api_af_packet_delete (vat_main_t * vam)
11487 {
11488   unformat_input_t *i = vam->input;
11489   vl_api_af_packet_delete_t *mp;
11490   u8 *host_if_name = 0;
11491   int ret;
11492
11493   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11494     {
11495       if (unformat (i, "name %s", &host_if_name))
11496         vec_add1 (host_if_name, 0);
11497       else
11498         break;
11499     }
11500
11501   if (!vec_len (host_if_name))
11502     {
11503       errmsg ("host-interface name must be specified");
11504       return -99;
11505     }
11506
11507   if (vec_len (host_if_name) > 64)
11508     {
11509       errmsg ("host-interface name too long");
11510       return -99;
11511     }
11512
11513   M (AF_PACKET_DELETE, mp);
11514
11515   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
11516   vec_free (host_if_name);
11517
11518   S (mp);
11519   W (ret);
11520   return ret;
11521 }
11522
11523 static void vl_api_af_packet_details_t_handler
11524   (vl_api_af_packet_details_t * mp)
11525 {
11526   vat_main_t *vam = &vat_main;
11527
11528   print (vam->ofp, "%-16s %d",
11529          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
11530 }
11531
11532 static void vl_api_af_packet_details_t_handler_json
11533   (vl_api_af_packet_details_t * mp)
11534 {
11535   vat_main_t *vam = &vat_main;
11536   vat_json_node_t *node = NULL;
11537
11538   if (VAT_JSON_ARRAY != vam->json_tree.type)
11539     {
11540       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11541       vat_json_init_array (&vam->json_tree);
11542     }
11543   node = vat_json_array_add (&vam->json_tree);
11544
11545   vat_json_init_object (node);
11546   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
11547   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
11548 }
11549
11550 static int
11551 api_af_packet_dump (vat_main_t * vam)
11552 {
11553   vl_api_af_packet_dump_t *mp;
11554   vl_api_control_ping_t *mp_ping;
11555   int ret;
11556
11557   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
11558   /* Get list of tap interfaces */
11559   M (AF_PACKET_DUMP, mp);
11560   S (mp);
11561
11562   /* Use a control ping for synchronization */
11563   MPING (CONTROL_PING, mp_ping);
11564   S (mp_ping);
11565
11566   W (ret);
11567   return ret;
11568 }
11569
11570 static int
11571 api_policer_add_del (vat_main_t * vam)
11572 {
11573   unformat_input_t *i = vam->input;
11574   vl_api_policer_add_del_t *mp;
11575   u8 is_add = 1;
11576   u8 *name = 0;
11577   u32 cir = 0;
11578   u32 eir = 0;
11579   u64 cb = 0;
11580   u64 eb = 0;
11581   u8 rate_type = 0;
11582   u8 round_type = 0;
11583   u8 type = 0;
11584   u8 color_aware = 0;
11585   sse2_qos_pol_action_params_st conform_action, exceed_action, violate_action;
11586   int ret;
11587
11588   conform_action.action_type = SSE2_QOS_ACTION_TRANSMIT;
11589   conform_action.dscp = 0;
11590   exceed_action.action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
11591   exceed_action.dscp = 0;
11592   violate_action.action_type = SSE2_QOS_ACTION_DROP;
11593   violate_action.dscp = 0;
11594
11595   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11596     {
11597       if (unformat (i, "del"))
11598         is_add = 0;
11599       else if (unformat (i, "name %s", &name))
11600         vec_add1 (name, 0);
11601       else if (unformat (i, "cir %u", &cir))
11602         ;
11603       else if (unformat (i, "eir %u", &eir))
11604         ;
11605       else if (unformat (i, "cb %u", &cb))
11606         ;
11607       else if (unformat (i, "eb %u", &eb))
11608         ;
11609       else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
11610                          &rate_type))
11611         ;
11612       else if (unformat (i, "round_type %U", unformat_policer_round_type,
11613                          &round_type))
11614         ;
11615       else if (unformat (i, "type %U", unformat_policer_type, &type))
11616         ;
11617       else if (unformat (i, "conform_action %U", unformat_policer_action_type,
11618                          &conform_action))
11619         ;
11620       else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
11621                          &exceed_action))
11622         ;
11623       else if (unformat (i, "violate_action %U", unformat_policer_action_type,
11624                          &violate_action))
11625         ;
11626       else if (unformat (i, "color-aware"))
11627         color_aware = 1;
11628       else
11629         break;
11630     }
11631
11632   if (!vec_len (name))
11633     {
11634       errmsg ("policer name must be specified");
11635       return -99;
11636     }
11637
11638   if (vec_len (name) > 64)
11639     {
11640       errmsg ("policer name too long");
11641       return -99;
11642     }
11643
11644   M (POLICER_ADD_DEL, mp);
11645
11646   clib_memcpy (mp->name, name, vec_len (name));
11647   vec_free (name);
11648   mp->is_add = is_add;
11649   mp->cir = ntohl (cir);
11650   mp->eir = ntohl (eir);
11651   mp->cb = clib_net_to_host_u64 (cb);
11652   mp->eb = clib_net_to_host_u64 (eb);
11653   mp->rate_type = rate_type;
11654   mp->round_type = round_type;
11655   mp->type = type;
11656   mp->conform_action.type = conform_action.action_type;
11657   mp->conform_action.dscp = conform_action.dscp;
11658   mp->exceed_action.type = exceed_action.action_type;
11659   mp->exceed_action.dscp = exceed_action.dscp;
11660   mp->violate_action.type = violate_action.action_type;
11661   mp->violate_action.dscp = violate_action.dscp;
11662   mp->color_aware = color_aware;
11663
11664   S (mp);
11665   W (ret);
11666   return ret;
11667 }
11668
11669 static int
11670 api_policer_dump (vat_main_t * vam)
11671 {
11672   unformat_input_t *i = vam->input;
11673   vl_api_policer_dump_t *mp;
11674   vl_api_control_ping_t *mp_ping;
11675   u8 *match_name = 0;
11676   u8 match_name_valid = 0;
11677   int ret;
11678
11679   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11680     {
11681       if (unformat (i, "name %s", &match_name))
11682         {
11683           vec_add1 (match_name, 0);
11684           match_name_valid = 1;
11685         }
11686       else
11687         break;
11688     }
11689
11690   M (POLICER_DUMP, mp);
11691   mp->match_name_valid = match_name_valid;
11692   clib_memcpy (mp->match_name, match_name, vec_len (match_name));
11693   vec_free (match_name);
11694   /* send it... */
11695   S (mp);
11696
11697   /* Use a control ping for synchronization */
11698   MPING (CONTROL_PING, mp_ping);
11699   S (mp_ping);
11700
11701   /* Wait for a reply... */
11702   W (ret);
11703   return ret;
11704 }
11705
11706 static int
11707 api_policer_classify_set_interface (vat_main_t * vam)
11708 {
11709   unformat_input_t *i = vam->input;
11710   vl_api_policer_classify_set_interface_t *mp;
11711   u32 sw_if_index;
11712   int sw_if_index_set;
11713   u32 ip4_table_index = ~0;
11714   u32 ip6_table_index = ~0;
11715   u32 l2_table_index = ~0;
11716   u8 is_add = 1;
11717   int ret;
11718
11719   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11720     {
11721       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11722         sw_if_index_set = 1;
11723       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11724         sw_if_index_set = 1;
11725       else if (unformat (i, "del"))
11726         is_add = 0;
11727       else if (unformat (i, "ip4-table %d", &ip4_table_index))
11728         ;
11729       else if (unformat (i, "ip6-table %d", &ip6_table_index))
11730         ;
11731       else if (unformat (i, "l2-table %d", &l2_table_index))
11732         ;
11733       else
11734         {
11735           clib_warning ("parse error '%U'", format_unformat_error, i);
11736           return -99;
11737         }
11738     }
11739
11740   if (sw_if_index_set == 0)
11741     {
11742       errmsg ("missing interface name or sw_if_index");
11743       return -99;
11744     }
11745
11746   M (POLICER_CLASSIFY_SET_INTERFACE, mp);
11747
11748   mp->sw_if_index = ntohl (sw_if_index);
11749   mp->ip4_table_index = ntohl (ip4_table_index);
11750   mp->ip6_table_index = ntohl (ip6_table_index);
11751   mp->l2_table_index = ntohl (l2_table_index);
11752   mp->is_add = is_add;
11753
11754   S (mp);
11755   W (ret);
11756   return ret;
11757 }
11758
11759 static int
11760 api_policer_classify_dump (vat_main_t * vam)
11761 {
11762   unformat_input_t *i = vam->input;
11763   vl_api_policer_classify_dump_t *mp;
11764   vl_api_control_ping_t *mp_ping;
11765   u8 type = POLICER_CLASSIFY_N_TABLES;
11766   int ret;
11767
11768   if (unformat (i, "type %U", unformat_policer_classify_table_type, &type))
11769     ;
11770   else
11771     {
11772       errmsg ("classify table type must be specified");
11773       return -99;
11774     }
11775
11776   if (!vam->json_output)
11777     {
11778       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
11779     }
11780
11781   M (POLICER_CLASSIFY_DUMP, mp);
11782   mp->type = type;
11783   /* send it... */
11784   S (mp);
11785
11786   /* Use a control ping for synchronization */
11787   MPING (CONTROL_PING, mp_ping);
11788   S (mp_ping);
11789
11790   /* Wait for a reply... */
11791   W (ret);
11792   return ret;
11793 }
11794
11795 static u8 *
11796 format_fib_api_path_nh_proto (u8 * s, va_list * args)
11797 {
11798   vl_api_fib_path_nh_proto_t proto =
11799     va_arg (*args, vl_api_fib_path_nh_proto_t);
11800
11801   switch (proto)
11802     {
11803     case FIB_API_PATH_NH_PROTO_IP4:
11804       s = format (s, "ip4");
11805       break;
11806     case FIB_API_PATH_NH_PROTO_IP6:
11807       s = format (s, "ip6");
11808       break;
11809     case FIB_API_PATH_NH_PROTO_MPLS:
11810       s = format (s, "mpls");
11811       break;
11812     case FIB_API_PATH_NH_PROTO_BIER:
11813       s = format (s, "bier");
11814       break;
11815     case FIB_API_PATH_NH_PROTO_ETHERNET:
11816       s = format (s, "ethernet");
11817       break;
11818     }
11819
11820   return (s);
11821 }
11822
11823 static u8 *
11824 format_vl_api_ip_address_union (u8 * s, va_list * args)
11825 {
11826   vl_api_address_family_t af = va_arg (*args, int);
11827   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
11828
11829   switch (af)
11830     {
11831     case ADDRESS_IP4:
11832       s = format (s, "%U", format_ip4_address, u->ip4);
11833       break;
11834     case ADDRESS_IP6:
11835       s = format (s, "%U", format_ip6_address, u->ip6);
11836       break;
11837     }
11838   return (s);
11839 }
11840
11841 static u8 *
11842 format_vl_api_fib_path_type (u8 * s, va_list * args)
11843 {
11844   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
11845
11846   switch (t)
11847     {
11848     case FIB_API_PATH_TYPE_NORMAL:
11849       s = format (s, "normal");
11850       break;
11851     case FIB_API_PATH_TYPE_LOCAL:
11852       s = format (s, "local");
11853       break;
11854     case FIB_API_PATH_TYPE_DROP:
11855       s = format (s, "drop");
11856       break;
11857     case FIB_API_PATH_TYPE_UDP_ENCAP:
11858       s = format (s, "udp-encap");
11859       break;
11860     case FIB_API_PATH_TYPE_BIER_IMP:
11861       s = format (s, "bier-imp");
11862       break;
11863     case FIB_API_PATH_TYPE_ICMP_UNREACH:
11864       s = format (s, "unreach");
11865       break;
11866     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
11867       s = format (s, "prohibit");
11868       break;
11869     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
11870       s = format (s, "src-lookup");
11871       break;
11872     case FIB_API_PATH_TYPE_DVR:
11873       s = format (s, "dvr");
11874       break;
11875     case FIB_API_PATH_TYPE_INTERFACE_RX:
11876       s = format (s, "interface-rx");
11877       break;
11878     case FIB_API_PATH_TYPE_CLASSIFY:
11879       s = format (s, "classify");
11880       break;
11881     }
11882
11883   return (s);
11884 }
11885
11886 static void
11887 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
11888 {
11889   print (vam->ofp,
11890          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
11891          ntohl (fp->weight), ntohl (fp->sw_if_index),
11892          format_vl_api_fib_path_type, fp->type,
11893          format_fib_api_path_nh_proto, fp->proto,
11894          format_vl_api_ip_address_union, &fp->nh.address);
11895 }
11896
11897 static void
11898 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
11899                                  vl_api_fib_path_t * fp)
11900 {
11901   struct in_addr ip4;
11902   struct in6_addr ip6;
11903
11904   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
11905   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
11906   vat_json_object_add_uint (node, "type", fp->type);
11907   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
11908   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
11909     {
11910       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
11911       vat_json_object_add_ip4 (node, "next_hop", ip4);
11912     }
11913   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
11914     {
11915       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
11916       vat_json_object_add_ip6 (node, "next_hop", ip6);
11917     }
11918 }
11919
11920 static void
11921 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
11922 {
11923   vat_main_t *vam = &vat_main;
11924   int count = ntohl (mp->mt_tunnel.mt_n_paths);
11925   vl_api_fib_path_t *fp;
11926   i32 i;
11927
11928   print (vam->ofp, "sw_if_index %d via:",
11929          ntohl (mp->mt_tunnel.mt_sw_if_index));
11930   fp = mp->mt_tunnel.mt_paths;
11931   for (i = 0; i < count; i++)
11932     {
11933       vl_api_fib_path_print (vam, fp);
11934       fp++;
11935     }
11936
11937   print (vam->ofp, "");
11938 }
11939
11940 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
11941 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
11942
11943 static void
11944 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
11945 {
11946   vat_main_t *vam = &vat_main;
11947   vat_json_node_t *node = NULL;
11948   int count = ntohl (mp->mt_tunnel.mt_n_paths);
11949   vl_api_fib_path_t *fp;
11950   i32 i;
11951
11952   if (VAT_JSON_ARRAY != vam->json_tree.type)
11953     {
11954       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11955       vat_json_init_array (&vam->json_tree);
11956     }
11957   node = vat_json_array_add (&vam->json_tree);
11958
11959   vat_json_init_object (node);
11960   vat_json_object_add_uint (node, "sw_if_index",
11961                             ntohl (mp->mt_tunnel.mt_sw_if_index));
11962
11963   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
11964
11965   fp = mp->mt_tunnel.mt_paths;
11966   for (i = 0; i < count; i++)
11967     {
11968       vl_api_mpls_fib_path_json_print (node, fp);
11969       fp++;
11970     }
11971 }
11972
11973 static int
11974 api_mpls_tunnel_dump (vat_main_t * vam)
11975 {
11976   vl_api_mpls_tunnel_dump_t *mp;
11977   vl_api_control_ping_t *mp_ping;
11978   int ret;
11979
11980   M (MPLS_TUNNEL_DUMP, mp);
11981
11982   S (mp);
11983
11984   /* Use a control ping for synchronization */
11985   MPING (CONTROL_PING, mp_ping);
11986   S (mp_ping);
11987
11988   W (ret);
11989   return ret;
11990 }
11991
11992 #define vl_api_mpls_table_details_t_endian vl_noop_handler
11993 #define vl_api_mpls_table_details_t_print vl_noop_handler
11994
11995
11996 static void
11997 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
11998 {
11999   vat_main_t *vam = &vat_main;
12000
12001   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
12002 }
12003
12004 static void vl_api_mpls_table_details_t_handler_json
12005   (vl_api_mpls_table_details_t * mp)
12006 {
12007   vat_main_t *vam = &vat_main;
12008   vat_json_node_t *node = NULL;
12009
12010   if (VAT_JSON_ARRAY != vam->json_tree.type)
12011     {
12012       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12013       vat_json_init_array (&vam->json_tree);
12014     }
12015   node = vat_json_array_add (&vam->json_tree);
12016
12017   vat_json_init_object (node);
12018   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
12019 }
12020
12021 static int
12022 api_mpls_table_dump (vat_main_t * vam)
12023 {
12024   vl_api_mpls_table_dump_t *mp;
12025   vl_api_control_ping_t *mp_ping;
12026   int ret;
12027
12028   M (MPLS_TABLE_DUMP, mp);
12029   S (mp);
12030
12031   /* Use a control ping for synchronization */
12032   MPING (CONTROL_PING, mp_ping);
12033   S (mp_ping);
12034
12035   W (ret);
12036   return ret;
12037 }
12038
12039 #define vl_api_mpls_route_details_t_endian vl_noop_handler
12040 #define vl_api_mpls_route_details_t_print vl_noop_handler
12041
12042 static void
12043 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
12044 {
12045   vat_main_t *vam = &vat_main;
12046   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
12047   vl_api_fib_path_t *fp;
12048   int i;
12049
12050   print (vam->ofp,
12051          "table-id %d, label %u, ess_bit %u",
12052          ntohl (mp->mr_route.mr_table_id),
12053          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
12054   fp = mp->mr_route.mr_paths;
12055   for (i = 0; i < count; i++)
12056     {
12057       vl_api_fib_path_print (vam, fp);
12058       fp++;
12059     }
12060 }
12061
12062 static void vl_api_mpls_route_details_t_handler_json
12063   (vl_api_mpls_route_details_t * mp)
12064 {
12065   vat_main_t *vam = &vat_main;
12066   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
12067   vat_json_node_t *node = NULL;
12068   vl_api_fib_path_t *fp;
12069   int i;
12070
12071   if (VAT_JSON_ARRAY != vam->json_tree.type)
12072     {
12073       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12074       vat_json_init_array (&vam->json_tree);
12075     }
12076   node = vat_json_array_add (&vam->json_tree);
12077
12078   vat_json_init_object (node);
12079   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
12080   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
12081   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
12082   vat_json_object_add_uint (node, "path_count", count);
12083   fp = mp->mr_route.mr_paths;
12084   for (i = 0; i < count; i++)
12085     {
12086       vl_api_mpls_fib_path_json_print (node, fp);
12087       fp++;
12088     }
12089 }
12090
12091 static int
12092 api_mpls_route_dump (vat_main_t * vam)
12093 {
12094   unformat_input_t *input = vam->input;
12095   vl_api_mpls_route_dump_t *mp;
12096   vl_api_control_ping_t *mp_ping;
12097   u32 table_id;
12098   int ret;
12099
12100   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12101     {
12102       if (unformat (input, "table_id %d", &table_id))
12103         ;
12104       else
12105         break;
12106     }
12107   if (table_id == ~0)
12108     {
12109       errmsg ("missing table id");
12110       return -99;
12111     }
12112
12113   M (MPLS_ROUTE_DUMP, mp);
12114
12115   mp->table.mt_table_id = ntohl (table_id);
12116   S (mp);
12117
12118   /* Use a control ping for synchronization */
12119   MPING (CONTROL_PING, mp_ping);
12120   S (mp_ping);
12121
12122   W (ret);
12123   return ret;
12124 }
12125
12126 #define vl_api_ip_table_details_t_endian vl_noop_handler
12127 #define vl_api_ip_table_details_t_print vl_noop_handler
12128
12129 static void
12130 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
12131 {
12132   vat_main_t *vam = &vat_main;
12133
12134   print (vam->ofp,
12135          "%s; table-id %d, prefix %U/%d",
12136          mp->table.name, ntohl (mp->table.table_id));
12137 }
12138
12139
12140 static void vl_api_ip_table_details_t_handler_json
12141   (vl_api_ip_table_details_t * mp)
12142 {
12143   vat_main_t *vam = &vat_main;
12144   vat_json_node_t *node = NULL;
12145
12146   if (VAT_JSON_ARRAY != vam->json_tree.type)
12147     {
12148       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12149       vat_json_init_array (&vam->json_tree);
12150     }
12151   node = vat_json_array_add (&vam->json_tree);
12152
12153   vat_json_init_object (node);
12154   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
12155 }
12156
12157 static int
12158 api_ip_table_dump (vat_main_t * vam)
12159 {
12160   vl_api_ip_table_dump_t *mp;
12161   vl_api_control_ping_t *mp_ping;
12162   int ret;
12163
12164   M (IP_TABLE_DUMP, mp);
12165   S (mp);
12166
12167   /* Use a control ping for synchronization */
12168   MPING (CONTROL_PING, mp_ping);
12169   S (mp_ping);
12170
12171   W (ret);
12172   return ret;
12173 }
12174
12175 static int
12176 api_ip_mtable_dump (vat_main_t * vam)
12177 {
12178   vl_api_ip_mtable_dump_t *mp;
12179   vl_api_control_ping_t *mp_ping;
12180   int ret;
12181
12182   M (IP_MTABLE_DUMP, mp);
12183   S (mp);
12184
12185   /* Use a control ping for synchronization */
12186   MPING (CONTROL_PING, mp_ping);
12187   S (mp_ping);
12188
12189   W (ret);
12190   return ret;
12191 }
12192
12193 static int
12194 api_ip_mroute_dump (vat_main_t * vam)
12195 {
12196   unformat_input_t *input = vam->input;
12197   vl_api_control_ping_t *mp_ping;
12198   vl_api_ip_mroute_dump_t *mp;
12199   int ret, is_ip6;
12200   u32 table_id;
12201
12202   is_ip6 = 0;
12203   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12204     {
12205       if (unformat (input, "table_id %d", &table_id))
12206         ;
12207       else if (unformat (input, "ip6"))
12208         is_ip6 = 1;
12209       else if (unformat (input, "ip4"))
12210         is_ip6 = 0;
12211       else
12212         break;
12213     }
12214   if (table_id == ~0)
12215     {
12216       errmsg ("missing table id");
12217       return -99;
12218     }
12219
12220   M (IP_MROUTE_DUMP, mp);
12221   mp->table.table_id = table_id;
12222   mp->table.is_ip6 = is_ip6;
12223   S (mp);
12224
12225   /* Use a control ping for synchronization */
12226   MPING (CONTROL_PING, mp_ping);
12227   S (mp_ping);
12228
12229   W (ret);
12230   return ret;
12231 }
12232
12233 #define vl_api_ip_route_details_t_endian vl_noop_handler
12234 #define vl_api_ip_route_details_t_print vl_noop_handler
12235
12236 static void
12237 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
12238 {
12239   vat_main_t *vam = &vat_main;
12240   u8 count = mp->route.n_paths;
12241   vl_api_fib_path_t *fp;
12242   int i;
12243
12244   print (vam->ofp,
12245          "table-id %d, prefix %U/%d",
12246          ntohl (mp->route.table_id),
12247          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
12248   for (i = 0; i < count; i++)
12249     {
12250       fp = &mp->route.paths[i];
12251
12252       vl_api_fib_path_print (vam, fp);
12253       fp++;
12254     }
12255 }
12256
12257 static void vl_api_ip_route_details_t_handler_json
12258   (vl_api_ip_route_details_t * mp)
12259 {
12260   vat_main_t *vam = &vat_main;
12261   u8 count = mp->route.n_paths;
12262   vat_json_node_t *node = NULL;
12263   struct in_addr ip4;
12264   struct in6_addr ip6;
12265   vl_api_fib_path_t *fp;
12266   int i;
12267
12268   if (VAT_JSON_ARRAY != vam->json_tree.type)
12269     {
12270       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12271       vat_json_init_array (&vam->json_tree);
12272     }
12273   node = vat_json_array_add (&vam->json_tree);
12274
12275   vat_json_init_object (node);
12276   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
12277   if (ADDRESS_IP6 == mp->route.prefix.address.af)
12278     {
12279       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
12280       vat_json_object_add_ip6 (node, "prefix", ip6);
12281     }
12282   else
12283     {
12284       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
12285       vat_json_object_add_ip4 (node, "prefix", ip4);
12286     }
12287   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
12288   vat_json_object_add_uint (node, "path_count", count);
12289   for (i = 0; i < count; i++)
12290     {
12291       fp = &mp->route.paths[i];
12292       vl_api_mpls_fib_path_json_print (node, fp);
12293     }
12294 }
12295
12296 static int
12297 api_ip_route_dump (vat_main_t * vam)
12298 {
12299   unformat_input_t *input = vam->input;
12300   vl_api_ip_route_dump_t *mp;
12301   vl_api_control_ping_t *mp_ping;
12302   u32 table_id;
12303   u8 is_ip6;
12304   int ret;
12305
12306   is_ip6 = 0;
12307   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12308     {
12309       if (unformat (input, "table_id %d", &table_id))
12310         ;
12311       else if (unformat (input, "ip6"))
12312         is_ip6 = 1;
12313       else if (unformat (input, "ip4"))
12314         is_ip6 = 0;
12315       else
12316         break;
12317     }
12318   if (table_id == ~0)
12319     {
12320       errmsg ("missing table id");
12321       return -99;
12322     }
12323
12324   M (IP_ROUTE_DUMP, mp);
12325
12326   mp->table.table_id = table_id;
12327   mp->table.is_ip6 = is_ip6;
12328
12329   S (mp);
12330
12331   /* Use a control ping for synchronization */
12332   MPING (CONTROL_PING, mp_ping);
12333   S (mp_ping);
12334
12335   W (ret);
12336   return ret;
12337 }
12338
12339 int
12340 api_classify_table_ids (vat_main_t * vam)
12341 {
12342   vl_api_classify_table_ids_t *mp;
12343   int ret;
12344
12345   /* Construct the API message */
12346   M (CLASSIFY_TABLE_IDS, mp);
12347   mp->context = 0;
12348
12349   S (mp);
12350   W (ret);
12351   return ret;
12352 }
12353
12354 int
12355 api_classify_table_by_interface (vat_main_t * vam)
12356 {
12357   unformat_input_t *input = vam->input;
12358   vl_api_classify_table_by_interface_t *mp;
12359
12360   u32 sw_if_index = ~0;
12361   int ret;
12362   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12363     {
12364       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
12365         ;
12366       else if (unformat (input, "sw_if_index %d", &sw_if_index))
12367         ;
12368       else
12369         break;
12370     }
12371   if (sw_if_index == ~0)
12372     {
12373       errmsg ("missing interface name or sw_if_index");
12374       return -99;
12375     }
12376
12377   /* Construct the API message */
12378   M (CLASSIFY_TABLE_BY_INTERFACE, mp);
12379   mp->context = 0;
12380   mp->sw_if_index = ntohl (sw_if_index);
12381
12382   S (mp);
12383   W (ret);
12384   return ret;
12385 }
12386
12387 int
12388 api_classify_table_info (vat_main_t * vam)
12389 {
12390   unformat_input_t *input = vam->input;
12391   vl_api_classify_table_info_t *mp;
12392
12393   u32 table_id = ~0;
12394   int ret;
12395   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12396     {
12397       if (unformat (input, "table_id %d", &table_id))
12398         ;
12399       else
12400         break;
12401     }
12402   if (table_id == ~0)
12403     {
12404       errmsg ("missing table id");
12405       return -99;
12406     }
12407
12408   /* Construct the API message */
12409   M (CLASSIFY_TABLE_INFO, mp);
12410   mp->context = 0;
12411   mp->table_id = ntohl (table_id);
12412
12413   S (mp);
12414   W (ret);
12415   return ret;
12416 }
12417
12418 int
12419 api_classify_session_dump (vat_main_t * vam)
12420 {
12421   unformat_input_t *input = vam->input;
12422   vl_api_classify_session_dump_t *mp;
12423   vl_api_control_ping_t *mp_ping;
12424
12425   u32 table_id = ~0;
12426   int ret;
12427   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12428     {
12429       if (unformat (input, "table_id %d", &table_id))
12430         ;
12431       else
12432         break;
12433     }
12434   if (table_id == ~0)
12435     {
12436       errmsg ("missing table id");
12437       return -99;
12438     }
12439
12440   /* Construct the API message */
12441   M (CLASSIFY_SESSION_DUMP, mp);
12442   mp->context = 0;
12443   mp->table_id = ntohl (table_id);
12444   S (mp);
12445
12446   /* Use a control ping for synchronization */
12447   MPING (CONTROL_PING, mp_ping);
12448   S (mp_ping);
12449
12450   W (ret);
12451   return ret;
12452 }
12453
12454 static void
12455 vl_api_ipfix_exporter_details_t_handler (vl_api_ipfix_exporter_details_t * mp)
12456 {
12457   vat_main_t *vam = &vat_main;
12458
12459   print (vam->ofp, "collector_address %U, collector_port %d, "
12460          "src_address %U, vrf_id %d, path_mtu %u, "
12461          "template_interval %u, udp_checksum %d",
12462          format_ip4_address, mp->collector_address,
12463          ntohs (mp->collector_port),
12464          format_ip4_address, mp->src_address,
12465          ntohl (mp->vrf_id), ntohl (mp->path_mtu),
12466          ntohl (mp->template_interval), mp->udp_checksum);
12467
12468   vam->retval = 0;
12469   vam->result_ready = 1;
12470 }
12471
12472 static void
12473   vl_api_ipfix_exporter_details_t_handler_json
12474   (vl_api_ipfix_exporter_details_t * mp)
12475 {
12476   vat_main_t *vam = &vat_main;
12477   vat_json_node_t node;
12478   struct in_addr collector_address;
12479   struct in_addr src_address;
12480
12481   vat_json_init_object (&node);
12482   clib_memcpy (&collector_address, &mp->collector_address,
12483                sizeof (collector_address));
12484   vat_json_object_add_ip4 (&node, "collector_address", collector_address);
12485   vat_json_object_add_uint (&node, "collector_port",
12486                             ntohs (mp->collector_port));
12487   clib_memcpy (&src_address, &mp->src_address, sizeof (src_address));
12488   vat_json_object_add_ip4 (&node, "src_address", src_address);
12489   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
12490   vat_json_object_add_uint (&node, "path_mtu", ntohl (mp->path_mtu));
12491   vat_json_object_add_uint (&node, "template_interval",
12492                             ntohl (mp->template_interval));
12493   vat_json_object_add_int (&node, "udp_checksum", mp->udp_checksum);
12494
12495   vat_json_print (vam->ofp, &node);
12496   vat_json_free (&node);
12497   vam->retval = 0;
12498   vam->result_ready = 1;
12499 }
12500
12501 int
12502 api_ipfix_exporter_dump (vat_main_t * vam)
12503 {
12504   vl_api_ipfix_exporter_dump_t *mp;
12505   int ret;
12506
12507   /* Construct the API message */
12508   M (IPFIX_EXPORTER_DUMP, mp);
12509   mp->context = 0;
12510
12511   S (mp);
12512   W (ret);
12513   return ret;
12514 }
12515
12516 static int
12517 api_ipfix_classify_stream_dump (vat_main_t * vam)
12518 {
12519   vl_api_ipfix_classify_stream_dump_t *mp;
12520   int ret;
12521
12522   /* Construct the API message */
12523   M (IPFIX_CLASSIFY_STREAM_DUMP, mp);
12524   mp->context = 0;
12525
12526   S (mp);
12527   W (ret);
12528   return ret;
12529   /* NOTREACHED */
12530   return 0;
12531 }
12532
12533 static void
12534   vl_api_ipfix_classify_stream_details_t_handler
12535   (vl_api_ipfix_classify_stream_details_t * mp)
12536 {
12537   vat_main_t *vam = &vat_main;
12538   print (vam->ofp, "domain_id %d, src_port %d",
12539          ntohl (mp->domain_id), ntohs (mp->src_port));
12540   vam->retval = 0;
12541   vam->result_ready = 1;
12542 }
12543
12544 static void
12545   vl_api_ipfix_classify_stream_details_t_handler_json
12546   (vl_api_ipfix_classify_stream_details_t * mp)
12547 {
12548   vat_main_t *vam = &vat_main;
12549   vat_json_node_t node;
12550
12551   vat_json_init_object (&node);
12552   vat_json_object_add_uint (&node, "domain_id", ntohl (mp->domain_id));
12553   vat_json_object_add_uint (&node, "src_port", ntohs (mp->src_port));
12554
12555   vat_json_print (vam->ofp, &node);
12556   vat_json_free (&node);
12557   vam->retval = 0;
12558   vam->result_ready = 1;
12559 }
12560
12561 static int
12562 api_ipfix_classify_table_dump (vat_main_t * vam)
12563 {
12564   vl_api_ipfix_classify_table_dump_t *mp;
12565   vl_api_control_ping_t *mp_ping;
12566   int ret;
12567
12568   if (!vam->json_output)
12569     {
12570       print (vam->ofp, "%15s%15s%20s", "table_id", "ip_version",
12571              "transport_protocol");
12572     }
12573
12574   /* Construct the API message */
12575   M (IPFIX_CLASSIFY_TABLE_DUMP, mp);
12576
12577   /* send it... */
12578   S (mp);
12579
12580   /* Use a control ping for synchronization */
12581   MPING (CONTROL_PING, mp_ping);
12582   S (mp_ping);
12583
12584   W (ret);
12585   return ret;
12586 }
12587
12588 static void
12589   vl_api_ipfix_classify_table_details_t_handler
12590   (vl_api_ipfix_classify_table_details_t * mp)
12591 {
12592   vat_main_t *vam = &vat_main;
12593   print (vam->ofp, "%15d%15d%20d", ntohl (mp->table_id), mp->ip_version,
12594          mp->transport_protocol);
12595 }
12596
12597 static void
12598   vl_api_ipfix_classify_table_details_t_handler_json
12599   (vl_api_ipfix_classify_table_details_t * mp)
12600 {
12601   vat_json_node_t *node = NULL;
12602   vat_main_t *vam = &vat_main;
12603
12604   if (VAT_JSON_ARRAY != vam->json_tree.type)
12605     {
12606       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12607       vat_json_init_array (&vam->json_tree);
12608     }
12609
12610   node = vat_json_array_add (&vam->json_tree);
12611   vat_json_init_object (node);
12612
12613   vat_json_object_add_uint (node, "table_id", ntohl (mp->table_id));
12614   vat_json_object_add_uint (node, "ip_version", mp->ip_version);
12615   vat_json_object_add_uint (node, "transport_protocol",
12616                             mp->transport_protocol);
12617 }
12618
12619 static int
12620 api_sw_interface_span_enable_disable (vat_main_t * vam)
12621 {
12622   unformat_input_t *i = vam->input;
12623   vl_api_sw_interface_span_enable_disable_t *mp;
12624   u32 src_sw_if_index = ~0;
12625   u32 dst_sw_if_index = ~0;
12626   u8 state = 3;
12627   int ret;
12628   u8 is_l2 = 0;
12629
12630   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12631     {
12632       if (unformat
12633           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
12634         ;
12635       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
12636         ;
12637       else
12638         if (unformat
12639             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
12640         ;
12641       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
12642         ;
12643       else if (unformat (i, "disable"))
12644         state = 0;
12645       else if (unformat (i, "rx"))
12646         state = 1;
12647       else if (unformat (i, "tx"))
12648         state = 2;
12649       else if (unformat (i, "both"))
12650         state = 3;
12651       else if (unformat (i, "l2"))
12652         is_l2 = 1;
12653       else
12654         break;
12655     }
12656
12657   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
12658
12659   mp->sw_if_index_from = htonl (src_sw_if_index);
12660   mp->sw_if_index_to = htonl (dst_sw_if_index);
12661   mp->state = state;
12662   mp->is_l2 = is_l2;
12663
12664   S (mp);
12665   W (ret);
12666   return ret;
12667 }
12668
12669 static void
12670 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
12671                                             * mp)
12672 {
12673   vat_main_t *vam = &vat_main;
12674   u8 *sw_if_from_name = 0;
12675   u8 *sw_if_to_name = 0;
12676   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12677   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12678   char *states[] = { "none", "rx", "tx", "both" };
12679   hash_pair_t *p;
12680
12681   /* *INDENT-OFF* */
12682   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12683   ({
12684     if ((u32) p->value[0] == sw_if_index_from)
12685       {
12686         sw_if_from_name = (u8 *)(p->key);
12687         if (sw_if_to_name)
12688           break;
12689       }
12690     if ((u32) p->value[0] == sw_if_index_to)
12691       {
12692         sw_if_to_name = (u8 *)(p->key);
12693         if (sw_if_from_name)
12694           break;
12695       }
12696   }));
12697   /* *INDENT-ON* */
12698   print (vam->ofp, "%20s => %20s (%s) %s",
12699          sw_if_from_name, sw_if_to_name, states[mp->state],
12700          mp->is_l2 ? "l2" : "device");
12701 }
12702
12703 static void
12704   vl_api_sw_interface_span_details_t_handler_json
12705   (vl_api_sw_interface_span_details_t * mp)
12706 {
12707   vat_main_t *vam = &vat_main;
12708   vat_json_node_t *node = NULL;
12709   u8 *sw_if_from_name = 0;
12710   u8 *sw_if_to_name = 0;
12711   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
12712   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
12713   hash_pair_t *p;
12714
12715   /* *INDENT-OFF* */
12716   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
12717   ({
12718     if ((u32) p->value[0] == sw_if_index_from)
12719       {
12720         sw_if_from_name = (u8 *)(p->key);
12721         if (sw_if_to_name)
12722           break;
12723       }
12724     if ((u32) p->value[0] == sw_if_index_to)
12725       {
12726         sw_if_to_name = (u8 *)(p->key);
12727         if (sw_if_from_name)
12728           break;
12729       }
12730   }));
12731   /* *INDENT-ON* */
12732
12733   if (VAT_JSON_ARRAY != vam->json_tree.type)
12734     {
12735       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12736       vat_json_init_array (&vam->json_tree);
12737     }
12738   node = vat_json_array_add (&vam->json_tree);
12739
12740   vat_json_init_object (node);
12741   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
12742   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
12743   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
12744   if (0 != sw_if_to_name)
12745     {
12746       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
12747     }
12748   vat_json_object_add_uint (node, "state", mp->state);
12749   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
12750 }
12751
12752 static int
12753 api_sw_interface_span_dump (vat_main_t * vam)
12754 {
12755   unformat_input_t *input = vam->input;
12756   vl_api_sw_interface_span_dump_t *mp;
12757   vl_api_control_ping_t *mp_ping;
12758   u8 is_l2 = 0;
12759   int ret;
12760
12761   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12762     {
12763       if (unformat (input, "l2"))
12764         is_l2 = 1;
12765       else
12766         break;
12767     }
12768
12769   M (SW_INTERFACE_SPAN_DUMP, mp);
12770   mp->is_l2 = is_l2;
12771   S (mp);
12772
12773   /* Use a control ping for synchronization */
12774   MPING (CONTROL_PING, mp_ping);
12775   S (mp_ping);
12776
12777   W (ret);
12778   return ret;
12779 }
12780
12781 int
12782 api_pg_create_interface (vat_main_t * vam)
12783 {
12784   unformat_input_t *input = vam->input;
12785   vl_api_pg_create_interface_t *mp;
12786
12787   u32 if_id = ~0, gso_size = 0;
12788   u8 gso_enabled = 0;
12789   int ret;
12790   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12791     {
12792       if (unformat (input, "if_id %d", &if_id))
12793         ;
12794       else if (unformat (input, "gso-enabled"))
12795         {
12796           gso_enabled = 1;
12797           if (unformat (input, "gso-size %u", &gso_size))
12798             ;
12799           else
12800             {
12801               errmsg ("missing gso-size");
12802               return -99;
12803             }
12804         }
12805       else
12806         break;
12807     }
12808   if (if_id == ~0)
12809     {
12810       errmsg ("missing pg interface index");
12811       return -99;
12812     }
12813
12814   /* Construct the API message */
12815   M (PG_CREATE_INTERFACE, mp);
12816   mp->context = 0;
12817   mp->interface_id = ntohl (if_id);
12818   mp->gso_enabled = gso_enabled;
12819
12820   S (mp);
12821   W (ret);
12822   return ret;
12823 }
12824
12825 int
12826 api_pg_capture (vat_main_t * vam)
12827 {
12828   unformat_input_t *input = vam->input;
12829   vl_api_pg_capture_t *mp;
12830
12831   u32 if_id = ~0;
12832   u8 enable = 1;
12833   u32 count = 1;
12834   u8 pcap_file_set = 0;
12835   u8 *pcap_file = 0;
12836   int ret;
12837   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12838     {
12839       if (unformat (input, "if_id %d", &if_id))
12840         ;
12841       else if (unformat (input, "pcap %s", &pcap_file))
12842         pcap_file_set = 1;
12843       else if (unformat (input, "count %d", &count))
12844         ;
12845       else if (unformat (input, "disable"))
12846         enable = 0;
12847       else
12848         break;
12849     }
12850   if (if_id == ~0)
12851     {
12852       errmsg ("missing pg interface index");
12853       return -99;
12854     }
12855   if (pcap_file_set > 0)
12856     {
12857       if (vec_len (pcap_file) > 255)
12858         {
12859           errmsg ("pcap file name is too long");
12860           return -99;
12861         }
12862     }
12863
12864   /* Construct the API message */
12865   M (PG_CAPTURE, mp);
12866   mp->context = 0;
12867   mp->interface_id = ntohl (if_id);
12868   mp->is_enabled = enable;
12869   mp->count = ntohl (count);
12870   if (pcap_file_set != 0)
12871     {
12872       vl_api_vec_to_api_string (pcap_file, &mp->pcap_file_name);
12873     }
12874   vec_free (pcap_file);
12875
12876   S (mp);
12877   W (ret);
12878   return ret;
12879 }
12880
12881 int
12882 api_pg_enable_disable (vat_main_t * vam)
12883 {
12884   unformat_input_t *input = vam->input;
12885   vl_api_pg_enable_disable_t *mp;
12886
12887   u8 enable = 1;
12888   u8 stream_name_set = 0;
12889   u8 *stream_name = 0;
12890   int ret;
12891   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12892     {
12893       if (unformat (input, "stream %s", &stream_name))
12894         stream_name_set = 1;
12895       else if (unformat (input, "disable"))
12896         enable = 0;
12897       else
12898         break;
12899     }
12900
12901   if (stream_name_set > 0)
12902     {
12903       if (vec_len (stream_name) > 255)
12904         {
12905           errmsg ("stream name too long");
12906           return -99;
12907         }
12908     }
12909
12910   /* Construct the API message */
12911   M (PG_ENABLE_DISABLE, mp);
12912   mp->context = 0;
12913   mp->is_enabled = enable;
12914   if (stream_name_set != 0)
12915     {
12916       vl_api_vec_to_api_string (stream_name, &mp->stream_name);
12917     }
12918   vec_free (stream_name);
12919
12920   S (mp);
12921   W (ret);
12922   return ret;
12923 }
12924
12925 int
12926 api_pg_interface_enable_disable_coalesce (vat_main_t * vam)
12927 {
12928   unformat_input_t *input = vam->input;
12929   vl_api_pg_interface_enable_disable_coalesce_t *mp;
12930
12931   u32 sw_if_index = ~0;
12932   u8 enable = 1;
12933   int ret;
12934   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12935     {
12936       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
12937         ;
12938       else if (unformat (input, "sw_if_index %d", &sw_if_index))
12939         ;
12940       else if (unformat (input, "disable"))
12941         enable = 0;
12942       else
12943         break;
12944     }
12945
12946   if (sw_if_index == ~0)
12947     {
12948       errmsg ("Interface required but not specified");
12949       return -99;
12950     }
12951
12952   /* Construct the API message */
12953   M (PG_INTERFACE_ENABLE_DISABLE_COALESCE, mp);
12954   mp->context = 0;
12955   mp->coalesce_enabled = enable;
12956   mp->sw_if_index = htonl (sw_if_index);
12957
12958   S (mp);
12959   W (ret);
12960   return ret;
12961 }
12962
12963 int
12964 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
12965 {
12966   unformat_input_t *input = vam->input;
12967   vl_api_ip_source_and_port_range_check_add_del_t *mp;
12968
12969   u16 *low_ports = 0;
12970   u16 *high_ports = 0;
12971   u16 this_low;
12972   u16 this_hi;
12973   vl_api_prefix_t prefix;
12974   u32 tmp, tmp2;
12975   u8 prefix_set = 0;
12976   u32 vrf_id = ~0;
12977   u8 is_add = 1;
12978   int ret;
12979
12980   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
12981     {
12982       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
12983         prefix_set = 1;
12984       else if (unformat (input, "vrf %d", &vrf_id))
12985         ;
12986       else if (unformat (input, "del"))
12987         is_add = 0;
12988       else if (unformat (input, "port %d", &tmp))
12989         {
12990           if (tmp == 0 || tmp > 65535)
12991             {
12992               errmsg ("port %d out of range", tmp);
12993               return -99;
12994             }
12995           this_low = tmp;
12996           this_hi = this_low + 1;
12997           vec_add1 (low_ports, this_low);
12998           vec_add1 (high_ports, this_hi);
12999         }
13000       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
13001         {
13002           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
13003             {
13004               errmsg ("incorrect range parameters");
13005               return -99;
13006             }
13007           this_low = tmp;
13008           /* Note: in debug CLI +1 is added to high before
13009              passing to real fn that does "the work"
13010              (ip_source_and_port_range_check_add_del).
13011              This fn is a wrapper around the binary API fn a
13012              control plane will call, which expects this increment
13013              to have occurred. Hence letting the binary API control
13014              plane fn do the increment for consistency between VAT
13015              and other control planes.
13016            */
13017           this_hi = tmp2;
13018           vec_add1 (low_ports, this_low);
13019           vec_add1 (high_ports, this_hi);
13020         }
13021       else
13022         break;
13023     }
13024
13025   if (prefix_set == 0)
13026     {
13027       errmsg ("<address>/<mask> not specified");
13028       return -99;
13029     }
13030
13031   if (vrf_id == ~0)
13032     {
13033       errmsg ("VRF ID required, not specified");
13034       return -99;
13035     }
13036
13037   if (vrf_id == 0)
13038     {
13039       errmsg
13040         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13041       return -99;
13042     }
13043
13044   if (vec_len (low_ports) == 0)
13045     {
13046       errmsg ("At least one port or port range required");
13047       return -99;
13048     }
13049
13050   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
13051
13052   mp->is_add = is_add;
13053
13054   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
13055
13056   mp->number_of_ranges = vec_len (low_ports);
13057
13058   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
13059   vec_free (low_ports);
13060
13061   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
13062   vec_free (high_ports);
13063
13064   mp->vrf_id = ntohl (vrf_id);
13065
13066   S (mp);
13067   W (ret);
13068   return ret;
13069 }
13070
13071 int
13072 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
13073 {
13074   unformat_input_t *input = vam->input;
13075   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
13076   u32 sw_if_index = ~0;
13077   int vrf_set = 0;
13078   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
13079   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
13080   u8 is_add = 1;
13081   int ret;
13082
13083   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13084     {
13085       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13086         ;
13087       else if (unformat (input, "sw_if_index %d", &sw_if_index))
13088         ;
13089       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
13090         vrf_set = 1;
13091       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
13092         vrf_set = 1;
13093       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
13094         vrf_set = 1;
13095       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
13096         vrf_set = 1;
13097       else if (unformat (input, "del"))
13098         is_add = 0;
13099       else
13100         break;
13101     }
13102
13103   if (sw_if_index == ~0)
13104     {
13105       errmsg ("Interface required but not specified");
13106       return -99;
13107     }
13108
13109   if (vrf_set == 0)
13110     {
13111       errmsg ("VRF ID required but not specified");
13112       return -99;
13113     }
13114
13115   if (tcp_out_vrf_id == 0
13116       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
13117     {
13118       errmsg
13119         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
13120       return -99;
13121     }
13122
13123   /* Construct the API message */
13124   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
13125
13126   mp->sw_if_index = ntohl (sw_if_index);
13127   mp->is_add = is_add;
13128   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
13129   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
13130   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
13131   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
13132
13133   /* send it... */
13134   S (mp);
13135
13136   /* Wait for a reply... */
13137   W (ret);
13138   return ret;
13139 }
13140
13141 static int
13142 api_set_punt (vat_main_t * vam)
13143 {
13144   unformat_input_t *i = vam->input;
13145   vl_api_address_family_t af;
13146   vl_api_set_punt_t *mp;
13147   u32 protocol = ~0;
13148   u32 port = ~0;
13149   int is_add = 1;
13150   int ret;
13151
13152   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13153     {
13154       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
13155         ;
13156       else if (unformat (i, "protocol %d", &protocol))
13157         ;
13158       else if (unformat (i, "port %d", &port))
13159         ;
13160       else if (unformat (i, "del"))
13161         is_add = 0;
13162       else
13163         {
13164           clib_warning ("parse error '%U'", format_unformat_error, i);
13165           return -99;
13166         }
13167     }
13168
13169   M (SET_PUNT, mp);
13170
13171   mp->is_add = (u8) is_add;
13172   mp->punt.type = PUNT_API_TYPE_L4;
13173   mp->punt.punt.l4.af = af;
13174   mp->punt.punt.l4.protocol = (u8) protocol;
13175   mp->punt.punt.l4.port = htons ((u16) port);
13176
13177   S (mp);
13178   W (ret);
13179   return ret;
13180 }
13181
13182 static int
13183 api_delete_subif (vat_main_t * vam)
13184 {
13185   unformat_input_t *i = vam->input;
13186   vl_api_delete_subif_t *mp;
13187   u32 sw_if_index = ~0;
13188   int ret;
13189
13190   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13191     {
13192       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13193         ;
13194       if (unformat (i, "sw_if_index %d", &sw_if_index))
13195         ;
13196       else
13197         break;
13198     }
13199
13200   if (sw_if_index == ~0)
13201     {
13202       errmsg ("missing sw_if_index");
13203       return -99;
13204     }
13205
13206   /* Construct the API message */
13207   M (DELETE_SUBIF, mp);
13208   mp->sw_if_index = ntohl (sw_if_index);
13209
13210   S (mp);
13211   W (ret);
13212   return ret;
13213 }
13214
13215 #define foreach_pbb_vtr_op      \
13216 _("disable",  L2_VTR_DISABLED)  \
13217 _("pop",  L2_VTR_POP_2)         \
13218 _("push",  L2_VTR_PUSH_2)
13219
13220 static int
13221 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
13222 {
13223   unformat_input_t *i = vam->input;
13224   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
13225   u32 sw_if_index = ~0, vtr_op = ~0;
13226   u16 outer_tag = ~0;
13227   u8 dmac[6], smac[6];
13228   u8 dmac_set = 0, smac_set = 0;
13229   u16 vlanid = 0;
13230   u32 sid = ~0;
13231   u32 tmp;
13232   int ret;
13233
13234   /* Shut up coverity */
13235   clib_memset (dmac, 0, sizeof (dmac));
13236   clib_memset (smac, 0, sizeof (smac));
13237
13238   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13239     {
13240       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13241         ;
13242       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13243         ;
13244       else if (unformat (i, "vtr_op %d", &vtr_op))
13245         ;
13246 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
13247       foreach_pbb_vtr_op
13248 #undef _
13249         else if (unformat (i, "translate_pbb_stag"))
13250         {
13251           if (unformat (i, "%d", &tmp))
13252             {
13253               vtr_op = L2_VTR_TRANSLATE_2_1;
13254               outer_tag = tmp;
13255             }
13256           else
13257             {
13258               errmsg
13259                 ("translate_pbb_stag operation requires outer tag definition");
13260               return -99;
13261             }
13262         }
13263       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
13264         dmac_set++;
13265       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
13266         smac_set++;
13267       else if (unformat (i, "sid %d", &sid))
13268         ;
13269       else if (unformat (i, "vlanid %d", &tmp))
13270         vlanid = tmp;
13271       else
13272         {
13273           clib_warning ("parse error '%U'", format_unformat_error, i);
13274           return -99;
13275         }
13276     }
13277
13278   if ((sw_if_index == ~0) || (vtr_op == ~0))
13279     {
13280       errmsg ("missing sw_if_index or vtr operation");
13281       return -99;
13282     }
13283   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
13284       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
13285     {
13286       errmsg
13287         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
13288       return -99;
13289     }
13290
13291   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
13292   mp->sw_if_index = ntohl (sw_if_index);
13293   mp->vtr_op = ntohl (vtr_op);
13294   mp->outer_tag = ntohs (outer_tag);
13295   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
13296   clib_memcpy (mp->b_smac, smac, sizeof (smac));
13297   mp->b_vlanid = ntohs (vlanid);
13298   mp->i_sid = ntohl (sid);
13299
13300   S (mp);
13301   W (ret);
13302   return ret;
13303 }
13304
13305 static int
13306 api_flow_classify_set_interface (vat_main_t * vam)
13307 {
13308   unformat_input_t *i = vam->input;
13309   vl_api_flow_classify_set_interface_t *mp;
13310   u32 sw_if_index;
13311   int sw_if_index_set;
13312   u32 ip4_table_index = ~0;
13313   u32 ip6_table_index = ~0;
13314   u8 is_add = 1;
13315   int ret;
13316
13317   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13318     {
13319       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13320         sw_if_index_set = 1;
13321       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13322         sw_if_index_set = 1;
13323       else if (unformat (i, "del"))
13324         is_add = 0;
13325       else if (unformat (i, "ip4-table %d", &ip4_table_index))
13326         ;
13327       else if (unformat (i, "ip6-table %d", &ip6_table_index))
13328         ;
13329       else
13330         {
13331           clib_warning ("parse error '%U'", format_unformat_error, i);
13332           return -99;
13333         }
13334     }
13335
13336   if (sw_if_index_set == 0)
13337     {
13338       errmsg ("missing interface name or sw_if_index");
13339       return -99;
13340     }
13341
13342   M (FLOW_CLASSIFY_SET_INTERFACE, mp);
13343
13344   mp->sw_if_index = ntohl (sw_if_index);
13345   mp->ip4_table_index = ntohl (ip4_table_index);
13346   mp->ip6_table_index = ntohl (ip6_table_index);
13347   mp->is_add = is_add;
13348
13349   S (mp);
13350   W (ret);
13351   return ret;
13352 }
13353
13354 static int
13355 api_flow_classify_dump (vat_main_t * vam)
13356 {
13357   unformat_input_t *i = vam->input;
13358   vl_api_flow_classify_dump_t *mp;
13359   vl_api_control_ping_t *mp_ping;
13360   u8 type = FLOW_CLASSIFY_N_TABLES;
13361   int ret;
13362
13363   if (unformat (i, "type %U", unformat_flow_classify_table_type, &type))
13364     ;
13365   else
13366     {
13367       errmsg ("classify table type must be specified");
13368       return -99;
13369     }
13370
13371   if (!vam->json_output)
13372     {
13373       print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table");
13374     }
13375
13376   M (FLOW_CLASSIFY_DUMP, mp);
13377   mp->type = type;
13378   /* send it... */
13379   S (mp);
13380
13381   /* Use a control ping for synchronization */
13382   MPING (CONTROL_PING, mp_ping);
13383   S (mp_ping);
13384
13385   /* Wait for a reply... */
13386   W (ret);
13387   return ret;
13388 }
13389
13390 static int
13391 api_feature_enable_disable (vat_main_t * vam)
13392 {
13393   unformat_input_t *i = vam->input;
13394   vl_api_feature_enable_disable_t *mp;
13395   u8 *arc_name = 0;
13396   u8 *feature_name = 0;
13397   u32 sw_if_index = ~0;
13398   u8 enable = 1;
13399   int ret;
13400
13401   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13402     {
13403       if (unformat (i, "arc_name %s", &arc_name))
13404         ;
13405       else if (unformat (i, "feature_name %s", &feature_name))
13406         ;
13407       else
13408         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13409         ;
13410       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13411         ;
13412       else if (unformat (i, "disable"))
13413         enable = 0;
13414       else
13415         break;
13416     }
13417
13418   if (arc_name == 0)
13419     {
13420       errmsg ("missing arc name");
13421       return -99;
13422     }
13423   if (vec_len (arc_name) > 63)
13424     {
13425       errmsg ("arc name too long");
13426     }
13427
13428   if (feature_name == 0)
13429     {
13430       errmsg ("missing feature name");
13431       return -99;
13432     }
13433   if (vec_len (feature_name) > 63)
13434     {
13435       errmsg ("feature name too long");
13436     }
13437
13438   if (sw_if_index == ~0)
13439     {
13440       errmsg ("missing interface name or sw_if_index");
13441       return -99;
13442     }
13443
13444   /* Construct the API message */
13445   M (FEATURE_ENABLE_DISABLE, mp);
13446   mp->sw_if_index = ntohl (sw_if_index);
13447   mp->enable = enable;
13448   clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
13449   clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
13450   vec_free (arc_name);
13451   vec_free (feature_name);
13452
13453   S (mp);
13454   W (ret);
13455   return ret;
13456 }
13457
13458 static int
13459 api_feature_gso_enable_disable (vat_main_t * vam)
13460 {
13461   unformat_input_t *i = vam->input;
13462   vl_api_feature_gso_enable_disable_t *mp;
13463   u32 sw_if_index = ~0;
13464   u8 enable = 1;
13465   int ret;
13466
13467   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13468     {
13469       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13470         ;
13471       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13472         ;
13473       else if (unformat (i, "enable"))
13474         enable = 1;
13475       else if (unformat (i, "disable"))
13476         enable = 0;
13477       else
13478         break;
13479     }
13480
13481   if (sw_if_index == ~0)
13482     {
13483       errmsg ("missing interface name or sw_if_index");
13484       return -99;
13485     }
13486
13487   /* Construct the API message */
13488   M (FEATURE_GSO_ENABLE_DISABLE, mp);
13489   mp->sw_if_index = ntohl (sw_if_index);
13490   mp->enable_disable = enable;
13491
13492   S (mp);
13493   W (ret);
13494   return ret;
13495 }
13496
13497 static int
13498 api_sw_interface_tag_add_del (vat_main_t * vam)
13499 {
13500   unformat_input_t *i = vam->input;
13501   vl_api_sw_interface_tag_add_del_t *mp;
13502   u32 sw_if_index = ~0;
13503   u8 *tag = 0;
13504   u8 enable = 1;
13505   int ret;
13506
13507   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13508     {
13509       if (unformat (i, "tag %s", &tag))
13510         ;
13511       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13512         ;
13513       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13514         ;
13515       else if (unformat (i, "del"))
13516         enable = 0;
13517       else
13518         break;
13519     }
13520
13521   if (sw_if_index == ~0)
13522     {
13523       errmsg ("missing interface name or sw_if_index");
13524       return -99;
13525     }
13526
13527   if (enable && (tag == 0))
13528     {
13529       errmsg ("no tag specified");
13530       return -99;
13531     }
13532
13533   /* Construct the API message */
13534   M (SW_INTERFACE_TAG_ADD_DEL, mp);
13535   mp->sw_if_index = ntohl (sw_if_index);
13536   mp->is_add = enable;
13537   if (enable)
13538     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
13539   vec_free (tag);
13540
13541   S (mp);
13542   W (ret);
13543   return ret;
13544 }
13545
13546 static int
13547 api_sw_interface_add_del_mac_address (vat_main_t * vam)
13548 {
13549   unformat_input_t *i = vam->input;
13550   vl_api_mac_address_t mac = { 0 };
13551   vl_api_sw_interface_add_del_mac_address_t *mp;
13552   u32 sw_if_index = ~0;
13553   u8 is_add = 1;
13554   u8 mac_set = 0;
13555   int ret;
13556
13557   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13558     {
13559       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13560         ;
13561       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13562         ;
13563       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
13564         mac_set++;
13565       else if (unformat (i, "del"))
13566         is_add = 0;
13567       else
13568         break;
13569     }
13570
13571   if (sw_if_index == ~0)
13572     {
13573       errmsg ("missing interface name or sw_if_index");
13574       return -99;
13575     }
13576
13577   if (!mac_set)
13578     {
13579       errmsg ("missing MAC address");
13580       return -99;
13581     }
13582
13583   /* Construct the API message */
13584   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
13585   mp->sw_if_index = ntohl (sw_if_index);
13586   mp->is_add = is_add;
13587   clib_memcpy (&mp->addr, &mac, sizeof (mac));
13588
13589   S (mp);
13590   W (ret);
13591   return ret;
13592 }
13593
13594 static void vl_api_l2_xconnect_details_t_handler
13595   (vl_api_l2_xconnect_details_t * mp)
13596 {
13597   vat_main_t *vam = &vat_main;
13598
13599   print (vam->ofp, "%15d%15d",
13600          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
13601 }
13602
13603 static void vl_api_l2_xconnect_details_t_handler_json
13604   (vl_api_l2_xconnect_details_t * mp)
13605 {
13606   vat_main_t *vam = &vat_main;
13607   vat_json_node_t *node = NULL;
13608
13609   if (VAT_JSON_ARRAY != vam->json_tree.type)
13610     {
13611       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
13612       vat_json_init_array (&vam->json_tree);
13613     }
13614   node = vat_json_array_add (&vam->json_tree);
13615
13616   vat_json_init_object (node);
13617   vat_json_object_add_uint (node, "rx_sw_if_index",
13618                             ntohl (mp->rx_sw_if_index));
13619   vat_json_object_add_uint (node, "tx_sw_if_index",
13620                             ntohl (mp->tx_sw_if_index));
13621 }
13622
13623 static int
13624 api_l2_xconnect_dump (vat_main_t * vam)
13625 {
13626   vl_api_l2_xconnect_dump_t *mp;
13627   vl_api_control_ping_t *mp_ping;
13628   int ret;
13629
13630   if (!vam->json_output)
13631     {
13632       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
13633     }
13634
13635   M (L2_XCONNECT_DUMP, mp);
13636
13637   S (mp);
13638
13639   /* Use a control ping for synchronization */
13640   MPING (CONTROL_PING, mp_ping);
13641   S (mp_ping);
13642
13643   W (ret);
13644   return ret;
13645 }
13646
13647 static int
13648 api_hw_interface_set_mtu (vat_main_t * vam)
13649 {
13650   unformat_input_t *i = vam->input;
13651   vl_api_hw_interface_set_mtu_t *mp;
13652   u32 sw_if_index = ~0;
13653   u32 mtu = 0;
13654   int ret;
13655
13656   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13657     {
13658       if (unformat (i, "mtu %d", &mtu))
13659         ;
13660       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
13661         ;
13662       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13663         ;
13664       else
13665         break;
13666     }
13667
13668   if (sw_if_index == ~0)
13669     {
13670       errmsg ("missing interface name or sw_if_index");
13671       return -99;
13672     }
13673
13674   if (mtu == 0)
13675     {
13676       errmsg ("no mtu specified");
13677       return -99;
13678     }
13679
13680   /* Construct the API message */
13681   M (HW_INTERFACE_SET_MTU, mp);
13682   mp->sw_if_index = ntohl (sw_if_index);
13683   mp->mtu = ntohs ((u16) mtu);
13684
13685   S (mp);
13686   W (ret);
13687   return ret;
13688 }
13689
13690 static int
13691 api_p2p_ethernet_add (vat_main_t * vam)
13692 {
13693   unformat_input_t *i = vam->input;
13694   vl_api_p2p_ethernet_add_t *mp;
13695   u32 parent_if_index = ~0;
13696   u32 sub_id = ~0;
13697   u8 remote_mac[6];
13698   u8 mac_set = 0;
13699   int ret;
13700
13701   clib_memset (remote_mac, 0, sizeof (remote_mac));
13702   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13703     {
13704       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
13705         ;
13706       else if (unformat (i, "sw_if_index %d", &parent_if_index))
13707         ;
13708       else
13709         if (unformat
13710             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
13711         mac_set++;
13712       else if (unformat (i, "sub_id %d", &sub_id))
13713         ;
13714       else
13715         {
13716           clib_warning ("parse error '%U'", format_unformat_error, i);
13717           return -99;
13718         }
13719     }
13720
13721   if (parent_if_index == ~0)
13722     {
13723       errmsg ("missing interface name or sw_if_index");
13724       return -99;
13725     }
13726   if (mac_set == 0)
13727     {
13728       errmsg ("missing remote mac address");
13729       return -99;
13730     }
13731   if (sub_id == ~0)
13732     {
13733       errmsg ("missing sub-interface id");
13734       return -99;
13735     }
13736
13737   M (P2P_ETHERNET_ADD, mp);
13738   mp->parent_if_index = ntohl (parent_if_index);
13739   mp->subif_id = ntohl (sub_id);
13740   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
13741
13742   S (mp);
13743   W (ret);
13744   return ret;
13745 }
13746
13747 static int
13748 api_p2p_ethernet_del (vat_main_t * vam)
13749 {
13750   unformat_input_t *i = vam->input;
13751   vl_api_p2p_ethernet_del_t *mp;
13752   u32 parent_if_index = ~0;
13753   u8 remote_mac[6];
13754   u8 mac_set = 0;
13755   int ret;
13756
13757   clib_memset (remote_mac, 0, sizeof (remote_mac));
13758   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13759     {
13760       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
13761         ;
13762       else if (unformat (i, "sw_if_index %d", &parent_if_index))
13763         ;
13764       else
13765         if (unformat
13766             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
13767         mac_set++;
13768       else
13769         {
13770           clib_warning ("parse error '%U'", format_unformat_error, i);
13771           return -99;
13772         }
13773     }
13774
13775   if (parent_if_index == ~0)
13776     {
13777       errmsg ("missing interface name or sw_if_index");
13778       return -99;
13779     }
13780   if (mac_set == 0)
13781     {
13782       errmsg ("missing remote mac address");
13783       return -99;
13784     }
13785
13786   M (P2P_ETHERNET_DEL, mp);
13787   mp->parent_if_index = ntohl (parent_if_index);
13788   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
13789
13790   S (mp);
13791   W (ret);
13792   return ret;
13793 }
13794
13795 static int
13796 api_tcp_configure_src_addresses (vat_main_t * vam)
13797 {
13798   vl_api_tcp_configure_src_addresses_t *mp;
13799   unformat_input_t *i = vam->input;
13800   vl_api_address_t first, last;
13801   u8 range_set = 0;
13802   u32 vrf_id = 0;
13803   int ret;
13804
13805   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13806     {
13807       if (unformat (i, "%U - %U",
13808                     unformat_vl_api_address, &first,
13809                     unformat_vl_api_address, &last))
13810         {
13811           if (range_set)
13812             {
13813               errmsg ("one range per message (range already set)");
13814               return -99;
13815             }
13816           range_set = 1;
13817         }
13818       else if (unformat (i, "vrf %d", &vrf_id))
13819         ;
13820       else
13821         break;
13822     }
13823
13824   if (range_set == 0)
13825     {
13826       errmsg ("address range not set");
13827       return -99;
13828     }
13829
13830   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
13831
13832   mp->vrf_id = ntohl (vrf_id);
13833   clib_memcpy (&mp->first_address, &first, sizeof (first));
13834   clib_memcpy (&mp->last_address, &last, sizeof (last));
13835
13836   S (mp);
13837   W (ret);
13838   return ret;
13839 }
13840
13841 static void vl_api_app_namespace_add_del_reply_t_handler
13842   (vl_api_app_namespace_add_del_reply_t * mp)
13843 {
13844   vat_main_t *vam = &vat_main;
13845   i32 retval = ntohl (mp->retval);
13846   if (vam->async_mode)
13847     {
13848       vam->async_errors += (retval < 0);
13849     }
13850   else
13851     {
13852       vam->retval = retval;
13853       if (retval == 0)
13854         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
13855       vam->result_ready = 1;
13856     }
13857 }
13858
13859 static void vl_api_app_namespace_add_del_reply_t_handler_json
13860   (vl_api_app_namespace_add_del_reply_t * mp)
13861 {
13862   vat_main_t *vam = &vat_main;
13863   vat_json_node_t node;
13864
13865   vat_json_init_object (&node);
13866   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
13867   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
13868
13869   vat_json_print (vam->ofp, &node);
13870   vat_json_free (&node);
13871
13872   vam->retval = ntohl (mp->retval);
13873   vam->result_ready = 1;
13874 }
13875
13876 static int
13877 api_app_namespace_add_del (vat_main_t * vam)
13878 {
13879   vl_api_app_namespace_add_del_t *mp;
13880   unformat_input_t *i = vam->input;
13881   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
13882   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
13883   u64 secret;
13884   int ret;
13885
13886   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13887     {
13888       if (unformat (i, "id %_%v%_", &ns_id))
13889         ;
13890       else if (unformat (i, "secret %lu", &secret))
13891         secret_set = 1;
13892       else if (unformat (i, "sw_if_index %d", &sw_if_index))
13893         sw_if_index_set = 1;
13894       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
13895         ;
13896       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
13897         ;
13898       else
13899         break;
13900     }
13901   if (!ns_id || !secret_set || !sw_if_index_set)
13902     {
13903       errmsg ("namespace id, secret and sw_if_index must be set");
13904       return -99;
13905     }
13906   if (vec_len (ns_id) > 64)
13907     {
13908       errmsg ("namespace id too long");
13909       return -99;
13910     }
13911   M (APP_NAMESPACE_ADD_DEL, mp);
13912
13913   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
13914   mp->secret = clib_host_to_net_u64 (secret);
13915   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
13916   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
13917   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
13918   vec_free (ns_id);
13919   S (mp);
13920   W (ret);
13921   return ret;
13922 }
13923
13924 static int
13925 api_sock_init_shm (vat_main_t * vam)
13926 {
13927 #if VPP_API_TEST_BUILTIN == 0
13928   unformat_input_t *i = vam->input;
13929   vl_api_shm_elem_config_t *config = 0;
13930   u64 size = 64 << 20;
13931   int rv;
13932
13933   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
13934     {
13935       if (unformat (i, "size %U", unformat_memory_size, &size))
13936         ;
13937       else
13938         break;
13939     }
13940
13941   /*
13942    * Canned custom ring allocator config.
13943    * Should probably parse all of this
13944    */
13945   vec_validate (config, 6);
13946   config[0].type = VL_API_VLIB_RING;
13947   config[0].size = 256;
13948   config[0].count = 32;
13949
13950   config[1].type = VL_API_VLIB_RING;
13951   config[1].size = 1024;
13952   config[1].count = 16;
13953
13954   config[2].type = VL_API_VLIB_RING;
13955   config[2].size = 4096;
13956   config[2].count = 2;
13957
13958   config[3].type = VL_API_CLIENT_RING;
13959   config[3].size = 256;
13960   config[3].count = 32;
13961
13962   config[4].type = VL_API_CLIENT_RING;
13963   config[4].size = 1024;
13964   config[4].count = 16;
13965
13966   config[5].type = VL_API_CLIENT_RING;
13967   config[5].size = 4096;
13968   config[5].count = 2;
13969
13970   config[6].type = VL_API_QUEUE;
13971   config[6].count = 128;
13972   config[6].size = sizeof (uword);
13973
13974   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
13975   if (!rv)
13976     vam->client_index_invalid = 1;
13977   return rv;
13978 #else
13979   return -99;
13980 #endif
13981 }
13982
13983 static void
13984 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
13985 {
13986   vat_main_t *vam = &vat_main;
13987   fib_prefix_t lcl, rmt;
13988
13989   ip_prefix_decode (&mp->lcl, &lcl);
13990   ip_prefix_decode (&mp->rmt, &rmt);
13991
13992   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
13993     {
13994       print (vam->ofp,
13995              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
13996              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
13997              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
13998              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
13999              &rmt.fp_addr.ip4, rmt.fp_len,
14000              clib_net_to_host_u16 (mp->rmt_port),
14001              clib_net_to_host_u32 (mp->action_index), mp->tag);
14002     }
14003   else
14004     {
14005       print (vam->ofp,
14006              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
14007              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
14008              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
14009              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
14010              &rmt.fp_addr.ip6, rmt.fp_len,
14011              clib_net_to_host_u16 (mp->rmt_port),
14012              clib_net_to_host_u32 (mp->action_index), mp->tag);
14013     }
14014 }
14015
14016 static void
14017 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
14018                                              mp)
14019 {
14020   vat_main_t *vam = &vat_main;
14021   vat_json_node_t *node = NULL;
14022   struct in6_addr ip6;
14023   struct in_addr ip4;
14024
14025   fib_prefix_t lcl, rmt;
14026
14027   ip_prefix_decode (&mp->lcl, &lcl);
14028   ip_prefix_decode (&mp->rmt, &rmt);
14029
14030   if (VAT_JSON_ARRAY != vam->json_tree.type)
14031     {
14032       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
14033       vat_json_init_array (&vam->json_tree);
14034     }
14035   node = vat_json_array_add (&vam->json_tree);
14036   vat_json_init_object (node);
14037
14038   vat_json_object_add_uint (node, "appns_index",
14039                             clib_net_to_host_u32 (mp->appns_index));
14040   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
14041   vat_json_object_add_uint (node, "scope", mp->scope);
14042   vat_json_object_add_uint (node, "action_index",
14043                             clib_net_to_host_u32 (mp->action_index));
14044   vat_json_object_add_uint (node, "lcl_port",
14045                             clib_net_to_host_u16 (mp->lcl_port));
14046   vat_json_object_add_uint (node, "rmt_port",
14047                             clib_net_to_host_u16 (mp->rmt_port));
14048   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
14049   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
14050   vat_json_object_add_string_copy (node, "tag", mp->tag);
14051   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
14052     {
14053       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
14054       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
14055       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
14056       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
14057     }
14058   else
14059     {
14060       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
14061       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
14062       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
14063       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
14064     }
14065 }
14066
14067 static int
14068 api_session_rule_add_del (vat_main_t * vam)
14069 {
14070   vl_api_session_rule_add_del_t *mp;
14071   unformat_input_t *i = vam->input;
14072   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
14073   u32 appns_index = 0, scope = 0;
14074   ip4_address_t lcl_ip4, rmt_ip4;
14075   ip6_address_t lcl_ip6, rmt_ip6;
14076   u8 is_ip4 = 1, conn_set = 0;
14077   u8 is_add = 1, *tag = 0;
14078   int ret;
14079   fib_prefix_t lcl, rmt;
14080
14081   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14082     {
14083       if (unformat (i, "del"))
14084         is_add = 0;
14085       else if (unformat (i, "add"))
14086         ;
14087       else if (unformat (i, "proto tcp"))
14088         proto = 0;
14089       else if (unformat (i, "proto udp"))
14090         proto = 1;
14091       else if (unformat (i, "appns %d", &appns_index))
14092         ;
14093       else if (unformat (i, "scope %d", &scope))
14094         ;
14095       else if (unformat (i, "tag %_%v%_", &tag))
14096         ;
14097       else
14098         if (unformat
14099             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
14100              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
14101              &rmt_port))
14102         {
14103           is_ip4 = 1;
14104           conn_set = 1;
14105         }
14106       else
14107         if (unformat
14108             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
14109              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
14110              &rmt_port))
14111         {
14112           is_ip4 = 0;
14113           conn_set = 1;
14114         }
14115       else if (unformat (i, "action %d", &action))
14116         ;
14117       else
14118         break;
14119     }
14120   if (proto == ~0 || !conn_set || action == ~0)
14121     {
14122       errmsg ("transport proto, connection and action must be set");
14123       return -99;
14124     }
14125
14126   if (scope > 3)
14127     {
14128       errmsg ("scope should be 0-3");
14129       return -99;
14130     }
14131
14132   M (SESSION_RULE_ADD_DEL, mp);
14133
14134   clib_memset (&lcl, 0, sizeof (lcl));
14135   clib_memset (&rmt, 0, sizeof (rmt));
14136   if (is_ip4)
14137     {
14138       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
14139       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
14140       lcl.fp_len = lcl_plen;
14141       rmt.fp_len = rmt_plen;
14142     }
14143   else
14144     {
14145       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
14146       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
14147       lcl.fp_len = lcl_plen;
14148       rmt.fp_len = rmt_plen;
14149     }
14150
14151
14152   ip_prefix_encode (&lcl, &mp->lcl);
14153   ip_prefix_encode (&rmt, &mp->rmt);
14154   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
14155   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
14156   mp->transport_proto =
14157     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
14158   mp->action_index = clib_host_to_net_u32 (action);
14159   mp->appns_index = clib_host_to_net_u32 (appns_index);
14160   mp->scope = scope;
14161   mp->is_add = is_add;
14162   if (tag)
14163     {
14164       clib_memcpy (mp->tag, tag, vec_len (tag));
14165       vec_free (tag);
14166     }
14167
14168   S (mp);
14169   W (ret);
14170   return ret;
14171 }
14172
14173 static int
14174 api_session_rules_dump (vat_main_t * vam)
14175 {
14176   vl_api_session_rules_dump_t *mp;
14177   vl_api_control_ping_t *mp_ping;
14178   int ret;
14179
14180   if (!vam->json_output)
14181     {
14182       print (vam->ofp, "%=20s", "Session Rules");
14183     }
14184
14185   M (SESSION_RULES_DUMP, mp);
14186   /* send it... */
14187   S (mp);
14188
14189   /* Use a control ping for synchronization */
14190   MPING (CONTROL_PING, mp_ping);
14191   S (mp_ping);
14192
14193   /* Wait for a reply... */
14194   W (ret);
14195   return ret;
14196 }
14197
14198 static int
14199 api_ip_container_proxy_add_del (vat_main_t * vam)
14200 {
14201   vl_api_ip_container_proxy_add_del_t *mp;
14202   unformat_input_t *i = vam->input;
14203   u32 sw_if_index = ~0;
14204   vl_api_prefix_t pfx = { };
14205   u8 is_add = 1;
14206   int ret;
14207
14208   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14209     {
14210       if (unformat (i, "del"))
14211         is_add = 0;
14212       else if (unformat (i, "add"))
14213         ;
14214       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
14215         ;
14216       else if (unformat (i, "sw_if_index %u", &sw_if_index))
14217         ;
14218       else
14219         break;
14220     }
14221   if (sw_if_index == ~0 || pfx.len == 0)
14222     {
14223       errmsg ("address and sw_if_index must be set");
14224       return -99;
14225     }
14226
14227   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
14228
14229   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
14230   mp->is_add = is_add;
14231   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
14232
14233   S (mp);
14234   W (ret);
14235   return ret;
14236 }
14237
14238 static int
14239 api_qos_record_enable_disable (vat_main_t * vam)
14240 {
14241   unformat_input_t *i = vam->input;
14242   vl_api_qos_record_enable_disable_t *mp;
14243   u32 sw_if_index, qs = 0xff;
14244   u8 sw_if_index_set = 0;
14245   u8 enable = 1;
14246   int ret;
14247
14248   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
14249     {
14250       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
14251         sw_if_index_set = 1;
14252       else if (unformat (i, "sw_if_index %d", &sw_if_index))
14253         sw_if_index_set = 1;
14254       else if (unformat (i, "%U", unformat_qos_source, &qs))
14255         ;
14256       else if (unformat (i, "disable"))
14257         enable = 0;
14258       else
14259         {
14260           clib_warning ("parse error '%U'", format_unformat_error, i);
14261           return -99;
14262         }
14263     }
14264
14265   if (sw_if_index_set == 0)
14266     {
14267       errmsg ("missing interface name or sw_if_index");
14268       return -99;
14269     }
14270   if (qs == 0xff)
14271     {
14272       errmsg ("input location must be specified");
14273       return -99;
14274     }
14275
14276   M (QOS_RECORD_ENABLE_DISABLE, mp);
14277
14278   mp->record.sw_if_index = ntohl (sw_if_index);
14279   mp->record.input_source = qs;
14280   mp->enable = enable;
14281
14282   S (mp);
14283   W (ret);
14284   return ret;
14285 }
14286
14287
14288 static int
14289 q_or_quit (vat_main_t * vam)
14290 {
14291 #if VPP_API_TEST_BUILTIN == 0
14292   longjmp (vam->jump_buf, 1);
14293 #endif
14294   return 0;                     /* not so much */
14295 }
14296
14297 static int
14298 q (vat_main_t * vam)
14299 {
14300   return q_or_quit (vam);
14301 }
14302
14303 static int
14304 quit (vat_main_t * vam)
14305 {
14306   return q_or_quit (vam);
14307 }
14308
14309 static int
14310 comment (vat_main_t * vam)
14311 {
14312   return 0;
14313 }
14314
14315 static int
14316 elog_save (vat_main_t * vam)
14317 {
14318 #if VPP_API_TEST_BUILTIN == 0
14319   elog_main_t *em = &vam->elog_main;
14320   unformat_input_t *i = vam->input;
14321   char *file, *chroot_file;
14322   clib_error_t *error;
14323
14324   if (!unformat (i, "%s", &file))
14325     {
14326       errmsg ("expected file name, got `%U'", format_unformat_error, i);
14327       return 0;
14328     }
14329
14330   /* It's fairly hard to get "../oopsie" through unformat; just in case */
14331   if (strstr (file, "..") || index (file, '/'))
14332     {
14333       errmsg ("illegal characters in filename '%s'", file);
14334       return 0;
14335     }
14336
14337   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
14338
14339   vec_free (file);
14340
14341   errmsg ("Saving %wd of %wd events to %s",
14342           elog_n_events_in_buffer (em),
14343           elog_buffer_capacity (em), chroot_file);
14344
14345   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
14346   vec_free (chroot_file);
14347
14348   if (error)
14349     clib_error_report (error);
14350 #else
14351   errmsg ("Use the vpp event loger...");
14352 #endif
14353
14354   return 0;
14355 }
14356
14357 static int
14358 elog_setup (vat_main_t * vam)
14359 {
14360 #if VPP_API_TEST_BUILTIN == 0
14361   elog_main_t *em = &vam->elog_main;
14362   unformat_input_t *i = vam->input;
14363   u32 nevents = 128 << 10;
14364
14365   (void) unformat (i, "nevents %d", &nevents);
14366
14367   elog_init (em, nevents);
14368   vl_api_set_elog_main (em);
14369   vl_api_set_elog_trace_api_messages (1);
14370   errmsg ("Event logger initialized with %u events", nevents);
14371 #else
14372   errmsg ("Use the vpp event loger...");
14373 #endif
14374   return 0;
14375 }
14376
14377 static int
14378 elog_enable (vat_main_t * vam)
14379 {
14380 #if VPP_API_TEST_BUILTIN == 0
14381   elog_main_t *em = &vam->elog_main;
14382
14383   elog_enable_disable (em, 1 /* enable */ );
14384   vl_api_set_elog_trace_api_messages (1);
14385   errmsg ("Event logger enabled...");
14386 #else
14387   errmsg ("Use the vpp event loger...");
14388 #endif
14389   return 0;
14390 }
14391
14392 static int
14393 elog_disable (vat_main_t * vam)
14394 {
14395 #if VPP_API_TEST_BUILTIN == 0
14396   elog_main_t *em = &vam->elog_main;
14397
14398   elog_enable_disable (em, 0 /* enable */ );
14399   vl_api_set_elog_trace_api_messages (1);
14400   errmsg ("Event logger disabled...");
14401 #else
14402   errmsg ("Use the vpp event loger...");
14403 #endif
14404   return 0;
14405 }
14406
14407 static int
14408 statseg (vat_main_t * vam)
14409 {
14410   ssvm_private_t *ssvmp = &vam->stat_segment;
14411   ssvm_shared_header_t *shared_header = ssvmp->sh;
14412   vlib_counter_t **counters;
14413   u64 thread0_index1_packets;
14414   u64 thread0_index1_bytes;
14415   f64 vector_rate, input_rate;
14416   uword *p;
14417
14418   uword *counter_vector_by_name;
14419   if (vam->stat_segment_lockp == 0)
14420     {
14421       errmsg ("Stat segment not mapped...");
14422       return -99;
14423     }
14424
14425   /* look up "/if/rx for sw_if_index 1 as a test */
14426
14427   clib_spinlock_lock (vam->stat_segment_lockp);
14428
14429   counter_vector_by_name = (uword *) shared_header->opaque[1];
14430
14431   p = hash_get_mem (counter_vector_by_name, "/if/rx");
14432   if (p == 0)
14433     {
14434       clib_spinlock_unlock (vam->stat_segment_lockp);
14435       errmsg ("/if/tx not found?");
14436       return -99;
14437     }
14438
14439   /* Fish per-thread vector of combined counters from shared memory */
14440   counters = (vlib_counter_t **) p[0];
14441
14442   if (vec_len (counters[0]) < 2)
14443     {
14444       clib_spinlock_unlock (vam->stat_segment_lockp);
14445       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
14446       return -99;
14447     }
14448
14449   /* Read thread 0 sw_if_index 1 counter */
14450   thread0_index1_packets = counters[0][1].packets;
14451   thread0_index1_bytes = counters[0][1].bytes;
14452
14453   p = hash_get_mem (counter_vector_by_name, "vector_rate");
14454   if (p == 0)
14455     {
14456       clib_spinlock_unlock (vam->stat_segment_lockp);
14457       errmsg ("vector_rate not found?");
14458       return -99;
14459     }
14460
14461   vector_rate = *(f64 *) (p[0]);
14462   p = hash_get_mem (counter_vector_by_name, "input_rate");
14463   if (p == 0)
14464     {
14465       clib_spinlock_unlock (vam->stat_segment_lockp);
14466       errmsg ("input_rate not found?");
14467       return -99;
14468     }
14469   input_rate = *(f64 *) (p[0]);
14470
14471   clib_spinlock_unlock (vam->stat_segment_lockp);
14472
14473   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
14474          vector_rate, input_rate);
14475   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
14476          thread0_index1_packets, thread0_index1_bytes);
14477
14478   return 0;
14479 }
14480
14481 static int
14482 cmd_cmp (void *a1, void *a2)
14483 {
14484   u8 **c1 = a1;
14485   u8 **c2 = a2;
14486
14487   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
14488 }
14489
14490 static int
14491 help (vat_main_t * vam)
14492 {
14493   u8 **cmds = 0;
14494   u8 *name = 0;
14495   hash_pair_t *p;
14496   unformat_input_t *i = vam->input;
14497   int j;
14498
14499   if (unformat (i, "%s", &name))
14500     {
14501       uword *hs;
14502
14503       vec_add1 (name, 0);
14504
14505       hs = hash_get_mem (vam->help_by_name, name);
14506       if (hs)
14507         print (vam->ofp, "usage: %s %s", name, hs[0]);
14508       else
14509         print (vam->ofp, "No such msg / command '%s'", name);
14510       vec_free (name);
14511       return 0;
14512     }
14513
14514   print (vam->ofp, "Help is available for the following:");
14515
14516     /* *INDENT-OFF* */
14517     hash_foreach_pair (p, vam->function_by_name,
14518     ({
14519       vec_add1 (cmds, (u8 *)(p->key));
14520     }));
14521     /* *INDENT-ON* */
14522
14523   vec_sort_with_function (cmds, cmd_cmp);
14524
14525   for (j = 0; j < vec_len (cmds); j++)
14526     print (vam->ofp, "%s", cmds[j]);
14527
14528   vec_free (cmds);
14529   return 0;
14530 }
14531
14532 static int
14533 set (vat_main_t * vam)
14534 {
14535   u8 *name = 0, *value = 0;
14536   unformat_input_t *i = vam->input;
14537
14538   if (unformat (i, "%s", &name))
14539     {
14540       /* The input buffer is a vector, not a string. */
14541       value = vec_dup (i->buffer);
14542       vec_delete (value, i->index, 0);
14543       /* Almost certainly has a trailing newline */
14544       if (value[vec_len (value) - 1] == '\n')
14545         value[vec_len (value) - 1] = 0;
14546       /* Make sure it's a proper string, one way or the other */
14547       vec_add1 (value, 0);
14548       (void) clib_macro_set_value (&vam->macro_main,
14549                                    (char *) name, (char *) value);
14550     }
14551   else
14552     errmsg ("usage: set <name> <value>");
14553
14554   vec_free (name);
14555   vec_free (value);
14556   return 0;
14557 }
14558
14559 static int
14560 unset (vat_main_t * vam)
14561 {
14562   u8 *name = 0;
14563
14564   if (unformat (vam->input, "%s", &name))
14565     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
14566       errmsg ("unset: %s wasn't set", name);
14567   vec_free (name);
14568   return 0;
14569 }
14570
14571 typedef struct
14572 {
14573   u8 *name;
14574   u8 *value;
14575 } macro_sort_t;
14576
14577
14578 static int
14579 macro_sort_cmp (void *a1, void *a2)
14580 {
14581   macro_sort_t *s1 = a1;
14582   macro_sort_t *s2 = a2;
14583
14584   return strcmp ((char *) (s1->name), (char *) (s2->name));
14585 }
14586
14587 static int
14588 dump_macro_table (vat_main_t * vam)
14589 {
14590   macro_sort_t *sort_me = 0, *sm;
14591   int i;
14592   hash_pair_t *p;
14593
14594     /* *INDENT-OFF* */
14595     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
14596     ({
14597       vec_add2 (sort_me, sm, 1);
14598       sm->name = (u8 *)(p->key);
14599       sm->value = (u8 *) (p->value[0]);
14600     }));
14601     /* *INDENT-ON* */
14602
14603   vec_sort_with_function (sort_me, macro_sort_cmp);
14604
14605   if (vec_len (sort_me))
14606     print (vam->ofp, "%-15s%s", "Name", "Value");
14607   else
14608     print (vam->ofp, "The macro table is empty...");
14609
14610   for (i = 0; i < vec_len (sort_me); i++)
14611     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
14612   return 0;
14613 }
14614
14615 static int
14616 dump_node_table (vat_main_t * vam)
14617 {
14618   int i, j;
14619   vlib_node_t *node, *next_node;
14620
14621   if (vec_len (vam->graph_nodes) == 0)
14622     {
14623       print (vam->ofp, "Node table empty, issue get_node_graph...");
14624       return 0;
14625     }
14626
14627   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
14628     {
14629       node = vam->graph_nodes[0][i];
14630       print (vam->ofp, "[%d] %s", i, node->name);
14631       for (j = 0; j < vec_len (node->next_nodes); j++)
14632         {
14633           if (node->next_nodes[j] != ~0)
14634             {
14635               next_node = vam->graph_nodes[0][node->next_nodes[j]];
14636               print (vam->ofp, "  [%d] %s", j, next_node->name);
14637             }
14638         }
14639     }
14640   return 0;
14641 }
14642
14643 static int
14644 value_sort_cmp (void *a1, void *a2)
14645 {
14646   name_sort_t *n1 = a1;
14647   name_sort_t *n2 = a2;
14648
14649   if (n1->value < n2->value)
14650     return -1;
14651   if (n1->value > n2->value)
14652     return 1;
14653   return 0;
14654 }
14655
14656
14657 static int
14658 dump_msg_api_table (vat_main_t * vam)
14659 {
14660   api_main_t *am = vlibapi_get_main ();
14661   name_sort_t *nses = 0, *ns;
14662   hash_pair_t *hp;
14663   int i;
14664
14665   /* *INDENT-OFF* */
14666   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
14667   ({
14668     vec_add2 (nses, ns, 1);
14669     ns->name = (u8 *)(hp->key);
14670     ns->value = (u32) hp->value[0];
14671   }));
14672   /* *INDENT-ON* */
14673
14674   vec_sort_with_function (nses, value_sort_cmp);
14675
14676   for (i = 0; i < vec_len (nses); i++)
14677     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
14678   vec_free (nses);
14679   return 0;
14680 }
14681
14682 static int
14683 get_msg_id (vat_main_t * vam)
14684 {
14685   u8 *name_and_crc;
14686   u32 message_index;
14687
14688   if (unformat (vam->input, "%s", &name_and_crc))
14689     {
14690       message_index = vl_msg_api_get_msg_index (name_and_crc);
14691       if (message_index == ~0)
14692         {
14693           print (vam->ofp, " '%s' not found", name_and_crc);
14694           return 0;
14695         }
14696       print (vam->ofp, " '%s' has message index %d",
14697              name_and_crc, message_index);
14698       return 0;
14699     }
14700   errmsg ("name_and_crc required...");
14701   return 0;
14702 }
14703
14704 static int
14705 search_node_table (vat_main_t * vam)
14706 {
14707   unformat_input_t *line_input = vam->input;
14708   u8 *node_to_find;
14709   int j;
14710   vlib_node_t *node, *next_node;
14711   uword *p;
14712
14713   if (vam->graph_node_index_by_name == 0)
14714     {
14715       print (vam->ofp, "Node table empty, issue get_node_graph...");
14716       return 0;
14717     }
14718
14719   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
14720     {
14721       if (unformat (line_input, "%s", &node_to_find))
14722         {
14723           vec_add1 (node_to_find, 0);
14724           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
14725           if (p == 0)
14726             {
14727               print (vam->ofp, "%s not found...", node_to_find);
14728               goto out;
14729             }
14730           node = vam->graph_nodes[0][p[0]];
14731           print (vam->ofp, "[%d] %s", p[0], node->name);
14732           for (j = 0; j < vec_len (node->next_nodes); j++)
14733             {
14734               if (node->next_nodes[j] != ~0)
14735                 {
14736                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
14737                   print (vam->ofp, "  [%d] %s", j, next_node->name);
14738                 }
14739             }
14740         }
14741
14742       else
14743         {
14744           clib_warning ("parse error '%U'", format_unformat_error,
14745                         line_input);
14746           return -99;
14747         }
14748
14749     out:
14750       vec_free (node_to_find);
14751
14752     }
14753
14754   return 0;
14755 }
14756
14757
14758 static int
14759 script (vat_main_t * vam)
14760 {
14761 #if (VPP_API_TEST_BUILTIN==0)
14762   u8 *s = 0;
14763   char *save_current_file;
14764   unformat_input_t save_input;
14765   jmp_buf save_jump_buf;
14766   u32 save_line_number;
14767
14768   FILE *new_fp, *save_ifp;
14769
14770   if (unformat (vam->input, "%s", &s))
14771     {
14772       new_fp = fopen ((char *) s, "r");
14773       if (new_fp == 0)
14774         {
14775           errmsg ("Couldn't open script file %s", s);
14776           vec_free (s);
14777           return -99;
14778         }
14779     }
14780   else
14781     {
14782       errmsg ("Missing script name");
14783       return -99;
14784     }
14785
14786   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
14787   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
14788   save_ifp = vam->ifp;
14789   save_line_number = vam->input_line_number;
14790   save_current_file = (char *) vam->current_file;
14791
14792   vam->input_line_number = 0;
14793   vam->ifp = new_fp;
14794   vam->current_file = s;
14795   do_one_file (vam);
14796
14797   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
14798   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
14799   vam->ifp = save_ifp;
14800   vam->input_line_number = save_line_number;
14801   vam->current_file = (u8 *) save_current_file;
14802   vec_free (s);
14803
14804   return 0;
14805 #else
14806   clib_warning ("use the exec command...");
14807   return -99;
14808 #endif
14809 }
14810
14811 static int
14812 echo (vat_main_t * vam)
14813 {
14814   print (vam->ofp, "%v", vam->input->buffer);
14815   return 0;
14816 }
14817
14818 /* List of API message constructors, CLI names map to api_xxx */
14819 #define foreach_vpe_api_msg                                             \
14820 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
14821 _(sw_interface_dump,"")                                                 \
14822 _(sw_interface_set_flags,                                               \
14823   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
14824 _(sw_interface_add_del_address,                                         \
14825   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
14826 _(sw_interface_set_rx_mode,                                             \
14827   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
14828 _(sw_interface_set_rx_placement,                                        \
14829   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
14830 _(sw_interface_rx_placement_dump,                                       \
14831   "[<intfc> | sw_if_index <id>]")                                         \
14832 _(sw_interface_set_table,                                               \
14833   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
14834 _(sw_interface_set_mpls_enable,                                         \
14835   "<intfc> | sw_if_index [disable | dis]")                              \
14836 _(sw_interface_set_vpath,                                               \
14837   "<intfc> | sw_if_index <id> enable | disable")                        \
14838 _(sw_interface_set_vxlan_bypass,                                        \
14839   "<intfc> | sw_if_index <id> [ip4 | ip6] [enable | disable]")          \
14840 _(sw_interface_set_l2_xconnect,                                         \
14841   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
14842   "enable | disable")                                                   \
14843 _(sw_interface_set_l2_bridge,                                           \
14844   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
14845   "[shg <split-horizon-group>] [bvi]\n"                                 \
14846   "enable | disable")                                                   \
14847 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
14848 _(bridge_domain_add_del,                                                \
14849   "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") \
14850 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
14851 _(l2fib_add_del,                                                        \
14852   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
14853 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
14854 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
14855 _(l2_flags,                                                             \
14856   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
14857 _(bridge_flags,                                                         \
14858   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
14859 _(tap_create_v2,                                                        \
14860   "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]") \
14861 _(tap_delete_v2,                                                        \
14862   "<vpp-if-name> | sw_if_index <id>")                                   \
14863 _(sw_interface_tap_v2_dump, "")                                         \
14864 _(virtio_pci_create_v2,                                                    \
14865   "pci-addr <pci-address> [use_random_mac | hw-addr <mac-addr>] [features <hex-value>] [gso-enabled [gro-coalesce] | csum-offload-enabled] [packed] [in-order] [buffering]") \
14866 _(virtio_pci_delete,                                                    \
14867   "<vpp-if-name> | sw_if_index <id>")                                   \
14868 _(sw_interface_virtio_pci_dump, "")                                     \
14869 _(bond_create,                                                          \
14870   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
14871   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
14872   "[id <if-id>]")                                                       \
14873 _(bond_create2,                                                         \
14874   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
14875   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
14876   "[id <if-id>] [gso]")                                                 \
14877 _(bond_delete,                                                          \
14878   "<vpp-if-name> | sw_if_index <id>")                                   \
14879 _(bond_add_member,                                                      \
14880   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
14881 _(bond_detach_member,                                                   \
14882   "sw_if_index <n>")                                                    \
14883  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
14884  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
14885  _(sw_member_interface_dump,                                            \
14886   "<vpp-if-name> | sw_if_index <id>")                                   \
14887 _(ip_table_add_del,                                                     \
14888   "table <n> [ipv6] [add | del]\n")                                     \
14889 _(ip_route_add_del,                                                     \
14890   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
14891   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
14892   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
14893   "[multipath] [count <n>] [del]")                                      \
14894 _(ip_mroute_add_del,                                                    \
14895   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
14896   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
14897 _(mpls_table_add_del,                                                   \
14898   "table <n> [add | del]\n")                                            \
14899 _(mpls_route_add_del,                                                   \
14900   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
14901   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
14902   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
14903   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
14904   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
14905   "[count <n>] [del]")                                                  \
14906 _(mpls_ip_bind_unbind,                                                  \
14907   "<label> <addr/len>")                                                 \
14908 _(mpls_tunnel_add_del,                                                  \
14909   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
14910   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
14911   "[l2-only]  [out-label <n>]")                                         \
14912 _(sr_mpls_policy_add,                                                   \
14913   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
14914 _(sr_mpls_policy_del,                                                   \
14915   "bsid <id>")                                                          \
14916 _(bier_table_add_del,                                                   \
14917   "<label> <sub-domain> <set> <bsl> [del]")                             \
14918 _(bier_route_add_del,                                                   \
14919   "<bit-position> <sub-domain> <set> <bsl> via <addr> [table-id <n>]\n" \
14920   "[<intfc> | sw_if_index <id>]"                                        \
14921   "[weight <n>] [del] [multipath]")                                     \
14922 _(sw_interface_set_unnumbered,                                          \
14923   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
14924 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
14925 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
14926   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
14927   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
14928   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
14929 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
14930 _(ip_table_flush, "table <n> [ipv6]")                                   \
14931 _(ip_table_replace_end, "table <n> [ipv6]")                             \
14932 _(set_ip_flow_hash,                                                     \
14933   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
14934 _(sw_interface_ip6_enable_disable,                                      \
14935   "<intfc> | sw_if_index <id> enable | disable")                        \
14936 _(l2_patch_add_del,                                                     \
14937   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
14938   "enable | disable")                                                   \
14939 _(sr_localsid_add_del,                                                  \
14940   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
14941   "fib-table <num> (end.psp) sw_if_index <num>")                        \
14942 _(classify_add_del_table,                                               \
14943   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
14944   " [del] [del-chain] mask <mask-value>\n"                              \
14945   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>\n"             \
14946   " [current-data-flag <n>] [current-data-offset <nn>] [table <nn>]")   \
14947 _(classify_add_del_session,                                             \
14948   "[hit-next|l2-hit-next|acl-hit-next|policer-hit-next] <name|nn>\n"    \
14949   "  table-index <nn> skip_n <nn> match_n <nn> match [hex] [l2]\n"      \
14950   "  [l3 [ip4|ip6]] [action set-ip4-fib-id <nn>]\n"                     \
14951   "  [action set-ip6-fib-id <nn> | action <n> metadata <nn>] [del]")    \
14952 _(classify_set_interface_ip_table,                                      \
14953   "<intfc> | sw_if_index <nn> table <nn>")                              \
14954 _(classify_set_interface_l2_tables,                                     \
14955   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
14956   "  [other-table <nn>]")                                               \
14957 _(get_node_index, "node <node-name")                                    \
14958 _(add_node_next, "node <node-name> next <next-node-name>")              \
14959 _(vxlan_offload_rx,                                                     \
14960   "hw { <interface name> | hw_if_index <nn>} "                          \
14961   "rx { <vxlan tunnel name> | sw_if_index <nn> } [del]")                \
14962 _(vxlan_add_del_tunnel,                                                 \
14963   "src <ip-addr> { dst <ip-addr> | group <mcast-ip-addr>\n"             \
14964   "{ <intfc> | mcast_sw_if_index <nn> } [instance <id>]}\n"             \
14965   "vni <vni> [encap-vrf-id <nn>] [decap-next <l2|nn>] [del]")           \
14966 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
14967 _(l2_fib_clear_table, "")                                               \
14968 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
14969 _(l2_interface_vlan_tag_rewrite,                                        \
14970   "<intfc> | sw_if_index <nn> \n"                                       \
14971   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
14972   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
14973 _(create_vhost_user_if,                                                 \
14974         "socket <filename> [server] [renumber <dev_instance>] "         \
14975         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
14976         "[mac <mac_address>] [packed]")                                 \
14977 _(modify_vhost_user_if,                                                 \
14978         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
14979         "[server] [renumber <dev_instance>] [gso] [packed]")            \
14980 _(create_vhost_user_if_v2,                                              \
14981         "socket <filename> [server] [renumber <dev_instance>] "         \
14982         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
14983         "[mac <mac_address>] [packed] [event-idx]")                     \
14984 _(modify_vhost_user_if_v2,                                              \
14985         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
14986         "[server] [renumber <dev_instance>] [gso] [packed] [event-idx]")\
14987 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
14988 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
14989 _(show_version, "")                                                     \
14990 _(show_threads, "")                                                     \
14991 _(vxlan_gpe_add_del_tunnel,                                             \
14992   "local <addr> remote <addr>  | group <mcast-ip-addr>\n"               \
14993   "{ <intfc> | mcast_sw_if_index <nn> } }\n"                            \
14994   "vni <nn> [encap-vrf-id <nn>] [decap-vrf-id <nn>]\n"                  \
14995   "[next-ip4][next-ip6][next-ethernet] [next-nsh] [del]\n")             \
14996 _(vxlan_gpe_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                \
14997 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
14998 _(interface_name_renumber,                                              \
14999   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
15000 _(input_acl_set_interface,                                              \
15001   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15002   "  [l2-table <nn>] [del]")                                            \
15003 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
15004 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
15005 _(ip_dump, "ipv4 | ipv6")                                               \
15006 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
15007 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
15008   "  spid_id <n> ")                                                     \
15009 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
15010   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
15011   "  integ_alg <alg> integ_key <hex>")                                  \
15012 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
15013   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
15014   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
15015   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
15016 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
15017 _(delete_loopback,"sw_if_index <nn>")                                   \
15018 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
15019 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
15020 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
15021 _(want_interface_events,  "enable|disable")                             \
15022 _(get_first_msg_id, "client <name>")                                    \
15023 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
15024 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
15025   "fib-id <nn> [ip4][ip6][default]")                                    \
15026 _(get_node_graph, " ")                                                  \
15027 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
15028 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
15029 _(ioam_disable, "")                                                     \
15030 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
15031 _(af_packet_delete, "name <host interface name>")                       \
15032 _(af_packet_dump, "")                                                   \
15033 _(policer_add_del, "name <policer name> <params> [del]")                \
15034 _(policer_dump, "[name <policer name>]")                                \
15035 _(policer_classify_set_interface,                                       \
15036   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15037   "  [l2-table <nn>] [del]")                                            \
15038 _(policer_classify_dump, "type [ip4|ip6|l2]")                           \
15039 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
15040 _(mpls_table_dump, "")                                                  \
15041 _(mpls_route_dump, "table-id <ID>")                                     \
15042 _(classify_table_ids, "")                                               \
15043 _(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
15044 _(classify_table_info, "table_id <nn>")                                 \
15045 _(classify_session_dump, "table_id <nn>")                               \
15046 _(set_ipfix_exporter, "collector_address <ip4> [collector_port <nn>] "  \
15047     "src_address <ip4> [vrf_id <nn>] [path_mtu <nn>] "                  \
15048     "[template_interval <nn>] [udp_checksum]")                          \
15049 _(ipfix_exporter_dump, "")                                              \
15050 _(set_ipfix_classify_stream, "[domain <domain-id>] [src_port <src-port>]") \
15051 _(ipfix_classify_stream_dump, "")                                       \
15052 _(ipfix_classify_table_add_del, "table <table-index> ip4|ip6 [tcp|udp]") \
15053 _(ipfix_classify_table_dump, "")                                        \
15054 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
15055 _(sw_interface_span_dump, "[l2]")                                           \
15056 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
15057 _(pg_create_interface, "if_id <nn> [gso-enabled gso-size <size>]")      \
15058 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
15059 _(pg_enable_disable, "[stream <id>] disable")                           \
15060 _(pg_interface_enable_disable_coalesce, "<intf> | sw_if_index <nn> enable | disable")  \
15061 _(ip_source_and_port_range_check_add_del,                               \
15062   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
15063 _(ip_source_and_port_range_check_interface_add_del,                     \
15064   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
15065   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
15066 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
15067 _(l2_interface_pbb_tag_rewrite,                                         \
15068   "<intfc> | sw_if_index <nn> \n"                                       \
15069   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
15070   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
15071 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
15072 _(flow_classify_set_interface,                                          \
15073   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>] [del]") \
15074 _(flow_classify_dump, "type [ip4|ip6]")                                 \
15075 _(ip_table_dump, "")                                                    \
15076 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
15077 _(ip_mtable_dump, "")                                                   \
15078 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
15079 _(feature_enable_disable, "arc_name <arc_name> "                        \
15080   "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]")   \
15081 _(feature_gso_enable_disable, "<intfc> | sw_if_index <nn> "             \
15082   "[enable | disable] ")                                                \
15083 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
15084 "[disable]")                                                            \
15085 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
15086   "mac <mac-address> [del]")                                            \
15087 _(l2_xconnect_dump, "")                                                 \
15088 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
15089 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
15090 _(p2p_ethernet_add, "<intfc> | sw_if_index <nn> remote_mac <mac-address> sub_id <id>") \
15091 _(p2p_ethernet_del, "<intfc> | sw_if_index <nn> remote_mac <mac-address>") \
15092 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
15093 _(sock_init_shm, "size <nnn>")                                          \
15094 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
15095 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
15096   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
15097 _(session_rules_dump, "")                                               \
15098 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
15099 _(output_acl_set_interface,                                             \
15100   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
15101   "  [l2-table <nn>] [del]")                                            \
15102 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
15103
15104 /* List of command functions, CLI names map directly to functions */
15105 #define foreach_cli_function                                    \
15106 _(comment, "usage: comment <ignore-rest-of-line>")              \
15107 _(dump_interface_table, "usage: dump_interface_table")          \
15108 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
15109 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
15110 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
15111 _(dump_macro_table, "usage: dump_macro_table ")                 \
15112 _(dump_node_table, "usage: dump_node_table")                    \
15113 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
15114 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
15115 _(elog_disable, "usage: elog_disable")                          \
15116 _(elog_enable, "usage: elog_enable")                            \
15117 _(elog_save, "usage: elog_save <filename>")                     \
15118 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
15119 _(echo, "usage: echo <message>")                                \
15120 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
15121 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
15122 _(help, "usage: help")                                          \
15123 _(q, "usage: quit")                                             \
15124 _(quit, "usage: quit")                                          \
15125 _(search_node_table, "usage: search_node_table <name>...")      \
15126 _(set, "usage: set <variable-name> <value>")                    \
15127 _(script, "usage: script <file-name>")                          \
15128 _(statseg, "usage: statseg")                                    \
15129 _(unset, "usage: unset <variable-name>")
15130
15131 #define _(N,n)                                  \
15132     static void vl_api_##n##_t_handler_uni      \
15133     (vl_api_##n##_t * mp)                       \
15134     {                                           \
15135         vat_main_t * vam = &vat_main;           \
15136         if (vam->json_output) {                 \
15137             vl_api_##n##_t_handler_json(mp);    \
15138         } else {                                \
15139             vl_api_##n##_t_handler(mp);         \
15140         }                                       \
15141     }
15142 foreach_vpe_api_reply_msg;
15143 #if VPP_API_TEST_BUILTIN == 0
15144 foreach_standalone_reply_msg;
15145 #endif
15146 #undef _
15147
15148 void
15149 vat_api_hookup (vat_main_t * vam)
15150 {
15151 #define _(N,n)                                                  \
15152     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
15153                            vl_api_##n##_t_handler_uni,          \
15154                            vl_noop_handler,                     \
15155                            vl_api_##n##_t_endian,               \
15156                            vl_api_##n##_t_print,                \
15157                            sizeof(vl_api_##n##_t), 1);
15158   foreach_vpe_api_reply_msg;
15159 #if VPP_API_TEST_BUILTIN == 0
15160   foreach_standalone_reply_msg;
15161 #endif
15162 #undef _
15163
15164 #if (VPP_API_TEST_BUILTIN==0)
15165   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
15166
15167   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
15168
15169   vam->function_by_name = hash_create_string (0, sizeof (uword));
15170
15171   vam->help_by_name = hash_create_string (0, sizeof (uword));
15172 #endif
15173
15174   /* API messages we can send */
15175 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
15176   foreach_vpe_api_msg;
15177 #undef _
15178
15179   /* Help strings */
15180 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15181   foreach_vpe_api_msg;
15182 #undef _
15183
15184   /* CLI functions */
15185 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
15186   foreach_cli_function;
15187 #undef _
15188
15189   /* Help strings */
15190 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
15191   foreach_cli_function;
15192 #undef _
15193 }
15194
15195 #if VPP_API_TEST_BUILTIN
15196 static clib_error_t *
15197 vat_api_hookup_shim (vlib_main_t * vm)
15198 {
15199   vat_api_hookup (&vat_main);
15200   return 0;
15201 }
15202
15203 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
15204 #endif
15205
15206 /*
15207  * fd.io coding-style-patch-verification: ON
15208  *
15209  * Local Variables:
15210  * eval: (c-set-style "gnu")
15211  * End:
15212  */