vxlan: api cleanup
[vpp.git] / src / vat / api_format.c
1 /*
2  *------------------------------------------------------------------
3  * api_format.c
4  *
5  * Copyright (c) 2014-2020 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <vat/vat.h>
21 #include <vlib/pci/pci.h>
22 #include <vpp/api/types.h>
23 #include <vppinfra/socket.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vnet/ip/ip.h>
27 #include <vnet/ip-neighbor/ip_neighbor.h>
28 #include <vnet/ip/ip_types_api.h>
29 #include <vnet/l2/l2_input.h>
30 #include <vnet/udp/udp_local.h>
31
32 #include <vpp/api/vpe_msg_enum.h>
33 #include <vnet/l2/l2_classify.h>
34 #include <vnet/l2/l2_vtr.h>
35 #include <vnet/classify/in_out_acl.h>
36 #include <vnet/classify/policer_classify.h>
37 #include <vnet/classify/flow_classify.h>
38 #include <vnet/mpls/mpls.h>
39 #include <vnet/ipsec/ipsec.h>
40 #include <inttypes.h>
41 #include <vnet/ip/ip6_hop_by_hop.h>
42 #include <vnet/ip/ip_source_and_port_range_check.h>
43 #include <vnet/policer/xlate.h>
44 #include <vnet/span/span.h>
45 #include <vnet/policer/policer.h>
46 #include <vnet/policer/police.h>
47 #include <vnet/mfib/mfib_types.h>
48 #include <vnet/bonding/node.h>
49 #include <vnet/qos/qos_types.h>
50 #include <vnet/ethernet/ethernet_types_api.h>
51 #include <vnet/ip/ip_types_api.h>
52 #include "vat/json_format.h"
53 #include <vnet/ip/ip_types_api.h>
54 #include <vnet/ethernet/ethernet_types_api.h>
55
56 #include <inttypes.h>
57 #include <sys/stat.h>
58
59 #define vl_typedefs             /* define message structures */
60 #include <vpp/api/vpe_all_api_h.h>
61 #undef vl_typedefs
62
63 /* declare message handlers for each api */
64
65 #define vl_endianfun            /* define message structures */
66 #include <vpp/api/vpe_all_api_h.h>
67 #undef vl_endianfun
68
69 /* instantiate all the print functions we know about */
70 #if VPP_API_TEST_BUILTIN == 0
71 #define vl_print(handle, ...)
72 #else
73 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
74 #endif
75 #define vl_printfun
76 #include <vpp/api/vpe_all_api_h.h>
77 #undef vl_printfun
78
79 #define __plugin_msg_base 0
80 #include <vlibapi/vat_helper_macros.h>
81
82 void vl_api_set_elog_main (elog_main_t * m);
83 int vl_api_set_elog_trace_api_messages (int enable);
84
85 #if VPP_API_TEST_BUILTIN == 0
86 #include <netdb.h>
87
88 u32
89 vl (void *p)
90 {
91   return vec_len (p);
92 }
93
94 int
95 vat_socket_connect (vat_main_t * vam)
96 {
97   int rv;
98   api_main_t *am = vlibapi_get_main ();
99   vam->socket_client_main = &socket_client_main;
100   if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
101                                       "vpp_api_test",
102                                       0 /* default socket rx, tx buffer */ )))
103     return rv;
104
105   /* vpp expects the client index in network order */
106   vam->my_client_index = htonl (socket_client_main.client_index);
107   am->my_client_index = vam->my_client_index;
108   return 0;
109 }
110 #else /* vpp built-in case, we don't do sockets... */
111 int
112 vat_socket_connect (vat_main_t * vam)
113 {
114   return 0;
115 }
116
117 int
118 vl_socket_client_read (int wait)
119 {
120   return -1;
121 };
122
123 int
124 vl_socket_client_write ()
125 {
126   return -1;
127 };
128
129 void *
130 vl_socket_client_msg_alloc (int nbytes)
131 {
132   return 0;
133 }
134 #endif
135
136
137 f64
138 vat_time_now (vat_main_t * vam)
139 {
140 #if VPP_API_TEST_BUILTIN
141   return vlib_time_now (vam->vlib_main);
142 #else
143   return clib_time_now (&vam->clib_time);
144 #endif
145 }
146
147 void
148 errmsg (char *fmt, ...)
149 {
150   vat_main_t *vam = &vat_main;
151   va_list va;
152   u8 *s;
153
154   va_start (va, fmt);
155   s = va_format (0, fmt, &va);
156   va_end (va);
157
158   vec_add1 (s, 0);
159
160 #if VPP_API_TEST_BUILTIN
161   vlib_cli_output (vam->vlib_main, (char *) s);
162 #else
163   {
164     if (vam->ifp != stdin)
165       fformat (vam->ofp, "%s(%d): \n", vam->current_file,
166                vam->input_line_number);
167     else
168       fformat (vam->ofp, "%s\n", (char *) s);
169     fflush (vam->ofp);
170   }
171 #endif
172
173   vec_free (s);
174 }
175
176 #if VPP_API_TEST_BUILTIN == 0
177 static uword
178 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
179 {
180   vat_main_t *vam = va_arg (*args, vat_main_t *);
181   u32 *result = va_arg (*args, u32 *);
182   u8 *if_name;
183   uword *p;
184
185   if (!unformat (input, "%s", &if_name))
186     return 0;
187
188   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
189   if (p == 0)
190     return 0;
191   *result = p[0];
192   return 1;
193 }
194
195 /* Parse an IP4 address %d.%d.%d.%d. */
196 uword
197 unformat_ip4_address (unformat_input_t * input, va_list * args)
198 {
199   u8 *result = va_arg (*args, u8 *);
200   unsigned a[4];
201
202   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
203     return 0;
204
205   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
206     return 0;
207
208   result[0] = a[0];
209   result[1] = a[1];
210   result[2] = a[2];
211   result[3] = a[3];
212
213   return 1;
214 }
215
216 uword
217 unformat_ethernet_address (unformat_input_t * input, va_list * args)
218 {
219   u8 *result = va_arg (*args, u8 *);
220   u32 i, a[6];
221
222   if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
223                  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
224     return 0;
225
226   /* Check range. */
227   for (i = 0; i < 6; i++)
228     if (a[i] >= (1 << 8))
229       return 0;
230
231   for (i = 0; i < 6; i++)
232     result[i] = a[i];
233
234   return 1;
235 }
236
237 /* Returns ethernet type as an int in host byte order. */
238 uword
239 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
240                                         va_list * args)
241 {
242   u16 *result = va_arg (*args, u16 *);
243   int type;
244
245   /* Numeric type. */
246   if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
247     {
248       if (type >= (1 << 16))
249         return 0;
250       *result = type;
251       return 1;
252     }
253   return 0;
254 }
255
256 /* Parse an IP46 address. */
257 uword
258 unformat_ip46_address (unformat_input_t * input, va_list * args)
259 {
260   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
261   ip46_type_t type = va_arg (*args, ip46_type_t);
262   if ((type != IP46_TYPE_IP6) &&
263       unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
264     {
265       ip46_address_mask_ip4 (ip46);
266       return 1;
267     }
268   else if ((type != IP46_TYPE_IP4) &&
269            unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
270     {
271       return 1;
272     }
273   return 0;
274 }
275
276 /* Parse an IP6 address. */
277 uword
278 unformat_ip6_address (unformat_input_t * input, va_list * args)
279 {
280   ip6_address_t *result = va_arg (*args, ip6_address_t *);
281   u16 hex_quads[8];
282   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
283   uword c, n_colon, double_colon_index;
284
285   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
286   double_colon_index = ARRAY_LEN (hex_quads);
287   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
288     {
289       hex_digit = 16;
290       if (c >= '0' && c <= '9')
291         hex_digit = c - '0';
292       else if (c >= 'a' && c <= 'f')
293         hex_digit = c + 10 - 'a';
294       else if (c >= 'A' && c <= 'F')
295         hex_digit = c + 10 - 'A';
296       else if (c == ':' && n_colon < 2)
297         n_colon++;
298       else
299         {
300           unformat_put_input (input);
301           break;
302         }
303
304       /* Too many hex quads. */
305       if (n_hex_quads >= ARRAY_LEN (hex_quads))
306         return 0;
307
308       if (hex_digit < 16)
309         {
310           hex_quad = (hex_quad << 4) | hex_digit;
311
312           /* Hex quad must fit in 16 bits. */
313           if (n_hex_digits >= 4)
314             return 0;
315
316           n_colon = 0;
317           n_hex_digits++;
318         }
319
320       /* Save position of :: */
321       if (n_colon == 2)
322         {
323           /* More than one :: ? */
324           if (double_colon_index < ARRAY_LEN (hex_quads))
325             return 0;
326           double_colon_index = n_hex_quads;
327         }
328
329       if (n_colon > 0 && n_hex_digits > 0)
330         {
331           hex_quads[n_hex_quads++] = hex_quad;
332           hex_quad = 0;
333           n_hex_digits = 0;
334         }
335     }
336
337   if (n_hex_digits > 0)
338     hex_quads[n_hex_quads++] = hex_quad;
339
340   {
341     word i;
342
343     /* Expand :: to appropriate number of zero hex quads. */
344     if (double_colon_index < ARRAY_LEN (hex_quads))
345       {
346         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
347
348         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
349           hex_quads[n_zero + i] = hex_quads[i];
350
351         for (i = 0; i < n_zero; i++)
352           hex_quads[double_colon_index + i] = 0;
353
354         n_hex_quads = ARRAY_LEN (hex_quads);
355       }
356
357     /* Too few hex quads given. */
358     if (n_hex_quads < ARRAY_LEN (hex_quads))
359       return 0;
360
361     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
362       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
363
364     return 1;
365   }
366 }
367
368 uword
369 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
370 {
371   u32 *r = va_arg (*args, u32 *);
372
373   if (0);
374 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
375   foreach_ipsec_policy_action
376 #undef _
377     else
378     return 0;
379   return 1;
380 }
381
382 u8 *
383 format_ipsec_crypto_alg (u8 * s, va_list * args)
384 {
385   u32 i = va_arg (*args, u32);
386   u8 *t = 0;
387
388   switch (i)
389     {
390 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
391       foreach_ipsec_crypto_alg
392 #undef _
393     default:
394       return format (s, "unknown");
395     }
396   return format (s, "%s", t);
397 }
398
399 u8 *
400 format_ipsec_integ_alg (u8 * s, va_list * args)
401 {
402   u32 i = va_arg (*args, u32);
403   u8 *t = 0;
404
405   switch (i)
406     {
407 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
408       foreach_ipsec_integ_alg
409 #undef _
410     default:
411       return format (s, "unknown");
412     }
413   return format (s, "%s", t);
414 }
415
416 #else /* VPP_API_TEST_BUILTIN == 1 */
417 static uword
418 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
419 {
420   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
421   vnet_main_t *vnm = vnet_get_main ();
422   u32 *result = va_arg (*args, u32 *);
423
424   return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
425 }
426
427 #endif /* VPP_API_TEST_BUILTIN */
428
429 uword
430 unformat_ipsec_api_crypto_alg (unformat_input_t * input, va_list * args)
431 {
432   u32 *r = va_arg (*args, u32 *);
433
434   if (0);
435 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
436   foreach_ipsec_crypto_alg
437 #undef _
438     else
439     return 0;
440   return 1;
441 }
442
443 uword
444 unformat_ipsec_api_integ_alg (unformat_input_t * input, va_list * args)
445 {
446   u32 *r = va_arg (*args, u32 *);
447
448   if (0);
449 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
450   foreach_ipsec_integ_alg
451 #undef _
452     else
453     return 0;
454   return 1;
455 }
456
457 static uword
458 unformat_policer_rate_type (unformat_input_t * input, va_list * args)
459 {
460   u8 *r = va_arg (*args, u8 *);
461
462   if (unformat (input, "kbps"))
463     *r = QOS_RATE_KBPS;
464   else if (unformat (input, "pps"))
465     *r = QOS_RATE_PPS;
466   else
467     return 0;
468   return 1;
469 }
470
471 static uword
472 unformat_policer_round_type (unformat_input_t * input, va_list * args)
473 {
474   u8 *r = va_arg (*args, u8 *);
475
476   if (unformat (input, "closest"))
477     *r = QOS_ROUND_TO_CLOSEST;
478   else if (unformat (input, "up"))
479     *r = QOS_ROUND_TO_UP;
480   else if (unformat (input, "down"))
481     *r = QOS_ROUND_TO_DOWN;
482   else
483     return 0;
484   return 1;
485 }
486
487 static uword
488 unformat_policer_type (unformat_input_t * input, va_list * args)
489 {
490   u8 *r = va_arg (*args, u8 *);
491
492   if (unformat (input, "1r2c"))
493     *r = QOS_POLICER_TYPE_1R2C;
494   else if (unformat (input, "1r3c"))
495     *r = QOS_POLICER_TYPE_1R3C_RFC_2697;
496   else if (unformat (input, "2r3c-2698"))
497     *r = QOS_POLICER_TYPE_2R3C_RFC_2698;
498   else if (unformat (input, "2r3c-4115"))
499     *r = QOS_POLICER_TYPE_2R3C_RFC_4115;
500   else if (unformat (input, "2r3c-mef5cf1"))
501     *r = QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
502   else
503     return 0;
504   return 1;
505 }
506
507 static uword
508 unformat_dscp (unformat_input_t * input, va_list * va)
509 {
510   u8 *r = va_arg (*va, u8 *);
511
512   if (0);
513 #define _(v, f) else if (unformat (input, #f)) *r = IP_DSCP_##f;
514   foreach_ip_dscp
515 #undef _
516     else return 0;
517   return 1;
518 }
519
520 static uword
521 unformat_policer_action_type (unformat_input_t * input, va_list * va)
522 {
523   qos_pol_action_params_st *a = va_arg (*va, qos_pol_action_params_st *);
524
525   if (unformat (input, "drop"))
526     a->action_type = QOS_ACTION_DROP;
527   else if (unformat (input, "transmit"))
528     a->action_type = QOS_ACTION_TRANSMIT;
529   else if (unformat (input, "mark-and-transmit %U", unformat_dscp, &a->dscp))
530     a->action_type = QOS_ACTION_MARK_AND_TRANSMIT;
531   else
532     return 0;
533   return 1;
534 }
535
536 #if (VPP_API_TEST_BUILTIN==0)
537
538 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
539 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
540 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
541 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
542
543 uword
544 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
545 {
546   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
547   mfib_itf_attribute_t attr;
548
549   old = *iflags;
550   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
551   {
552     if (unformat (input, mfib_itf_flag_long_names[attr]))
553       *iflags |= (1 << attr);
554   }
555   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
556   {
557     if (unformat (input, mfib_itf_flag_names[attr]))
558       *iflags |= (1 << attr);
559   }
560
561   return (old == *iflags ? 0 : 1);
562 }
563
564 uword
565 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
566 {
567   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
568   mfib_entry_attribute_t attr;
569
570   old = *eflags;
571   FOR_EACH_MFIB_ATTRIBUTE (attr)
572   {
573     if (unformat (input, mfib_flag_long_names[attr]))
574       *eflags |= (1 << attr);
575   }
576   FOR_EACH_MFIB_ATTRIBUTE (attr)
577   {
578     if (unformat (input, mfib_flag_names[attr]))
579       *eflags |= (1 << attr);
580   }
581
582   return (old == *eflags ? 0 : 1);
583 }
584
585 u8 *
586 format_ip4_address (u8 * s, va_list * args)
587 {
588   u8 *a = va_arg (*args, u8 *);
589   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
590 }
591
592 u8 *
593 format_ip6_address (u8 * s, va_list * args)
594 {
595   ip6_address_t *a = va_arg (*args, ip6_address_t *);
596   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
597
598   i_max_n_zero = ARRAY_LEN (a->as_u16);
599   max_n_zeros = 0;
600   i_first_zero = i_max_n_zero;
601   n_zeros = 0;
602   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
603     {
604       u32 is_zero = a->as_u16[i] == 0;
605       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
606         {
607           i_first_zero = i;
608           n_zeros = 0;
609         }
610       n_zeros += is_zero;
611       if ((!is_zero && n_zeros > max_n_zeros)
612           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
613         {
614           i_max_n_zero = i_first_zero;
615           max_n_zeros = n_zeros;
616           i_first_zero = ARRAY_LEN (a->as_u16);
617           n_zeros = 0;
618         }
619     }
620
621   last_double_colon = 0;
622   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
623     {
624       if (i == i_max_n_zero && max_n_zeros > 1)
625         {
626           s = format (s, "::");
627           i += max_n_zeros - 1;
628           last_double_colon = 1;
629         }
630       else
631         {
632           s = format (s, "%s%x",
633                       (last_double_colon || i == 0) ? "" : ":",
634                       clib_net_to_host_u16 (a->as_u16[i]));
635           last_double_colon = 0;
636         }
637     }
638
639   return s;
640 }
641
642 /* Format an IP46 address. */
643 u8 *
644 format_ip46_address (u8 * s, va_list * args)
645 {
646   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
647   ip46_type_t type = va_arg (*args, ip46_type_t);
648   int is_ip4 = 1;
649
650   switch (type)
651     {
652     case IP46_TYPE_ANY:
653       is_ip4 = ip46_address_is_ip4 (ip46);
654       break;
655     case IP46_TYPE_IP4:
656       is_ip4 = 1;
657       break;
658     case IP46_TYPE_IP6:
659       is_ip4 = 0;
660       break;
661     }
662
663   return is_ip4 ?
664     format (s, "%U", format_ip4_address, &ip46->ip4) :
665     format (s, "%U", format_ip6_address, &ip46->ip6);
666 }
667
668 u8 *
669 format_ethernet_address (u8 * s, va_list * args)
670 {
671   u8 *a = va_arg (*args, u8 *);
672
673   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
674                  a[0], a[1], a[2], a[3], a[4], a[5]);
675 }
676 #endif
677
678 static void
679 increment_v4_address (vl_api_ip4_address_t * i)
680 {
681   ip4_address_t *a = (ip4_address_t *) i;
682   u32 v;
683
684   v = ntohl (a->as_u32) + 1;
685   a->as_u32 = ntohl (v);
686 }
687
688 static void
689 increment_v6_address (vl_api_ip6_address_t * i)
690 {
691   ip6_address_t *a = (ip6_address_t *) i;
692   u64 v0, v1;
693
694   v0 = clib_net_to_host_u64 (a->as_u64[0]);
695   v1 = clib_net_to_host_u64 (a->as_u64[1]);
696
697   v1 += 1;
698   if (v1 == 0)
699     v0 += 1;
700   a->as_u64[0] = clib_net_to_host_u64 (v0);
701   a->as_u64[1] = clib_net_to_host_u64 (v1);
702 }
703
704 static void
705 increment_address (vl_api_address_t * a)
706 {
707   if (a->af == ADDRESS_IP4)
708     increment_v4_address (&a->un.ip4);
709   else if (a->af == ADDRESS_IP6)
710     increment_v6_address (&a->un.ip6);
711 }
712
713 static void
714 set_ip4_address (vl_api_address_t * a, u32 v)
715 {
716   if (a->af == ADDRESS_IP4)
717     {
718       ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
719       i->as_u32 = v;
720     }
721 }
722
723 void
724 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
725 {
726   if (is_ip4)
727     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
728   else
729     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
730                       sizeof (ip6_address_t));
731 }
732
733 static void
734 increment_mac_address (u8 * mac)
735 {
736   u64 tmp = *((u64 *) mac);
737   tmp = clib_net_to_host_u64 (tmp);
738   tmp += 1 << 16;               /* skip unused (least significant) octets */
739   tmp = clib_host_to_net_u64 (tmp);
740
741   clib_memcpy (mac, &tmp, 6);
742 }
743
744 static void
745 vat_json_object_add_address (vat_json_node_t * node,
746                              const char *str, const vl_api_address_t * addr)
747 {
748   if (ADDRESS_IP6 == addr->af)
749     {
750       struct in6_addr ip6;
751
752       clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
753       vat_json_object_add_ip6 (node, str, ip6);
754     }
755   else
756     {
757       struct in_addr ip4;
758
759       clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
760       vat_json_object_add_ip4 (node, str, ip4);
761     }
762 }
763
764 static void
765 vat_json_object_add_prefix (vat_json_node_t * node,
766                             const vl_api_prefix_t * prefix)
767 {
768   vat_json_object_add_uint (node, "len", prefix->len);
769   vat_json_object_add_address (node, "address", &prefix->address);
770 }
771
772 static void vl_api_create_loopback_reply_t_handler
773   (vl_api_create_loopback_reply_t * mp)
774 {
775   vat_main_t *vam = &vat_main;
776   i32 retval = ntohl (mp->retval);
777
778   vam->retval = retval;
779   vam->regenerate_interface_table = 1;
780   vam->sw_if_index = ntohl (mp->sw_if_index);
781   vam->result_ready = 1;
782 }
783
784 static void vl_api_create_loopback_reply_t_handler_json
785   (vl_api_create_loopback_reply_t * mp)
786 {
787   vat_main_t *vam = &vat_main;
788   vat_json_node_t node;
789
790   vat_json_init_object (&node);
791   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
792   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
793
794   vat_json_print (vam->ofp, &node);
795   vat_json_free (&node);
796   vam->retval = ntohl (mp->retval);
797   vam->result_ready = 1;
798 }
799
800 static void vl_api_create_loopback_instance_reply_t_handler
801   (vl_api_create_loopback_instance_reply_t * mp)
802 {
803   vat_main_t *vam = &vat_main;
804   i32 retval = ntohl (mp->retval);
805
806   vam->retval = retval;
807   vam->regenerate_interface_table = 1;
808   vam->sw_if_index = ntohl (mp->sw_if_index);
809   vam->result_ready = 1;
810 }
811
812 static void vl_api_create_loopback_instance_reply_t_handler_json
813   (vl_api_create_loopback_instance_reply_t * mp)
814 {
815   vat_main_t *vam = &vat_main;
816   vat_json_node_t node;
817
818   vat_json_init_object (&node);
819   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
820   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
821
822   vat_json_print (vam->ofp, &node);
823   vat_json_free (&node);
824   vam->retval = ntohl (mp->retval);
825   vam->result_ready = 1;
826 }
827
828 static void vl_api_af_packet_create_reply_t_handler
829   (vl_api_af_packet_create_reply_t * mp)
830 {
831   vat_main_t *vam = &vat_main;
832   i32 retval = ntohl (mp->retval);
833
834   vam->retval = retval;
835   vam->regenerate_interface_table = 1;
836   vam->sw_if_index = ntohl (mp->sw_if_index);
837   vam->result_ready = 1;
838 }
839
840 static void vl_api_af_packet_create_reply_t_handler_json
841   (vl_api_af_packet_create_reply_t * mp)
842 {
843   vat_main_t *vam = &vat_main;
844   vat_json_node_t node;
845
846   vat_json_init_object (&node);
847   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
848   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
849
850   vat_json_print (vam->ofp, &node);
851   vat_json_free (&node);
852
853   vam->retval = ntohl (mp->retval);
854   vam->result_ready = 1;
855 }
856
857 static void vl_api_create_vlan_subif_reply_t_handler
858   (vl_api_create_vlan_subif_reply_t * mp)
859 {
860   vat_main_t *vam = &vat_main;
861   i32 retval = ntohl (mp->retval);
862
863   vam->retval = retval;
864   vam->regenerate_interface_table = 1;
865   vam->sw_if_index = ntohl (mp->sw_if_index);
866   vam->result_ready = 1;
867 }
868
869 static void vl_api_create_vlan_subif_reply_t_handler_json
870   (vl_api_create_vlan_subif_reply_t * mp)
871 {
872   vat_main_t *vam = &vat_main;
873   vat_json_node_t node;
874
875   vat_json_init_object (&node);
876   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
877   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
878
879   vat_json_print (vam->ofp, &node);
880   vat_json_free (&node);
881
882   vam->retval = ntohl (mp->retval);
883   vam->result_ready = 1;
884 }
885
886 static void vl_api_create_subif_reply_t_handler
887   (vl_api_create_subif_reply_t * mp)
888 {
889   vat_main_t *vam = &vat_main;
890   i32 retval = ntohl (mp->retval);
891
892   vam->retval = retval;
893   vam->regenerate_interface_table = 1;
894   vam->sw_if_index = ntohl (mp->sw_if_index);
895   vam->result_ready = 1;
896 }
897
898 static void vl_api_create_subif_reply_t_handler_json
899   (vl_api_create_subif_reply_t * mp)
900 {
901   vat_main_t *vam = &vat_main;
902   vat_json_node_t node;
903
904   vat_json_init_object (&node);
905   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
906   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
907
908   vat_json_print (vam->ofp, &node);
909   vat_json_free (&node);
910
911   vam->retval = ntohl (mp->retval);
912   vam->result_ready = 1;
913 }
914
915 static void vl_api_interface_name_renumber_reply_t_handler
916   (vl_api_interface_name_renumber_reply_t * mp)
917 {
918   vat_main_t *vam = &vat_main;
919   i32 retval = ntohl (mp->retval);
920
921   vam->retval = retval;
922   vam->regenerate_interface_table = 1;
923   vam->result_ready = 1;
924 }
925
926 static void vl_api_interface_name_renumber_reply_t_handler_json
927   (vl_api_interface_name_renumber_reply_t * mp)
928 {
929   vat_main_t *vam = &vat_main;
930   vat_json_node_t node;
931
932   vat_json_init_object (&node);
933   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
934
935   vat_json_print (vam->ofp, &node);
936   vat_json_free (&node);
937
938   vam->retval = ntohl (mp->retval);
939   vam->result_ready = 1;
940 }
941
942 /*
943  * Special-case: build the interface table, maintain
944  * the next loopback sw_if_index vbl.
945  */
946 static void vl_api_sw_interface_details_t_handler
947   (vl_api_sw_interface_details_t * mp)
948 {
949   vat_main_t *vam = &vat_main;
950   u8 *s = format (0, "%s%c", mp->interface_name, 0);
951
952   hash_set_mem (vam->sw_if_index_by_interface_name, s,
953                 ntohl (mp->sw_if_index));
954
955   /* In sub interface case, fill the sub interface table entry */
956   if (mp->sw_if_index != mp->sup_sw_if_index)
957     {
958       sw_interface_subif_t *sub = NULL;
959
960       vec_add2 (vam->sw_if_subif_table, sub, 1);
961
962       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
963       strncpy ((char *) sub->interface_name, (char *) s,
964                vec_len (sub->interface_name));
965       sub->sw_if_index = ntohl (mp->sw_if_index);
966       sub->sub_id = ntohl (mp->sub_id);
967
968       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
969
970       sub->sub_number_of_tags = mp->sub_number_of_tags;
971       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
972       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
973
974       /* vlan tag rewrite */
975       sub->vtr_op = ntohl (mp->vtr_op);
976       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
977       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
978       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
979     }
980 }
981
982 static void vl_api_sw_interface_details_t_handler_json
983   (vl_api_sw_interface_details_t * mp)
984 {
985   vat_main_t *vam = &vat_main;
986   vat_json_node_t *node = NULL;
987
988   if (VAT_JSON_ARRAY != vam->json_tree.type)
989     {
990       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
991       vat_json_init_array (&vam->json_tree);
992     }
993   node = vat_json_array_add (&vam->json_tree);
994
995   vat_json_init_object (node);
996   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
997   vat_json_object_add_uint (node, "sup_sw_if_index",
998                             ntohl (mp->sup_sw_if_index));
999   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
1000                              sizeof (mp->l2_address));
1001   vat_json_object_add_string_copy (node, "interface_name",
1002                                    mp->interface_name);
1003   vat_json_object_add_string_copy (node, "interface_dev_type",
1004                                    mp->interface_dev_type);
1005   vat_json_object_add_uint (node, "flags", mp->flags);
1006   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
1007   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
1008   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
1009   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
1010   vat_json_object_add_uint (node, "sub_number_of_tags",
1011                             mp->sub_number_of_tags);
1012   vat_json_object_add_uint (node, "sub_outer_vlan_id",
1013                             ntohs (mp->sub_outer_vlan_id));
1014   vat_json_object_add_uint (node, "sub_inner_vlan_id",
1015                             ntohs (mp->sub_inner_vlan_id));
1016   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
1017   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
1018   vat_json_object_add_uint (node, "vtr_push_dot1q",
1019                             ntohl (mp->vtr_push_dot1q));
1020   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
1021   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
1022   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
1023     {
1024       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
1025                                        format (0, "%U",
1026                                                format_ethernet_address,
1027                                                &mp->b_dmac));
1028       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
1029                                        format (0, "%U",
1030                                                format_ethernet_address,
1031                                                &mp->b_smac));
1032       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
1033       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
1034     }
1035 }
1036
1037 #if VPP_API_TEST_BUILTIN == 0
1038 static void vl_api_sw_interface_event_t_handler
1039   (vl_api_sw_interface_event_t * mp)
1040 {
1041   vat_main_t *vam = &vat_main;
1042   if (vam->interface_event_display)
1043     errmsg ("interface flags: sw_if_index %d %s %s",
1044             ntohl (mp->sw_if_index),
1045             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
1046             "admin-up" : "admin-down",
1047             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
1048             "link-up" : "link-down");
1049 }
1050 #endif
1051
1052 __clib_unused static void
1053 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
1054 {
1055   /* JSON output not supported */
1056 }
1057
1058 static void
1059 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
1060 {
1061   vat_main_t *vam = &vat_main;
1062   i32 retval = ntohl (mp->retval);
1063
1064   vam->retval = retval;
1065   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
1066   vam->result_ready = 1;
1067 }
1068
1069 static void
1070 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
1071 {
1072   vat_main_t *vam = &vat_main;
1073   vat_json_node_t node;
1074   void *oldheap;
1075   u8 *reply;
1076
1077   vat_json_init_object (&node);
1078   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1079   vat_json_object_add_uint (&node, "reply_in_shmem",
1080                             ntohl (mp->reply_in_shmem));
1081   /* Toss the shared-memory original... */
1082   oldheap = vl_msg_push_heap ();
1083
1084   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1085   vec_free (reply);
1086
1087   vl_msg_pop_heap (oldheap);
1088
1089   vat_json_print (vam->ofp, &node);
1090   vat_json_free (&node);
1091
1092   vam->retval = ntohl (mp->retval);
1093   vam->result_ready = 1;
1094 }
1095
1096 static void
1097 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
1098 {
1099   vat_main_t *vam = &vat_main;
1100   i32 retval = ntohl (mp->retval);
1101
1102   vec_reset_length (vam->cmd_reply);
1103
1104   vam->retval = retval;
1105   if (retval == 0)
1106     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1107   vam->result_ready = 1;
1108 }
1109
1110 static void
1111 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
1112 {
1113   vat_main_t *vam = &vat_main;
1114   vat_json_node_t node;
1115   u8 *reply = 0;                /* reply vector */
1116
1117   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
1118   vec_reset_length (vam->cmd_reply);
1119
1120   vat_json_init_object (&node);
1121   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1122   vat_json_object_add_string_copy (&node, "reply", reply);
1123
1124   vat_json_print (vam->ofp, &node);
1125   vat_json_free (&node);
1126   vec_free (reply);
1127
1128   vam->retval = ntohl (mp->retval);
1129   vam->result_ready = 1;
1130 }
1131
1132 static void vl_api_get_node_index_reply_t_handler
1133   (vl_api_get_node_index_reply_t * mp)
1134 {
1135   vat_main_t *vam = &vat_main;
1136   i32 retval = ntohl (mp->retval);
1137   if (vam->async_mode)
1138     {
1139       vam->async_errors += (retval < 0);
1140     }
1141   else
1142     {
1143       vam->retval = retval;
1144       if (retval == 0)
1145         errmsg ("node index %d", ntohl (mp->node_index));
1146       vam->result_ready = 1;
1147     }
1148 }
1149
1150 static void vl_api_get_node_index_reply_t_handler_json
1151   (vl_api_get_node_index_reply_t * mp)
1152 {
1153   vat_main_t *vam = &vat_main;
1154   vat_json_node_t node;
1155
1156   vat_json_init_object (&node);
1157   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1158   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1159
1160   vat_json_print (vam->ofp, &node);
1161   vat_json_free (&node);
1162
1163   vam->retval = ntohl (mp->retval);
1164   vam->result_ready = 1;
1165 }
1166
1167 static void vl_api_get_next_index_reply_t_handler
1168   (vl_api_get_next_index_reply_t * mp)
1169 {
1170   vat_main_t *vam = &vat_main;
1171   i32 retval = ntohl (mp->retval);
1172   if (vam->async_mode)
1173     {
1174       vam->async_errors += (retval < 0);
1175     }
1176   else
1177     {
1178       vam->retval = retval;
1179       if (retval == 0)
1180         errmsg ("next node index %d", ntohl (mp->next_index));
1181       vam->result_ready = 1;
1182     }
1183 }
1184
1185 static void vl_api_get_next_index_reply_t_handler_json
1186   (vl_api_get_next_index_reply_t * mp)
1187 {
1188   vat_main_t *vam = &vat_main;
1189   vat_json_node_t node;
1190
1191   vat_json_init_object (&node);
1192   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1193   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1194
1195   vat_json_print (vam->ofp, &node);
1196   vat_json_free (&node);
1197
1198   vam->retval = ntohl (mp->retval);
1199   vam->result_ready = 1;
1200 }
1201
1202 static void vl_api_add_node_next_reply_t_handler
1203   (vl_api_add_node_next_reply_t * mp)
1204 {
1205   vat_main_t *vam = &vat_main;
1206   i32 retval = ntohl (mp->retval);
1207   if (vam->async_mode)
1208     {
1209       vam->async_errors += (retval < 0);
1210     }
1211   else
1212     {
1213       vam->retval = retval;
1214       if (retval == 0)
1215         errmsg ("next index %d", ntohl (mp->next_index));
1216       vam->result_ready = 1;
1217     }
1218 }
1219
1220 static void vl_api_add_node_next_reply_t_handler_json
1221   (vl_api_add_node_next_reply_t * mp)
1222 {
1223   vat_main_t *vam = &vat_main;
1224   vat_json_node_t node;
1225
1226   vat_json_init_object (&node);
1227   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1228   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1229
1230   vat_json_print (vam->ofp, &node);
1231   vat_json_free (&node);
1232
1233   vam->retval = ntohl (mp->retval);
1234   vam->result_ready = 1;
1235 }
1236
1237 static void vl_api_show_version_reply_t_handler
1238   (vl_api_show_version_reply_t * mp)
1239 {
1240   vat_main_t *vam = &vat_main;
1241   i32 retval = ntohl (mp->retval);
1242
1243   if (retval >= 0)
1244     {
1245       errmsg ("        program: %s", mp->program);
1246       errmsg ("        version: %s", mp->version);
1247       errmsg ("     build date: %s", mp->build_date);
1248       errmsg ("build directory: %s", mp->build_directory);
1249     }
1250   vam->retval = retval;
1251   vam->result_ready = 1;
1252 }
1253
1254 static void vl_api_show_version_reply_t_handler_json
1255   (vl_api_show_version_reply_t * mp)
1256 {
1257   vat_main_t *vam = &vat_main;
1258   vat_json_node_t node;
1259
1260   vat_json_init_object (&node);
1261   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1262   vat_json_object_add_string_copy (&node, "program", mp->program);
1263   vat_json_object_add_string_copy (&node, "version", mp->version);
1264   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1265   vat_json_object_add_string_copy (&node, "build_directory",
1266                                    mp->build_directory);
1267
1268   vat_json_print (vam->ofp, &node);
1269   vat_json_free (&node);
1270
1271   vam->retval = ntohl (mp->retval);
1272   vam->result_ready = 1;
1273 }
1274
1275 static void vl_api_show_threads_reply_t_handler
1276   (vl_api_show_threads_reply_t * mp)
1277 {
1278   vat_main_t *vam = &vat_main;
1279   i32 retval = ntohl (mp->retval);
1280   int i, count = 0;
1281
1282   if (retval >= 0)
1283     count = ntohl (mp->count);
1284
1285   for (i = 0; i < count; i++)
1286     print (vam->ofp,
1287            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1288            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1289            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1290            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1291            ntohl (mp->thread_data[i].cpu_socket));
1292
1293   vam->retval = retval;
1294   vam->result_ready = 1;
1295 }
1296
1297 static void vl_api_show_threads_reply_t_handler_json
1298   (vl_api_show_threads_reply_t * mp)
1299 {
1300   vat_main_t *vam = &vat_main;
1301   vat_json_node_t node;
1302   vl_api_thread_data_t *td;
1303   i32 retval = ntohl (mp->retval);
1304   int i, count = 0;
1305
1306   if (retval >= 0)
1307     count = ntohl (mp->count);
1308
1309   vat_json_init_object (&node);
1310   vat_json_object_add_int (&node, "retval", retval);
1311   vat_json_object_add_uint (&node, "count", count);
1312
1313   for (i = 0; i < count; i++)
1314     {
1315       td = &mp->thread_data[i];
1316       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1317       vat_json_object_add_string_copy (&node, "name", td->name);
1318       vat_json_object_add_string_copy (&node, "type", td->type);
1319       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1320       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1321       vat_json_object_add_int (&node, "core", ntohl (td->id));
1322       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1323     }
1324
1325   vat_json_print (vam->ofp, &node);
1326   vat_json_free (&node);
1327
1328   vam->retval = retval;
1329   vam->result_ready = 1;
1330 }
1331
1332 static int
1333 api_show_threads (vat_main_t * vam)
1334 {
1335   vl_api_show_threads_t *mp;
1336   int ret;
1337
1338   print (vam->ofp,
1339          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1340          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1341
1342   M (SHOW_THREADS, mp);
1343
1344   S (mp);
1345   W (ret);
1346   return ret;
1347 }
1348
1349 static void
1350 vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
1351 {
1352   u32 n_macs = ntohl (mp->n_macs);
1353   errmsg ("L2MAC event received with pid %d cl-idx %d for %d macs: \n",
1354           ntohl (mp->pid), mp->client_index, n_macs);
1355   int i;
1356   for (i = 0; i < n_macs; i++)
1357     {
1358       vl_api_mac_entry_t *mac = &mp->mac[i];
1359       errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
1360               i + 1, ntohl (mac->sw_if_index),
1361               format_ethernet_address, mac->mac_addr, mac->action);
1362       if (i == 1000)
1363         break;
1364     }
1365 }
1366
1367 static void
1368 vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
1369 {
1370   /* JSON output not supported */
1371 }
1372
1373 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1374 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1375
1376 /*
1377  * Special-case: build the bridge domain table, maintain
1378  * the next bd id vbl.
1379  */
1380 static void vl_api_bridge_domain_details_t_handler
1381   (vl_api_bridge_domain_details_t * mp)
1382 {
1383   vat_main_t *vam = &vat_main;
1384   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1385   int i;
1386
1387   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
1388          " ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
1389
1390   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
1391          ntohl (mp->bd_id), mp->learn, mp->forward,
1392          mp->flood, ntohl (mp->bvi_sw_if_index),
1393          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1394
1395   if (n_sw_ifs)
1396     {
1397       vl_api_bridge_domain_sw_if_t *sw_ifs;
1398       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1399              "Interface Name");
1400
1401       sw_ifs = mp->sw_if_details;
1402       for (i = 0; i < n_sw_ifs; i++)
1403         {
1404           u8 *sw_if_name = 0;
1405           u32 sw_if_index;
1406           hash_pair_t *p;
1407
1408           sw_if_index = ntohl (sw_ifs->sw_if_index);
1409
1410           /* *INDENT-OFF* */
1411           hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1412                              ({
1413                                if ((u32) p->value[0] == sw_if_index)
1414                                  {
1415                                    sw_if_name = (u8 *)(p->key);
1416                                    break;
1417                                  }
1418                              }));
1419           /* *INDENT-ON* */
1420           print (vam->ofp, "%7d     %3d  %s", sw_if_index,
1421                  sw_ifs->shg, sw_if_name ? (char *) sw_if_name :
1422                  "sw_if_index not found!");
1423
1424           sw_ifs++;
1425         }
1426     }
1427 }
1428
1429 static void vl_api_bridge_domain_details_t_handler_json
1430   (vl_api_bridge_domain_details_t * mp)
1431 {
1432   vat_main_t *vam = &vat_main;
1433   vat_json_node_t *node, *array = NULL;
1434   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1435
1436   if (VAT_JSON_ARRAY != vam->json_tree.type)
1437     {
1438       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1439       vat_json_init_array (&vam->json_tree);
1440     }
1441   node = vat_json_array_add (&vam->json_tree);
1442
1443   vat_json_init_object (node);
1444   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
1445   vat_json_object_add_uint (node, "flood", mp->flood);
1446   vat_json_object_add_uint (node, "forward", mp->forward);
1447   vat_json_object_add_uint (node, "learn", mp->learn);
1448   vat_json_object_add_uint (node, "bvi_sw_if_index",
1449                             ntohl (mp->bvi_sw_if_index));
1450   vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs);
1451   array = vat_json_object_add (node, "sw_if");
1452   vat_json_init_array (array);
1453
1454
1455
1456   if (n_sw_ifs)
1457     {
1458       vl_api_bridge_domain_sw_if_t *sw_ifs;
1459       int i;
1460
1461       sw_ifs = mp->sw_if_details;
1462       for (i = 0; i < n_sw_ifs; i++)
1463         {
1464           node = vat_json_array_add (array);
1465           vat_json_init_object (node);
1466           vat_json_object_add_uint (node, "sw_if_index",
1467                                     ntohl (sw_ifs->sw_if_index));
1468           vat_json_object_add_uint (node, "shg", sw_ifs->shg);
1469           sw_ifs++;
1470         }
1471     }
1472 }
1473
1474 static void vl_api_control_ping_reply_t_handler
1475   (vl_api_control_ping_reply_t * mp)
1476 {
1477   vat_main_t *vam = &vat_main;
1478   i32 retval = ntohl (mp->retval);
1479   if (vam->async_mode)
1480     {
1481       vam->async_errors += (retval < 0);
1482     }
1483   else
1484     {
1485       vam->retval = retval;
1486       vam->result_ready = 1;
1487     }
1488   if (vam->socket_client_main)
1489     vam->socket_client_main->control_pings_outstanding--;
1490 }
1491
1492 static void vl_api_control_ping_reply_t_handler_json
1493   (vl_api_control_ping_reply_t * mp)
1494 {
1495   vat_main_t *vam = &vat_main;
1496   i32 retval = ntohl (mp->retval);
1497
1498   if (VAT_JSON_NONE != vam->json_tree.type)
1499     {
1500       vat_json_print (vam->ofp, &vam->json_tree);
1501       vat_json_free (&vam->json_tree);
1502       vam->json_tree.type = VAT_JSON_NONE;
1503     }
1504   else
1505     {
1506       /* just print [] */
1507       vat_json_init_array (&vam->json_tree);
1508       vat_json_print (vam->ofp, &vam->json_tree);
1509       vam->json_tree.type = VAT_JSON_NONE;
1510     }
1511
1512   vam->retval = retval;
1513   vam->result_ready = 1;
1514 }
1515
1516 static void
1517   vl_api_bridge_domain_set_mac_age_reply_t_handler
1518   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1519 {
1520   vat_main_t *vam = &vat_main;
1521   i32 retval = ntohl (mp->retval);
1522   if (vam->async_mode)
1523     {
1524       vam->async_errors += (retval < 0);
1525     }
1526   else
1527     {
1528       vam->retval = retval;
1529       vam->result_ready = 1;
1530     }
1531 }
1532
1533 static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json
1534   (vl_api_bridge_domain_set_mac_age_reply_t * mp)
1535 {
1536   vat_main_t *vam = &vat_main;
1537   vat_json_node_t node;
1538
1539   vat_json_init_object (&node);
1540   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1541
1542   vat_json_print (vam->ofp, &node);
1543   vat_json_free (&node);
1544
1545   vam->retval = ntohl (mp->retval);
1546   vam->result_ready = 1;
1547 }
1548
1549 static void
1550 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp)
1551 {
1552   vat_main_t *vam = &vat_main;
1553   i32 retval = ntohl (mp->retval);
1554   if (vam->async_mode)
1555     {
1556       vam->async_errors += (retval < 0);
1557     }
1558   else
1559     {
1560       vam->retval = retval;
1561       vam->result_ready = 1;
1562     }
1563 }
1564
1565 static void vl_api_l2_flags_reply_t_handler_json
1566   (vl_api_l2_flags_reply_t * mp)
1567 {
1568   vat_main_t *vam = &vat_main;
1569   vat_json_node_t node;
1570
1571   vat_json_init_object (&node);
1572   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1573   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1574                             ntohl (mp->resulting_feature_bitmap));
1575
1576   vat_json_print (vam->ofp, &node);
1577   vat_json_free (&node);
1578
1579   vam->retval = ntohl (mp->retval);
1580   vam->result_ready = 1;
1581 }
1582
1583 static void vl_api_bridge_flags_reply_t_handler
1584   (vl_api_bridge_flags_reply_t * mp)
1585 {
1586   vat_main_t *vam = &vat_main;
1587   i32 retval = ntohl (mp->retval);
1588   if (vam->async_mode)
1589     {
1590       vam->async_errors += (retval < 0);
1591     }
1592   else
1593     {
1594       vam->retval = retval;
1595       vam->result_ready = 1;
1596     }
1597 }
1598
1599 static void vl_api_bridge_flags_reply_t_handler_json
1600   (vl_api_bridge_flags_reply_t * mp)
1601 {
1602   vat_main_t *vam = &vat_main;
1603   vat_json_node_t node;
1604
1605   vat_json_init_object (&node);
1606   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1607   vat_json_object_add_uint (&node, "resulting_feature_bitmap",
1608                             ntohl (mp->resulting_feature_bitmap));
1609
1610   vat_json_print (vam->ofp, &node);
1611   vat_json_free (&node);
1612
1613   vam->retval = ntohl (mp->retval);
1614   vam->result_ready = 1;
1615 }
1616
1617 static void
1618 vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp)
1619 {
1620   vat_main_t *vam = &vat_main;
1621   i32 retval = ntohl (mp->retval);
1622   if (vam->async_mode)
1623     {
1624       vam->async_errors += (retval < 0);
1625     }
1626   else
1627     {
1628       vam->retval = retval;
1629       vam->sw_if_index = ntohl (mp->sw_if_index);
1630       vam->result_ready = 1;
1631     }
1632
1633 }
1634
1635 static void vl_api_tap_create_v2_reply_t_handler_json
1636   (vl_api_tap_create_v2_reply_t * mp)
1637 {
1638   vat_main_t *vam = &vat_main;
1639   vat_json_node_t node;
1640
1641   vat_json_init_object (&node);
1642   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1643   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1644
1645   vat_json_print (vam->ofp, &node);
1646   vat_json_free (&node);
1647
1648   vam->retval = ntohl (mp->retval);
1649   vam->result_ready = 1;
1650
1651 }
1652
1653 static void
1654 vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp)
1655 {
1656   vat_main_t *vam = &vat_main;
1657   i32 retval = ntohl (mp->retval);
1658   if (vam->async_mode)
1659     {
1660       vam->async_errors += (retval < 0);
1661     }
1662   else
1663     {
1664       vam->retval = retval;
1665       vam->result_ready = 1;
1666     }
1667 }
1668
1669 static void vl_api_tap_delete_v2_reply_t_handler_json
1670   (vl_api_tap_delete_v2_reply_t * mp)
1671 {
1672   vat_main_t *vam = &vat_main;
1673   vat_json_node_t node;
1674
1675   vat_json_init_object (&node);
1676   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1677
1678   vat_json_print (vam->ofp, &node);
1679   vat_json_free (&node);
1680
1681   vam->retval = ntohl (mp->retval);
1682   vam->result_ready = 1;
1683 }
1684
1685 static void
1686 vl_api_virtio_pci_create_reply_t_handler (vl_api_virtio_pci_create_reply_t *
1687                                           mp)
1688 {
1689   vat_main_t *vam = &vat_main;
1690   i32 retval = ntohl (mp->retval);
1691   if (vam->async_mode)
1692     {
1693       vam->async_errors += (retval < 0);
1694     }
1695   else
1696     {
1697       vam->retval = retval;
1698       vam->sw_if_index = ntohl (mp->sw_if_index);
1699       vam->result_ready = 1;
1700     }
1701 }
1702
1703 static void vl_api_virtio_pci_create_reply_t_handler_json
1704   (vl_api_virtio_pci_create_reply_t * mp)
1705 {
1706   vat_main_t *vam = &vat_main;
1707   vat_json_node_t node;
1708
1709   vat_json_init_object (&node);
1710   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1711   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1712
1713   vat_json_print (vam->ofp, &node);
1714   vat_json_free (&node);
1715
1716   vam->retval = ntohl (mp->retval);
1717   vam->result_ready = 1;
1718
1719 }
1720
1721 static void
1722   vl_api_virtio_pci_create_v2_reply_t_handler
1723   (vl_api_virtio_pci_create_v2_reply_t * mp)
1724 {
1725   vat_main_t *vam = &vat_main;
1726   i32 retval = ntohl (mp->retval);
1727   if (vam->async_mode)
1728     {
1729       vam->async_errors += (retval < 0);
1730     }
1731   else
1732     {
1733       vam->retval = retval;
1734       vam->sw_if_index = ntohl (mp->sw_if_index);
1735       vam->result_ready = 1;
1736     }
1737 }
1738
1739 static void vl_api_virtio_pci_create_v2_reply_t_handler_json
1740   (vl_api_virtio_pci_create_v2_reply_t * mp)
1741 {
1742   vat_main_t *vam = &vat_main;
1743   vat_json_node_t node;
1744
1745   vat_json_init_object (&node);
1746   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1747   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1748
1749   vat_json_print (vam->ofp, &node);
1750   vat_json_free (&node);
1751
1752   vam->retval = ntohl (mp->retval);
1753   vam->result_ready = 1;
1754 }
1755
1756 static void
1757 vl_api_virtio_pci_delete_reply_t_handler (vl_api_virtio_pci_delete_reply_t *
1758                                           mp)
1759 {
1760   vat_main_t *vam = &vat_main;
1761   i32 retval = ntohl (mp->retval);
1762   if (vam->async_mode)
1763     {
1764       vam->async_errors += (retval < 0);
1765     }
1766   else
1767     {
1768       vam->retval = retval;
1769       vam->result_ready = 1;
1770     }
1771 }
1772
1773 static void vl_api_virtio_pci_delete_reply_t_handler_json
1774   (vl_api_virtio_pci_delete_reply_t * mp)
1775 {
1776   vat_main_t *vam = &vat_main;
1777   vat_json_node_t node;
1778
1779   vat_json_init_object (&node);
1780   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1781
1782   vat_json_print (vam->ofp, &node);
1783   vat_json_free (&node);
1784
1785   vam->retval = ntohl (mp->retval);
1786   vam->result_ready = 1;
1787 }
1788
1789 static void
1790 vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
1791 {
1792   vat_main_t *vam = &vat_main;
1793   i32 retval = ntohl (mp->retval);
1794
1795   if (vam->async_mode)
1796     {
1797       vam->async_errors += (retval < 0);
1798     }
1799   else
1800     {
1801       vam->retval = retval;
1802       vam->sw_if_index = ntohl (mp->sw_if_index);
1803       vam->result_ready = 1;
1804     }
1805 }
1806
1807 static void vl_api_bond_create_reply_t_handler_json
1808   (vl_api_bond_create_reply_t * mp)
1809 {
1810   vat_main_t *vam = &vat_main;
1811   vat_json_node_t node;
1812
1813   vat_json_init_object (&node);
1814   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1815   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1816
1817   vat_json_print (vam->ofp, &node);
1818   vat_json_free (&node);
1819
1820   vam->retval = ntohl (mp->retval);
1821   vam->result_ready = 1;
1822 }
1823
1824 static void
1825 vl_api_bond_create2_reply_t_handler (vl_api_bond_create2_reply_t * mp)
1826 {
1827   vat_main_t *vam = &vat_main;
1828   i32 retval = ntohl (mp->retval);
1829
1830   if (vam->async_mode)
1831     {
1832       vam->async_errors += (retval < 0);
1833     }
1834   else
1835     {
1836       vam->retval = retval;
1837       vam->sw_if_index = ntohl (mp->sw_if_index);
1838       vam->result_ready = 1;
1839     }
1840 }
1841
1842 static void vl_api_bond_create2_reply_t_handler_json
1843   (vl_api_bond_create2_reply_t * mp)
1844 {
1845   vat_main_t *vam = &vat_main;
1846   vat_json_node_t node;
1847
1848   vat_json_init_object (&node);
1849   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1850   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
1851
1852   vat_json_print (vam->ofp, &node);
1853   vat_json_free (&node);
1854
1855   vam->retval = ntohl (mp->retval);
1856   vam->result_ready = 1;
1857 }
1858
1859 static void
1860 vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
1861 {
1862   vat_main_t *vam = &vat_main;
1863   i32 retval = ntohl (mp->retval);
1864
1865   if (vam->async_mode)
1866     {
1867       vam->async_errors += (retval < 0);
1868     }
1869   else
1870     {
1871       vam->retval = retval;
1872       vam->result_ready = 1;
1873     }
1874 }
1875
1876 static void vl_api_bond_delete_reply_t_handler_json
1877   (vl_api_bond_delete_reply_t * mp)
1878 {
1879   vat_main_t *vam = &vat_main;
1880   vat_json_node_t node;
1881
1882   vat_json_init_object (&node);
1883   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1884
1885   vat_json_print (vam->ofp, &node);
1886   vat_json_free (&node);
1887
1888   vam->retval = ntohl (mp->retval);
1889   vam->result_ready = 1;
1890 }
1891
1892 static void
1893 vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t * mp)
1894 {
1895   vat_main_t *vam = &vat_main;
1896   i32 retval = ntohl (mp->retval);
1897
1898   if (vam->async_mode)
1899     {
1900       vam->async_errors += (retval < 0);
1901     }
1902   else
1903     {
1904       vam->retval = retval;
1905       vam->result_ready = 1;
1906     }
1907 }
1908
1909 static void vl_api_bond_add_member_reply_t_handler_json
1910   (vl_api_bond_add_member_reply_t * mp)
1911 {
1912   vat_main_t *vam = &vat_main;
1913   vat_json_node_t node;
1914
1915   vat_json_init_object (&node);
1916   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1917
1918   vat_json_print (vam->ofp, &node);
1919   vat_json_free (&node);
1920
1921   vam->retval = ntohl (mp->retval);
1922   vam->result_ready = 1;
1923 }
1924
1925 static void
1926 vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *
1927                                            mp)
1928 {
1929   vat_main_t *vam = &vat_main;
1930   i32 retval = ntohl (mp->retval);
1931
1932   if (vam->async_mode)
1933     {
1934       vam->async_errors += (retval < 0);
1935     }
1936   else
1937     {
1938       vam->retval = retval;
1939       vam->result_ready = 1;
1940     }
1941 }
1942
1943 static void vl_api_bond_detach_member_reply_t_handler_json
1944   (vl_api_bond_detach_member_reply_t * mp)
1945 {
1946   vat_main_t *vam = &vat_main;
1947   vat_json_node_t node;
1948
1949   vat_json_init_object (&node);
1950   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1951
1952   vat_json_print (vam->ofp, &node);
1953   vat_json_free (&node);
1954
1955   vam->retval = ntohl (mp->retval);
1956   vam->result_ready = 1;
1957 }
1958
1959 static int
1960 api_sw_interface_set_bond_weight (vat_main_t * vam)
1961 {
1962   unformat_input_t *i = vam->input;
1963   vl_api_sw_interface_set_bond_weight_t *mp;
1964   u32 sw_if_index = ~0;
1965   u32 weight = 0;
1966   u8 weight_enter = 0;
1967   int ret;
1968
1969   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1970     {
1971       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1972         ;
1973       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1974         ;
1975       else if (unformat (i, "weight %u", &weight))
1976         weight_enter = 1;
1977       else
1978         break;
1979     }
1980
1981   if (sw_if_index == ~0)
1982     {
1983       errmsg ("missing interface name or sw_if_index");
1984       return -99;
1985     }
1986   if (weight_enter == 0)
1987     {
1988       errmsg ("missing valid weight");
1989       return -99;
1990     }
1991
1992   /* Construct the API message */
1993   M (SW_INTERFACE_SET_BOND_WEIGHT, mp);
1994   mp->sw_if_index = ntohl (sw_if_index);
1995   mp->weight = ntohl (weight);
1996
1997   S (mp);
1998   W (ret);
1999   return ret;
2000 }
2001
2002 static void vl_api_sw_bond_interface_details_t_handler
2003   (vl_api_sw_bond_interface_details_t * mp)
2004 {
2005   vat_main_t *vam = &vat_main;
2006
2007   print (vam->ofp,
2008          "%-16s %-12d %-12U %-13U %-14u %-14u",
2009          mp->interface_name, ntohl (mp->sw_if_index),
2010          format_bond_mode, ntohl (mp->mode), format_bond_load_balance,
2011          ntohl (mp->lb), ntohl (mp->active_members), ntohl (mp->members));
2012 }
2013
2014 static void vl_api_sw_bond_interface_details_t_handler_json
2015   (vl_api_sw_bond_interface_details_t * mp)
2016 {
2017   vat_main_t *vam = &vat_main;
2018   vat_json_node_t *node = NULL;
2019
2020   if (VAT_JSON_ARRAY != vam->json_tree.type)
2021     {
2022       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2023       vat_json_init_array (&vam->json_tree);
2024     }
2025   node = vat_json_array_add (&vam->json_tree);
2026
2027   vat_json_init_object (node);
2028   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2029   vat_json_object_add_string_copy (node, "interface_name",
2030                                    mp->interface_name);
2031   vat_json_object_add_uint (node, "mode", ntohl (mp->mode));
2032   vat_json_object_add_uint (node, "load_balance", ntohl (mp->lb));
2033   vat_json_object_add_uint (node, "active_members",
2034                             ntohl (mp->active_members));
2035   vat_json_object_add_uint (node, "members", ntohl (mp->members));
2036 }
2037
2038 static int
2039 api_sw_bond_interface_dump (vat_main_t * vam)
2040 {
2041   unformat_input_t *i = vam->input;
2042   vl_api_sw_bond_interface_dump_t *mp;
2043   vl_api_control_ping_t *mp_ping;
2044   int ret;
2045   u32 sw_if_index = ~0;
2046
2047   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2048     {
2049       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2050         ;
2051       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2052         ;
2053       else
2054         break;
2055     }
2056
2057   print (vam->ofp,
2058          "\n%-16s %-12s %-12s %-13s %-14s %-14s",
2059          "interface name", "sw_if_index", "mode", "load balance",
2060          "active members", "members");
2061
2062   /* Get list of bond interfaces */
2063   M (SW_BOND_INTERFACE_DUMP, mp);
2064   mp->sw_if_index = ntohl (sw_if_index);
2065   S (mp);
2066
2067   /* Use a control ping for synchronization */
2068   MPING (CONTROL_PING, mp_ping);
2069   S (mp_ping);
2070
2071   W (ret);
2072   return ret;
2073 }
2074
2075 static void vl_api_sw_member_interface_details_t_handler
2076   (vl_api_sw_member_interface_details_t * mp)
2077 {
2078   vat_main_t *vam = &vat_main;
2079
2080   print (vam->ofp,
2081          "%-25s %-12d %-7d %-12d %-10d %-10d", mp->interface_name,
2082          ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout,
2083          ntohl (mp->weight), mp->is_local_numa);
2084 }
2085
2086 static void vl_api_sw_member_interface_details_t_handler_json
2087   (vl_api_sw_member_interface_details_t * mp)
2088 {
2089   vat_main_t *vam = &vat_main;
2090   vat_json_node_t *node = NULL;
2091
2092   if (VAT_JSON_ARRAY != vam->json_tree.type)
2093     {
2094       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2095       vat_json_init_array (&vam->json_tree);
2096     }
2097   node = vat_json_array_add (&vam->json_tree);
2098
2099   vat_json_init_object (node);
2100   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2101   vat_json_object_add_string_copy (node, "interface_name",
2102                                    mp->interface_name);
2103   vat_json_object_add_uint (node, "passive", mp->is_passive);
2104   vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
2105   vat_json_object_add_uint (node, "weight", ntohl (mp->weight));
2106   vat_json_object_add_uint (node, "is_local_numa", mp->is_local_numa);
2107 }
2108
2109 static int
2110 api_sw_member_interface_dump (vat_main_t * vam)
2111 {
2112   unformat_input_t *i = vam->input;
2113   vl_api_sw_member_interface_dump_t *mp;
2114   vl_api_control_ping_t *mp_ping;
2115   u32 sw_if_index = ~0;
2116   u8 sw_if_index_set = 0;
2117   int ret;
2118
2119   /* Parse args required to build the message */
2120   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2121     {
2122       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2123         sw_if_index_set = 1;
2124       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2125         sw_if_index_set = 1;
2126       else
2127         break;
2128     }
2129
2130   if (sw_if_index_set == 0)
2131     {
2132       errmsg ("missing vpp interface name. ");
2133       return -99;
2134     }
2135
2136   print (vam->ofp,
2137          "\n%-25s %-12s %-7s %-12s %-10s %-10s",
2138          "member interface name", "sw_if_index", "passive", "long_timeout",
2139          "weight", "local numa");
2140
2141   /* Get list of bond interfaces */
2142   M (SW_MEMBER_INTERFACE_DUMP, mp);
2143   mp->sw_if_index = ntohl (sw_if_index);
2144   S (mp);
2145
2146   /* Use a control ping for synchronization */
2147   MPING (CONTROL_PING, mp_ping);
2148   S (mp_ping);
2149
2150   W (ret);
2151   return ret;
2152 }
2153
2154 static void vl_api_mpls_tunnel_add_del_reply_t_handler
2155   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2156 {
2157   vat_main_t *vam = &vat_main;
2158   i32 retval = ntohl (mp->retval);
2159   if (vam->async_mode)
2160     {
2161       vam->async_errors += (retval < 0);
2162     }
2163   else
2164     {
2165       vam->retval = retval;
2166       vam->sw_if_index = ntohl (mp->sw_if_index);
2167       vam->result_ready = 1;
2168     }
2169   vam->regenerate_interface_table = 1;
2170 }
2171
2172 static void vl_api_mpls_tunnel_add_del_reply_t_handler_json
2173   (vl_api_mpls_tunnel_add_del_reply_t * mp)
2174 {
2175   vat_main_t *vam = &vat_main;
2176   vat_json_node_t node;
2177
2178   vat_json_init_object (&node);
2179   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2180   vat_json_object_add_uint (&node, "tunnel_sw_if_index",
2181                             ntohl (mp->sw_if_index));
2182
2183   vat_json_print (vam->ofp, &node);
2184   vat_json_free (&node);
2185
2186   vam->retval = ntohl (mp->retval);
2187   vam->result_ready = 1;
2188 }
2189
2190 static void vl_api_create_vhost_user_if_reply_t_handler
2191   (vl_api_create_vhost_user_if_reply_t * mp)
2192 {
2193   vat_main_t *vam = &vat_main;
2194   i32 retval = ntohl (mp->retval);
2195   if (vam->async_mode)
2196     {
2197       vam->async_errors += (retval < 0);
2198     }
2199   else
2200     {
2201       vam->retval = retval;
2202       vam->sw_if_index = ntohl (mp->sw_if_index);
2203       vam->result_ready = 1;
2204     }
2205   vam->regenerate_interface_table = 1;
2206 }
2207
2208 static void vl_api_create_vhost_user_if_reply_t_handler_json
2209   (vl_api_create_vhost_user_if_reply_t * mp)
2210 {
2211   vat_main_t *vam = &vat_main;
2212   vat_json_node_t node;
2213
2214   vat_json_init_object (&node);
2215   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2216   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2217
2218   vat_json_print (vam->ofp, &node);
2219   vat_json_free (&node);
2220
2221   vam->retval = ntohl (mp->retval);
2222   vam->result_ready = 1;
2223 }
2224
2225 static void vl_api_create_vhost_user_if_v2_reply_t_handler
2226   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2227 {
2228   vat_main_t *vam = &vat_main;
2229   i32 retval = ntohl (mp->retval);
2230   if (vam->async_mode)
2231     {
2232       vam->async_errors += (retval < 0);
2233     }
2234   else
2235     {
2236       vam->retval = retval;
2237       vam->sw_if_index = ntohl (mp->sw_if_index);
2238       vam->result_ready = 1;
2239     }
2240   vam->regenerate_interface_table = 1;
2241 }
2242
2243 static void vl_api_create_vhost_user_if_v2_reply_t_handler_json
2244   (vl_api_create_vhost_user_if_v2_reply_t * mp)
2245 {
2246   vat_main_t *vam = &vat_main;
2247   vat_json_node_t node;
2248
2249   vat_json_init_object (&node);
2250   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2251   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
2252
2253   vat_json_print (vam->ofp, &node);
2254   vat_json_free (&node);
2255
2256   vam->retval = ntohl (mp->retval);
2257   vam->result_ready = 1;
2258 }
2259
2260 static void vl_api_ip_address_details_t_handler
2261   (vl_api_ip_address_details_t * mp)
2262 {
2263   vat_main_t *vam = &vat_main;
2264   static ip_address_details_t empty_ip_address_details = { {0} };
2265   ip_address_details_t *address = NULL;
2266   ip_details_t *current_ip_details = NULL;
2267   ip_details_t *details = NULL;
2268
2269   details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
2270
2271   if (!details || vam->current_sw_if_index >= vec_len (details)
2272       || !details[vam->current_sw_if_index].present)
2273     {
2274       errmsg ("ip address details arrived but not stored");
2275       errmsg ("ip_dump should be called first");
2276       return;
2277     }
2278
2279   current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
2280
2281 #define addresses (current_ip_details->addr)
2282
2283   vec_validate_init_empty (addresses, vec_len (addresses),
2284                            empty_ip_address_details);
2285
2286   address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
2287
2288   clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
2289   address->prefix_length = mp->prefix.len;
2290 #undef addresses
2291 }
2292
2293 static void vl_api_ip_address_details_t_handler_json
2294   (vl_api_ip_address_details_t * mp)
2295 {
2296   vat_main_t *vam = &vat_main;
2297   vat_json_node_t *node = NULL;
2298
2299   if (VAT_JSON_ARRAY != vam->json_tree.type)
2300     {
2301       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2302       vat_json_init_array (&vam->json_tree);
2303     }
2304   node = vat_json_array_add (&vam->json_tree);
2305
2306   vat_json_init_object (node);
2307   vat_json_object_add_prefix (node, &mp->prefix);
2308 }
2309
2310 static void
2311 vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
2312 {
2313   vat_main_t *vam = &vat_main;
2314   static ip_details_t empty_ip_details = { 0 };
2315   ip_details_t *ip = NULL;
2316   u32 sw_if_index = ~0;
2317
2318   sw_if_index = ntohl (mp->sw_if_index);
2319
2320   vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2321                            sw_if_index, empty_ip_details);
2322
2323   ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
2324                          sw_if_index);
2325
2326   ip->present = 1;
2327 }
2328
2329 static void
2330 vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
2331 {
2332   vat_main_t *vam = &vat_main;
2333
2334   if (VAT_JSON_ARRAY != vam->json_tree.type)
2335     {
2336       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2337       vat_json_init_array (&vam->json_tree);
2338     }
2339   vat_json_array_add_uint (&vam->json_tree,
2340                            clib_net_to_host_u32 (mp->sw_if_index));
2341 }
2342
2343 static void vl_api_get_first_msg_id_reply_t_handler
2344   (vl_api_get_first_msg_id_reply_t * mp)
2345 {
2346   vat_main_t *vam = &vat_main;
2347   i32 retval = ntohl (mp->retval);
2348
2349   if (vam->async_mode)
2350     {
2351       vam->async_errors += (retval < 0);
2352     }
2353   else
2354     {
2355       vam->retval = retval;
2356       vam->result_ready = 1;
2357     }
2358   if (retval >= 0)
2359     {
2360       errmsg ("first message id %d", ntohs (mp->first_msg_id));
2361     }
2362 }
2363
2364 static void vl_api_get_first_msg_id_reply_t_handler_json
2365   (vl_api_get_first_msg_id_reply_t * mp)
2366 {
2367   vat_main_t *vam = &vat_main;
2368   vat_json_node_t node;
2369
2370   vat_json_init_object (&node);
2371   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2372   vat_json_object_add_uint (&node, "first_msg_id",
2373                             (uint) ntohs (mp->first_msg_id));
2374
2375   vat_json_print (vam->ofp, &node);
2376   vat_json_free (&node);
2377
2378   vam->retval = ntohl (mp->retval);
2379   vam->result_ready = 1;
2380 }
2381
2382 static void vl_api_get_node_graph_reply_t_handler
2383   (vl_api_get_node_graph_reply_t * mp)
2384 {
2385   vat_main_t *vam = &vat_main;
2386   i32 retval = ntohl (mp->retval);
2387   u8 *pvt_copy, *reply;
2388   void *oldheap;
2389   vlib_node_t *node;
2390   int i;
2391
2392   if (vam->async_mode)
2393     {
2394       vam->async_errors += (retval < 0);
2395     }
2396   else
2397     {
2398       vam->retval = retval;
2399       vam->result_ready = 1;
2400     }
2401
2402   /* "Should never happen..." */
2403   if (retval != 0)
2404     return;
2405
2406   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2407   pvt_copy = vec_dup (reply);
2408
2409   /* Toss the shared-memory original... */
2410   oldheap = vl_msg_push_heap ();
2411
2412   vec_free (reply);
2413
2414   vl_msg_pop_heap (oldheap);
2415
2416   if (vam->graph_nodes)
2417     {
2418       hash_free (vam->graph_node_index_by_name);
2419
2420       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2421         {
2422           node = vam->graph_nodes[0][i];
2423           vec_free (node->name);
2424           vec_free (node->next_nodes);
2425           vec_free (node);
2426         }
2427       vec_free (vam->graph_nodes[0]);
2428       vec_free (vam->graph_nodes);
2429     }
2430
2431   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
2432   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
2433   vec_free (pvt_copy);
2434
2435   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
2436     {
2437       node = vam->graph_nodes[0][i];
2438       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
2439     }
2440 }
2441
2442 static void vl_api_get_node_graph_reply_t_handler_json
2443   (vl_api_get_node_graph_reply_t * mp)
2444 {
2445   vat_main_t *vam = &vat_main;
2446   void *oldheap;
2447   vat_json_node_t node;
2448   u8 *reply;
2449
2450   /* $$$$ make this real? */
2451   vat_json_init_object (&node);
2452   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2453   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
2454
2455   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
2456
2457   /* Toss the shared-memory original... */
2458   oldheap = vl_msg_push_heap ();
2459
2460   vec_free (reply);
2461
2462   vl_msg_pop_heap (oldheap);
2463
2464   vat_json_print (vam->ofp, &node);
2465   vat_json_free (&node);
2466
2467   vam->retval = ntohl (mp->retval);
2468   vam->result_ready = 1;
2469 }
2470
2471 static u8 *
2472 format_policer_type (u8 * s, va_list * va)
2473 {
2474   u32 i = va_arg (*va, u32);
2475
2476   if (i == QOS_POLICER_TYPE_1R2C)
2477     s = format (s, "1r2c");
2478   else if (i == QOS_POLICER_TYPE_1R3C_RFC_2697)
2479     s = format (s, "1r3c");
2480   else if (i == QOS_POLICER_TYPE_2R3C_RFC_2698)
2481     s = format (s, "2r3c-2698");
2482   else if (i == QOS_POLICER_TYPE_2R3C_RFC_4115)
2483     s = format (s, "2r3c-4115");
2484   else if (i == QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
2485     s = format (s, "2r3c-mef5cf1");
2486   else
2487     s = format (s, "ILLEGAL");
2488   return s;
2489 }
2490
2491 static u8 *
2492 format_policer_rate_type (u8 * s, va_list * va)
2493 {
2494   u32 i = va_arg (*va, u32);
2495
2496   if (i == QOS_RATE_KBPS)
2497     s = format (s, "kbps");
2498   else if (i == QOS_RATE_PPS)
2499     s = format (s, "pps");
2500   else
2501     s = format (s, "ILLEGAL");
2502   return s;
2503 }
2504
2505 static u8 *
2506 format_policer_round_type (u8 * s, va_list * va)
2507 {
2508   u32 i = va_arg (*va, u32);
2509
2510   if (i == QOS_ROUND_TO_CLOSEST)
2511     s = format (s, "closest");
2512   else if (i == QOS_ROUND_TO_UP)
2513     s = format (s, "up");
2514   else if (i == QOS_ROUND_TO_DOWN)
2515     s = format (s, "down");
2516   else
2517     s = format (s, "ILLEGAL");
2518   return s;
2519 }
2520
2521 static u8 *
2522 format_policer_action_type (u8 * s, va_list * va)
2523 {
2524   u32 i = va_arg (*va, u32);
2525
2526   if (i == QOS_ACTION_DROP)
2527     s = format (s, "drop");
2528   else if (i == QOS_ACTION_TRANSMIT)
2529     s = format (s, "transmit");
2530   else if (i == QOS_ACTION_MARK_AND_TRANSMIT)
2531     s = format (s, "mark-and-transmit");
2532   else
2533     s = format (s, "ILLEGAL");
2534   return s;
2535 }
2536
2537 static u8 *
2538 format_dscp (u8 * s, va_list * va)
2539 {
2540   u32 i = va_arg (*va, u32);
2541   char *t = 0;
2542
2543   switch (i)
2544     {
2545 #define _(v, f)                                                               \
2546   case IP_DSCP_##f:                                                           \
2547     return (format (s, "%s", #f));
2548       foreach_ip_dscp
2549 #undef _
2550     }
2551   s = format (s, "%s", t);
2552   return (format (s, "ILLEGAL"));
2553 }
2554
2555 static void
2556 vl_api_policer_details_t_handler (vl_api_policer_details_t * mp)
2557 {
2558   vat_main_t *vam = &vat_main;
2559   u8 *conform_dscp_str, *exceed_dscp_str, *violate_dscp_str;
2560
2561   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2562     conform_dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2563   else
2564     conform_dscp_str = format (0, "");
2565
2566   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2567     exceed_dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2568   else
2569     exceed_dscp_str = format (0, "");
2570
2571   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2572     violate_dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2573   else
2574     violate_dscp_str = format (0, "");
2575
2576   print (vam->ofp, "Name \"%s\", type %U, cir %u, eir %u, cb %u, eb %u, "
2577          "rate type %U, round type %U, %s rate, %s color-aware, "
2578          "cir %u tok/period, pir %u tok/period, scale %u, cur lim %u, "
2579          "cur bkt %u, ext lim %u, ext bkt %u, last update %llu"
2580          "conform action %U%s, exceed action %U%s, violate action %U%s",
2581          mp->name,
2582          format_policer_type, mp->type,
2583          ntohl (mp->cir),
2584          ntohl (mp->eir),
2585          clib_net_to_host_u64 (mp->cb),
2586          clib_net_to_host_u64 (mp->eb),
2587          format_policer_rate_type, mp->rate_type,
2588          format_policer_round_type, mp->round_type,
2589          mp->single_rate ? "single" : "dual",
2590          mp->color_aware ? "is" : "not",
2591          ntohl (mp->cir_tokens_per_period),
2592          ntohl (mp->pir_tokens_per_period),
2593          ntohl (mp->scale),
2594          ntohl (mp->current_limit),
2595          ntohl (mp->current_bucket),
2596          ntohl (mp->extended_limit),
2597          ntohl (mp->extended_bucket),
2598          clib_net_to_host_u64 (mp->last_update_time),
2599          format_policer_action_type, mp->conform_action.type,
2600          conform_dscp_str,
2601          format_policer_action_type, mp->exceed_action.type,
2602          exceed_dscp_str,
2603          format_policer_action_type, mp->violate_action.type,
2604          violate_dscp_str);
2605
2606   vec_free (conform_dscp_str);
2607   vec_free (exceed_dscp_str);
2608   vec_free (violate_dscp_str);
2609 }
2610
2611 static void vl_api_policer_details_t_handler_json
2612   (vl_api_policer_details_t * mp)
2613 {
2614   vat_main_t *vam = &vat_main;
2615   vat_json_node_t *node;
2616   u8 *rate_type_str, *round_type_str, *type_str;
2617   u8 *conform_action_str, *exceed_action_str, *violate_action_str;
2618
2619   rate_type_str = format (0, "%U", format_policer_rate_type, mp->rate_type);
2620   round_type_str =
2621     format (0, "%U", format_policer_round_type, mp->round_type);
2622   type_str = format (0, "%U", format_policer_type, mp->type);
2623   conform_action_str = format (0, "%U", format_policer_action_type,
2624                                mp->conform_action.type);
2625   exceed_action_str = format (0, "%U", format_policer_action_type,
2626                               mp->exceed_action.type);
2627   violate_action_str = format (0, "%U", format_policer_action_type,
2628                                mp->violate_action.type);
2629
2630   if (VAT_JSON_ARRAY != vam->json_tree.type)
2631     {
2632       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2633       vat_json_init_array (&vam->json_tree);
2634     }
2635   node = vat_json_array_add (&vam->json_tree);
2636
2637   vat_json_init_object (node);
2638   vat_json_object_add_string_copy (node, "name", mp->name);
2639   vat_json_object_add_uint (node, "cir", ntohl (mp->cir));
2640   vat_json_object_add_uint (node, "eir", ntohl (mp->eir));
2641   vat_json_object_add_uint (node, "cb", clib_net_to_host_u64 (mp->cb));
2642   vat_json_object_add_uint (node, "eb", clib_net_to_host_u64 (mp->eb));
2643   vat_json_object_add_string_copy (node, "rate_type", rate_type_str);
2644   vat_json_object_add_string_copy (node, "round_type", round_type_str);
2645   vat_json_object_add_string_copy (node, "type", type_str);
2646   vat_json_object_add_uint (node, "single_rate", mp->single_rate);
2647   vat_json_object_add_uint (node, "color_aware", mp->color_aware);
2648   vat_json_object_add_uint (node, "scale", ntohl (mp->scale));
2649   vat_json_object_add_uint (node, "cir_tokens_per_period",
2650                             ntohl (mp->cir_tokens_per_period));
2651   vat_json_object_add_uint (node, "eir_tokens_per_period",
2652                             ntohl (mp->pir_tokens_per_period));
2653   vat_json_object_add_uint (node, "current_limit", ntohl (mp->current_limit));
2654   vat_json_object_add_uint (node, "current_bucket",
2655                             ntohl (mp->current_bucket));
2656   vat_json_object_add_uint (node, "extended_limit",
2657                             ntohl (mp->extended_limit));
2658   vat_json_object_add_uint (node, "extended_bucket",
2659                             ntohl (mp->extended_bucket));
2660   vat_json_object_add_uint (node, "last_update_time",
2661                             ntohl (mp->last_update_time));
2662   vat_json_object_add_string_copy (node, "conform_action",
2663                                    conform_action_str);
2664   if (mp->conform_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2665     {
2666       u8 *dscp_str = format (0, "%U", format_dscp, mp->conform_action.dscp);
2667       vat_json_object_add_string_copy (node, "conform_dscp", dscp_str);
2668       vec_free (dscp_str);
2669     }
2670   vat_json_object_add_string_copy (node, "exceed_action", exceed_action_str);
2671   if (mp->exceed_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2672     {
2673       u8 *dscp_str = format (0, "%U", format_dscp, mp->exceed_action.dscp);
2674       vat_json_object_add_string_copy (node, "exceed_dscp", dscp_str);
2675       vec_free (dscp_str);
2676     }
2677   vat_json_object_add_string_copy (node, "violate_action",
2678                                    violate_action_str);
2679   if (mp->violate_action.type == SSE2_QOS_ACTION_API_MARK_AND_TRANSMIT)
2680     {
2681       u8 *dscp_str = format (0, "%U", format_dscp, mp->violate_action.dscp);
2682       vat_json_object_add_string_copy (node, "violate_dscp", dscp_str);
2683       vec_free (dscp_str);
2684     }
2685
2686   vec_free (rate_type_str);
2687   vec_free (round_type_str);
2688   vec_free (type_str);
2689   vec_free (conform_action_str);
2690   vec_free (exceed_action_str);
2691   vec_free (violate_action_str);
2692 }
2693
2694 static void vl_api_policer_add_del_reply_t_handler
2695   (vl_api_policer_add_del_reply_t * mp)
2696 {
2697   vat_main_t *vam = &vat_main;
2698   i32 retval = ntohl (mp->retval);
2699   if (vam->async_mode)
2700     {
2701       vam->async_errors += (retval < 0);
2702     }
2703   else
2704     {
2705       vam->retval = retval;
2706       vam->result_ready = 1;
2707       if (retval == 0 && mp->policer_index != 0xFFFFFFFF)
2708         /*
2709          * Note: this is just barely thread-safe, depends on
2710          * the main thread spinning waiting for an answer...
2711          */
2712         errmsg ("policer index %d", ntohl (mp->policer_index));
2713     }
2714 }
2715
2716 static void vl_api_policer_add_del_reply_t_handler_json
2717   (vl_api_policer_add_del_reply_t * mp)
2718 {
2719   vat_main_t *vam = &vat_main;
2720   vat_json_node_t node;
2721
2722   vat_json_init_object (&node);
2723   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2724   vat_json_object_add_uint (&node, "policer_index",
2725                             ntohl (mp->policer_index));
2726
2727   vat_json_print (vam->ofp, &node);
2728   vat_json_free (&node);
2729
2730   vam->retval = ntohl (mp->retval);
2731   vam->result_ready = 1;
2732 }
2733
2734 /* Format hex dump. */
2735 u8 *
2736 format_hex_bytes (u8 * s, va_list * va)
2737 {
2738   u8 *bytes = va_arg (*va, u8 *);
2739   int n_bytes = va_arg (*va, int);
2740   uword i;
2741
2742   /* Print short or long form depending on byte count. */
2743   uword short_form = n_bytes <= 32;
2744   u32 indent = format_get_indent (s);
2745
2746   if (n_bytes == 0)
2747     return s;
2748
2749   for (i = 0; i < n_bytes; i++)
2750     {
2751       if (!short_form && (i % 32) == 0)
2752         s = format (s, "%08x: ", i);
2753       s = format (s, "%02x", bytes[i]);
2754       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
2755         s = format (s, "\n%U", format_white_space, indent);
2756     }
2757
2758   return s;
2759 }
2760
2761 static void vl_api_pg_create_interface_reply_t_handler
2762   (vl_api_pg_create_interface_reply_t * mp)
2763 {
2764   vat_main_t *vam = &vat_main;
2765
2766   vam->retval = ntohl (mp->retval);
2767   vam->result_ready = 1;
2768 }
2769
2770 static void vl_api_pg_create_interface_reply_t_handler_json
2771   (vl_api_pg_create_interface_reply_t * mp)
2772 {
2773   vat_main_t *vam = &vat_main;
2774   vat_json_node_t node;
2775
2776   i32 retval = ntohl (mp->retval);
2777   if (retval == 0)
2778     {
2779       vat_json_init_object (&node);
2780
2781       vat_json_object_add_int (&node, "sw_if_index", ntohl (mp->sw_if_index));
2782
2783       vat_json_print (vam->ofp, &node);
2784       vat_json_free (&node);
2785     }
2786   vam->retval = ntohl (mp->retval);
2787   vam->result_ready = 1;
2788 }
2789
2790 /*
2791  * Generate boilerplate reply handlers, which
2792  * dig the return value out of the xxx_reply_t API message,
2793  * stick it into vam->retval, and set vam->result_ready
2794  *
2795  * Could also do this by pointing N message decode slots at
2796  * a single function, but that could break in subtle ways.
2797  */
2798
2799 #define foreach_standard_reply_retval_handler           \
2800 _(sw_interface_set_flags_reply)                         \
2801 _(sw_interface_add_del_address_reply)                   \
2802 _(sw_interface_set_rx_mode_reply)                       \
2803 _(sw_interface_set_rx_placement_reply)                  \
2804 _(sw_interface_set_table_reply)                         \
2805 _(sw_interface_set_mpls_enable_reply)                   \
2806 _(sw_interface_set_vpath_reply)                         \
2807 _(sw_interface_set_l2_bridge_reply)                     \
2808 _(sw_interface_set_bond_weight_reply)                   \
2809 _(bridge_domain_add_del_reply)                          \
2810 _(sw_interface_set_l2_xconnect_reply)                   \
2811 _(l2fib_add_del_reply)                                  \
2812 _(l2fib_flush_int_reply)                                \
2813 _(l2fib_flush_bd_reply)                                 \
2814 _(ip_route_add_del_reply)                               \
2815 _(ip_table_add_del_reply)                               \
2816 _(ip_table_replace_begin_reply)                         \
2817 _(ip_table_flush_reply)                                 \
2818 _(ip_table_replace_end_reply)                           \
2819 _(ip_mroute_add_del_reply)                              \
2820 _(mpls_route_add_del_reply)                             \
2821 _(mpls_table_add_del_reply)                             \
2822 _(mpls_ip_bind_unbind_reply)                            \
2823 _(sw_interface_set_unnumbered_reply)                    \
2824 _(set_ip_flow_hash_reply)                               \
2825 _(sw_interface_ip6_enable_disable_reply)                \
2826 _(l2_patch_add_del_reply)                               \
2827 _(sr_mpls_policy_add_reply)                             \
2828 _(sr_mpls_policy_mod_reply)                             \
2829 _(sr_mpls_policy_del_reply)                             \
2830 _(sr_policy_add_reply)                                  \
2831 _(sr_policy_mod_reply)                                  \
2832 _(sr_policy_del_reply)                                  \
2833 _(sr_localsid_add_del_reply)                            \
2834 _(sr_steering_add_del_reply)                            \
2835 _(l2_fib_clear_table_reply)                             \
2836 _(l2_interface_efp_filter_reply)                        \
2837 _(l2_interface_vlan_tag_rewrite_reply)                  \
2838 _(modify_vhost_user_if_reply)                           \
2839 _(modify_vhost_user_if_v2_reply)                        \
2840 _(delete_vhost_user_if_reply)                           \
2841 _(want_l2_macs_events_reply)                            \
2842 _(ipsec_spd_add_del_reply)                              \
2843 _(ipsec_interface_add_del_spd_reply)                    \
2844 _(ipsec_spd_entry_add_del_reply)                        \
2845 _(ipsec_sad_entry_add_del_reply)                        \
2846 _(delete_loopback_reply)                                \
2847 _(bd_ip_mac_add_del_reply)                              \
2848 _(bd_ip_mac_flush_reply)                                \
2849 _(want_interface_events_reply)                          \
2850 _(sw_interface_clear_stats_reply)                       \
2851 _(ioam_enable_reply)                                    \
2852 _(ioam_disable_reply)                                   \
2853 _(af_packet_delete_reply)                               \
2854 _(set_ipfix_exporter_reply)                             \
2855 _(set_ipfix_classify_stream_reply)                      \
2856 _(ipfix_classify_table_add_del_reply)                   \
2857 _(sw_interface_span_enable_disable_reply)               \
2858 _(pg_capture_reply)                                     \
2859 _(pg_enable_disable_reply)                              \
2860 _(pg_interface_enable_disable_coalesce_reply)           \
2861 _(ip_source_and_port_range_check_add_del_reply)         \
2862 _(ip_source_and_port_range_check_interface_add_del_reply)\
2863 _(delete_subif_reply)                                   \
2864 _(l2_interface_pbb_tag_rewrite_reply)                   \
2865 _(set_punt_reply)                                       \
2866 _(feature_enable_disable_reply)                         \
2867 _(feature_gso_enable_disable_reply)                     \
2868 _(sw_interface_tag_add_del_reply)                       \
2869 _(sw_interface_add_del_mac_address_reply)               \
2870 _(hw_interface_set_mtu_reply)                           \
2871 _(p2p_ethernet_add_reply)                               \
2872 _(p2p_ethernet_del_reply)                               \
2873 _(tcp_configure_src_addresses_reply)                    \
2874 _(session_rule_add_del_reply)                           \
2875 _(ip_container_proxy_add_del_reply)                     \
2876 _(qos_record_enable_disable_reply)                      \
2877 _(flow_add_reply)
2878
2879 #define _(n)                                    \
2880     static void vl_api_##n##_t_handler          \
2881     (vl_api_##n##_t * mp)                       \
2882     {                                           \
2883         vat_main_t * vam = &vat_main;           \
2884         i32 retval = ntohl(mp->retval);         \
2885         if (vam->async_mode) {                  \
2886             vam->async_errors += (retval < 0);  \
2887         } else {                                \
2888             vam->retval = retval;               \
2889             vam->result_ready = 1;              \
2890         }                                       \
2891     }
2892 foreach_standard_reply_retval_handler;
2893 #undef _
2894
2895 #define _(n)                                    \
2896     static void vl_api_##n##_t_handler_json     \
2897     (vl_api_##n##_t * mp)                       \
2898     {                                           \
2899         vat_main_t * vam = &vat_main;           \
2900         vat_json_node_t node;                   \
2901         vat_json_init_object(&node);            \
2902         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
2903         vat_json_print(vam->ofp, &node);        \
2904         vam->retval = ntohl(mp->retval);        \
2905         vam->result_ready = 1;                  \
2906     }
2907 foreach_standard_reply_retval_handler;
2908 #undef _
2909
2910 /*
2911  * Table of message reply handlers, must include boilerplate handlers
2912  * we just generated
2913  */
2914
2915 #define foreach_vpe_api_reply_msg                                       \
2916 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
2917 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
2918 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
2919 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
2920 _(CONTROL_PING_REPLY, control_ping_reply)                               \
2921 _(CLI_REPLY, cli_reply)                                                 \
2922 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
2923 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
2924   sw_interface_add_del_address_reply)                                   \
2925 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
2926 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
2927 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
2928 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
2929 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
2930 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
2931 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
2932   sw_interface_set_l2_xconnect_reply)                                   \
2933 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
2934   sw_interface_set_l2_bridge_reply)                                     \
2935 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
2936 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
2937 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
2938 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
2939 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
2940 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
2941 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
2942 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
2943 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
2944 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
2945 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
2946 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
2947 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
2948 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
2949 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
2950 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
2951 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
2952 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
2953 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
2954 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
2955 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
2956 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
2957 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
2958 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
2959 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
2960 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
2961 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
2962 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
2963 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
2964 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
2965 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
2966 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
2967 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
2968 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
2969   sw_interface_set_unnumbered_reply)                                    \
2970 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
2971 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
2972 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
2973 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
2974   sw_interface_ip6_enable_disable_reply)                                \
2975 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
2976 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
2977 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
2978 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
2979 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
2980 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
2981 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
2982 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
2983 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
2984 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
2985 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
2986 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
2987 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
2988 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
2989 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
2990 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
2991 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
2992 _(CREATE_VHOST_USER_IF_V2_REPLY, create_vhost_user_if_v2_reply)         \
2993 _(MODIFY_VHOST_USER_IF_V2_REPLY, modify_vhost_user_if_v2_reply)         \
2994 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
2995 _(SHOW_VERSION_REPLY, show_version_reply)                               \
2996 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
2997 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
2998 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
2999 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
3000 _(L2_MACS_EVENT, l2_macs_event)                                         \
3001 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
3002 _(IP_DETAILS, ip_details)                                               \
3003 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
3004 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
3005 _(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
3006 _(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
3007 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
3008 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
3009 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
3010 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
3011 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
3012 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
3013 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
3014 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
3015 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
3016 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
3017 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
3018 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
3019 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
3020 _(AF_PACKET_DETAILS, af_packet_details)                                 \
3021 _(POLICER_ADD_DEL_REPLY, policer_add_del_reply)                         \
3022 _(POLICER_DETAILS, policer_details)                                     \
3023 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
3024 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
3025 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
3026 _(SET_IPFIX_EXPORTER_REPLY, set_ipfix_exporter_reply)                   \
3027 _(IPFIX_EXPORTER_DETAILS, ipfix_exporter_details)                       \
3028 _(SET_IPFIX_CLASSIFY_STREAM_REPLY, set_ipfix_classify_stream_reply)     \
3029 _(IPFIX_CLASSIFY_STREAM_DETAILS, ipfix_classify_stream_details)         \
3030 _(IPFIX_CLASSIFY_TABLE_ADD_DEL_REPLY, ipfix_classify_table_add_del_reply) \
3031 _(IPFIX_CLASSIFY_TABLE_DETAILS, ipfix_classify_table_details)           \
3032 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
3033 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
3034 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
3035 _(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply)                 \
3036 _(PG_CAPTURE_REPLY, pg_capture_reply)                                   \
3037 _(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply)                     \
3038 _(PG_INTERFACE_ENABLE_DISABLE_COALESCE_REPLY, pg_interface_enable_disable_coalesce_reply) \
3039 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
3040  ip_source_and_port_range_check_add_del_reply)                          \
3041 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
3042  ip_source_and_port_range_check_interface_add_del_reply)                \
3043 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
3044 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
3045 _(SET_PUNT_REPLY, set_punt_reply)                                       \
3046 _(IP_TABLE_DETAILS, ip_table_details)                                   \
3047 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
3048 _(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply)           \
3049 _(FEATURE_GSO_ENABLE_DISABLE_REPLY, feature_gso_enable_disable_reply)   \
3050 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
3051 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
3052 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
3053 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
3054 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
3055 _(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply)                       \
3056 _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply)                       \
3057 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
3058 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
3059 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
3060 _(SESSION_RULES_DETAILS, session_rules_details)                         \
3061 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
3062 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
3063 _(FLOW_ADD_REPLY, flow_add_reply)   \
3064
3065 #define foreach_standalone_reply_msg                                    \
3066 _(SW_INTERFACE_EVENT, sw_interface_event)
3067
3068 typedef struct
3069 {
3070   u8 *name;
3071   u32 value;
3072 } name_sort_t;
3073
3074 #define STR_VTR_OP_CASE(op)     \
3075     case L2_VTR_ ## op:         \
3076         return "" # op;
3077
3078 static const char *
3079 str_vtr_op (u32 vtr_op)
3080 {
3081   switch (vtr_op)
3082     {
3083       STR_VTR_OP_CASE (DISABLED);
3084       STR_VTR_OP_CASE (PUSH_1);
3085       STR_VTR_OP_CASE (PUSH_2);
3086       STR_VTR_OP_CASE (POP_1);
3087       STR_VTR_OP_CASE (POP_2);
3088       STR_VTR_OP_CASE (TRANSLATE_1_1);
3089       STR_VTR_OP_CASE (TRANSLATE_1_2);
3090       STR_VTR_OP_CASE (TRANSLATE_2_1);
3091       STR_VTR_OP_CASE (TRANSLATE_2_2);
3092     }
3093
3094   return "UNKNOWN";
3095 }
3096
3097 static int
3098 dump_sub_interface_table (vat_main_t * vam)
3099 {
3100   const sw_interface_subif_t *sub = NULL;
3101
3102   if (vam->json_output)
3103     {
3104       clib_warning
3105         ("JSON output supported only for VPE API calls and dump_stats_table");
3106       return -99;
3107     }
3108
3109   print (vam->ofp,
3110          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
3111          "Interface", "sw_if_index",
3112          "sub id", "dot1ad", "tags", "outer id",
3113          "inner id", "exact", "default", "outer any", "inner any");
3114
3115   vec_foreach (sub, vam->sw_if_subif_table)
3116   {
3117     print (vam->ofp,
3118            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
3119            sub->interface_name,
3120            sub->sw_if_index,
3121            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
3122            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
3123            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
3124            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
3125     if (sub->vtr_op != L2_VTR_DISABLED)
3126       {
3127         print (vam->ofp,
3128                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
3129                "tag1: %d tag2: %d ]",
3130                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
3131                sub->vtr_tag1, sub->vtr_tag2);
3132       }
3133   }
3134
3135   return 0;
3136 }
3137
3138 static int
3139 name_sort_cmp (void *a1, void *a2)
3140 {
3141   name_sort_t *n1 = a1;
3142   name_sort_t *n2 = a2;
3143
3144   return strcmp ((char *) n1->name, (char *) n2->name);
3145 }
3146
3147 static int
3148 dump_interface_table (vat_main_t * vam)
3149 {
3150   hash_pair_t *p;
3151   name_sort_t *nses = 0, *ns;
3152
3153   if (vam->json_output)
3154     {
3155       clib_warning
3156         ("JSON output supported only for VPE API calls and dump_stats_table");
3157       return -99;
3158     }
3159
3160   /* *INDENT-OFF* */
3161   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3162   ({
3163     vec_add2 (nses, ns, 1);
3164     ns->name = (u8 *)(p->key);
3165     ns->value = (u32) p->value[0];
3166   }));
3167   /* *INDENT-ON* */
3168
3169   vec_sort_with_function (nses, name_sort_cmp);
3170
3171   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
3172   vec_foreach (ns, nses)
3173   {
3174     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
3175   }
3176   vec_free (nses);
3177   return 0;
3178 }
3179
3180 static int
3181 dump_ip_table (vat_main_t * vam, int is_ipv6)
3182 {
3183   const ip_details_t *det = NULL;
3184   const ip_address_details_t *address = NULL;
3185   u32 i = ~0;
3186
3187   print (vam->ofp, "%-12s", "sw_if_index");
3188
3189   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
3190   {
3191     i++;
3192     if (!det->present)
3193       {
3194         continue;
3195       }
3196     print (vam->ofp, "%-12d", i);
3197     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
3198     if (!det->addr)
3199       {
3200         continue;
3201       }
3202     vec_foreach (address, det->addr)
3203     {
3204       print (vam->ofp,
3205              "            %-30U%-13d",
3206              is_ipv6 ? format_ip6_address : format_ip4_address,
3207              address->ip, address->prefix_length);
3208     }
3209   }
3210
3211   return 0;
3212 }
3213
3214 static int
3215 dump_ipv4_table (vat_main_t * vam)
3216 {
3217   if (vam->json_output)
3218     {
3219       clib_warning
3220         ("JSON output supported only for VPE API calls and dump_stats_table");
3221       return -99;
3222     }
3223
3224   return dump_ip_table (vam, 0);
3225 }
3226
3227 static int
3228 dump_ipv6_table (vat_main_t * vam)
3229 {
3230   if (vam->json_output)
3231     {
3232       clib_warning
3233         ("JSON output supported only for VPE API calls and dump_stats_table");
3234       return -99;
3235     }
3236
3237   return dump_ip_table (vam, 1);
3238 }
3239
3240 /*
3241  * Pass CLI buffers directly in the CLI_INBAND API message,
3242  * instead of an additional shared memory area.
3243  */
3244 static int
3245 exec_inband (vat_main_t * vam)
3246 {
3247   vl_api_cli_inband_t *mp;
3248   unformat_input_t *i = vam->input;
3249   int ret;
3250
3251   if (vec_len (i->buffer) == 0)
3252     return -1;
3253
3254   if (vam->exec_mode == 0 && unformat (i, "mode"))
3255     {
3256       vam->exec_mode = 1;
3257       return 0;
3258     }
3259   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
3260     {
3261       vam->exec_mode = 0;
3262       return 0;
3263     }
3264
3265   /*
3266    * In order for the CLI command to work, it
3267    * must be a vector ending in \n, not a C-string ending
3268    * in \n\0.
3269    */
3270   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
3271   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
3272
3273   S (mp);
3274   W (ret);
3275   /* json responses may or may not include a useful reply... */
3276   if (vec_len (vam->cmd_reply))
3277     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
3278   return ret;
3279 }
3280
3281 int
3282 exec (vat_main_t * vam)
3283 {
3284   return exec_inband (vam);
3285 }
3286
3287 static int
3288 api_create_loopback (vat_main_t * vam)
3289 {
3290   unformat_input_t *i = vam->input;
3291   vl_api_create_loopback_t *mp;
3292   vl_api_create_loopback_instance_t *mp_lbi;
3293   u8 mac_address[6];
3294   u8 mac_set = 0;
3295   u8 is_specified = 0;
3296   u32 user_instance = 0;
3297   int ret;
3298
3299   clib_memset (mac_address, 0, sizeof (mac_address));
3300
3301   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3302     {
3303       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
3304         mac_set = 1;
3305       if (unformat (i, "instance %d", &user_instance))
3306         is_specified = 1;
3307       else
3308         break;
3309     }
3310
3311   if (is_specified)
3312     {
3313       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
3314       mp_lbi->is_specified = is_specified;
3315       if (is_specified)
3316         mp_lbi->user_instance = htonl (user_instance);
3317       if (mac_set)
3318         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
3319       S (mp_lbi);
3320     }
3321   else
3322     {
3323       /* Construct the API message */
3324       M (CREATE_LOOPBACK, mp);
3325       if (mac_set)
3326         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
3327       S (mp);
3328     }
3329
3330   W (ret);
3331   return ret;
3332 }
3333
3334 static int
3335 api_delete_loopback (vat_main_t * vam)
3336 {
3337   unformat_input_t *i = vam->input;
3338   vl_api_delete_loopback_t *mp;
3339   u32 sw_if_index = ~0;
3340   int ret;
3341
3342   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3343     {
3344       if (unformat (i, "sw_if_index %d", &sw_if_index))
3345         ;
3346       else
3347         break;
3348     }
3349
3350   if (sw_if_index == ~0)
3351     {
3352       errmsg ("missing sw_if_index");
3353       return -99;
3354     }
3355
3356   /* Construct the API message */
3357   M (DELETE_LOOPBACK, mp);
3358   mp->sw_if_index = ntohl (sw_if_index);
3359
3360   S (mp);
3361   W (ret);
3362   return ret;
3363 }
3364
3365 static int
3366 api_want_interface_events (vat_main_t * vam)
3367 {
3368   unformat_input_t *i = vam->input;
3369   vl_api_want_interface_events_t *mp;
3370   int enable = -1;
3371   int ret;
3372
3373   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3374     {
3375       if (unformat (i, "enable"))
3376         enable = 1;
3377       else if (unformat (i, "disable"))
3378         enable = 0;
3379       else
3380         break;
3381     }
3382
3383   if (enable == -1)
3384     {
3385       errmsg ("missing enable|disable");
3386       return -99;
3387     }
3388
3389   M (WANT_INTERFACE_EVENTS, mp);
3390   mp->enable_disable = enable;
3391
3392   vam->interface_event_display = enable;
3393
3394   S (mp);
3395   W (ret);
3396   return ret;
3397 }
3398
3399
3400 /* Note: non-static, called once to set up the initial intfc table */
3401 int
3402 api_sw_interface_dump (vat_main_t * vam)
3403 {
3404   vl_api_sw_interface_dump_t *mp;
3405   vl_api_control_ping_t *mp_ping;
3406   hash_pair_t *p;
3407   name_sort_t *nses = 0, *ns;
3408   sw_interface_subif_t *sub = NULL;
3409   int ret;
3410
3411   /* Toss the old name table */
3412   /* *INDENT-OFF* */
3413   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3414   ({
3415     vec_add2 (nses, ns, 1);
3416     ns->name = (u8 *)(p->key);
3417     ns->value = (u32) p->value[0];
3418   }));
3419   /* *INDENT-ON* */
3420
3421   hash_free (vam->sw_if_index_by_interface_name);
3422
3423   vec_foreach (ns, nses) vec_free (ns->name);
3424
3425   vec_free (nses);
3426
3427   vec_foreach (sub, vam->sw_if_subif_table)
3428   {
3429     vec_free (sub->interface_name);
3430   }
3431   vec_free (vam->sw_if_subif_table);
3432
3433   /* recreate the interface name hash table */
3434   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3435
3436   /*
3437    * Ask for all interface names. Otherwise, the epic catalog of
3438    * name filters becomes ridiculously long, and vat ends up needing
3439    * to be taught about new interface types.
3440    */
3441   M (SW_INTERFACE_DUMP, mp);
3442   S (mp);
3443
3444   /* Use a control ping for synchronization */
3445   MPING (CONTROL_PING, mp_ping);
3446   S (mp_ping);
3447
3448   W (ret);
3449   return ret;
3450 }
3451
3452 static int
3453 api_sw_interface_set_flags (vat_main_t * vam)
3454 {
3455   unformat_input_t *i = vam->input;
3456   vl_api_sw_interface_set_flags_t *mp;
3457   u32 sw_if_index;
3458   u8 sw_if_index_set = 0;
3459   u8 admin_up = 0;
3460   int ret;
3461
3462   /* Parse args required to build the message */
3463   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3464     {
3465       if (unformat (i, "admin-up"))
3466         admin_up = 1;
3467       else if (unformat (i, "admin-down"))
3468         admin_up = 0;
3469       else
3470         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3471         sw_if_index_set = 1;
3472       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3473         sw_if_index_set = 1;
3474       else
3475         break;
3476     }
3477
3478   if (sw_if_index_set == 0)
3479     {
3480       errmsg ("missing interface name or sw_if_index");
3481       return -99;
3482     }
3483
3484   /* Construct the API message */
3485   M (SW_INTERFACE_SET_FLAGS, mp);
3486   mp->sw_if_index = ntohl (sw_if_index);
3487   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3488
3489   /* send it... */
3490   S (mp);
3491
3492   /* Wait for a reply, return the good/bad news... */
3493   W (ret);
3494   return ret;
3495 }
3496
3497 static int
3498 api_sw_interface_set_rx_mode (vat_main_t * vam)
3499 {
3500   unformat_input_t *i = vam->input;
3501   vl_api_sw_interface_set_rx_mode_t *mp;
3502   u32 sw_if_index;
3503   u8 sw_if_index_set = 0;
3504   int ret;
3505   u8 queue_id_valid = 0;
3506   u32 queue_id;
3507   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
3508
3509   /* Parse args required to build the message */
3510   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3511     {
3512       if (unformat (i, "queue %d", &queue_id))
3513         queue_id_valid = 1;
3514       else if (unformat (i, "polling"))
3515         mode = VNET_HW_IF_RX_MODE_POLLING;
3516       else if (unformat (i, "interrupt"))
3517         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
3518       else if (unformat (i, "adaptive"))
3519         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
3520       else
3521         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3522         sw_if_index_set = 1;
3523       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3524         sw_if_index_set = 1;
3525       else
3526         break;
3527     }
3528
3529   if (sw_if_index_set == 0)
3530     {
3531       errmsg ("missing interface name or sw_if_index");
3532       return -99;
3533     }
3534   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
3535     {
3536       errmsg ("missing rx-mode");
3537       return -99;
3538     }
3539
3540   /* Construct the API message */
3541   M (SW_INTERFACE_SET_RX_MODE, mp);
3542   mp->sw_if_index = ntohl (sw_if_index);
3543   mp->mode = (vl_api_rx_mode_t) mode;
3544   mp->queue_id_valid = queue_id_valid;
3545   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
3546
3547   /* send it... */
3548   S (mp);
3549
3550   /* Wait for a reply, return the good/bad news... */
3551   W (ret);
3552   return ret;
3553 }
3554
3555 static int
3556 api_sw_interface_set_rx_placement (vat_main_t * vam)
3557 {
3558   unformat_input_t *i = vam->input;
3559   vl_api_sw_interface_set_rx_placement_t *mp;
3560   u32 sw_if_index;
3561   u8 sw_if_index_set = 0;
3562   int ret;
3563   u8 is_main = 0;
3564   u32 queue_id, thread_index;
3565
3566   /* Parse args required to build the message */
3567   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3568     {
3569       if (unformat (i, "queue %d", &queue_id))
3570         ;
3571       else if (unformat (i, "main"))
3572         is_main = 1;
3573       else if (unformat (i, "worker %d", &thread_index))
3574         ;
3575       else
3576         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3577         sw_if_index_set = 1;
3578       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3579         sw_if_index_set = 1;
3580       else
3581         break;
3582     }
3583
3584   if (sw_if_index_set == 0)
3585     {
3586       errmsg ("missing interface name or sw_if_index");
3587       return -99;
3588     }
3589
3590   if (is_main)
3591     thread_index = 0;
3592   /* Construct the API message */
3593   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
3594   mp->sw_if_index = ntohl (sw_if_index);
3595   mp->worker_id = ntohl (thread_index);
3596   mp->queue_id = ntohl (queue_id);
3597   mp->is_main = is_main;
3598
3599   /* send it... */
3600   S (mp);
3601   /* Wait for a reply, return the good/bad news... */
3602   W (ret);
3603   return ret;
3604 }
3605
3606 static void vl_api_sw_interface_rx_placement_details_t_handler
3607   (vl_api_sw_interface_rx_placement_details_t * mp)
3608 {
3609   vat_main_t *vam = &vat_main;
3610   u32 worker_id = ntohl (mp->worker_id);
3611
3612   print (vam->ofp,
3613          "\n%-11d %-11s %-6d %-5d %-9s",
3614          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
3615          worker_id, ntohl (mp->queue_id),
3616          (mp->mode ==
3617           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
3618 }
3619
3620 static void vl_api_sw_interface_rx_placement_details_t_handler_json
3621   (vl_api_sw_interface_rx_placement_details_t * mp)
3622 {
3623   vat_main_t *vam = &vat_main;
3624   vat_json_node_t *node = NULL;
3625
3626   if (VAT_JSON_ARRAY != vam->json_tree.type)
3627     {
3628       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3629       vat_json_init_array (&vam->json_tree);
3630     }
3631   node = vat_json_array_add (&vam->json_tree);
3632
3633   vat_json_init_object (node);
3634   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3635   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
3636   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
3637   vat_json_object_add_uint (node, "mode", mp->mode);
3638 }
3639
3640 static int
3641 api_sw_interface_rx_placement_dump (vat_main_t * vam)
3642 {
3643   unformat_input_t *i = vam->input;
3644   vl_api_sw_interface_rx_placement_dump_t *mp;
3645   vl_api_control_ping_t *mp_ping;
3646   int ret;
3647   u32 sw_if_index;
3648   u8 sw_if_index_set = 0;
3649
3650   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3651     {
3652       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3653         sw_if_index_set++;
3654       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3655         sw_if_index_set++;
3656       else
3657         break;
3658     }
3659
3660   print (vam->ofp,
3661          "\n%-11s %-11s %-6s %-5s %-4s",
3662          "sw_if_index", "main/worker", "thread", "queue", "mode");
3663
3664   /* Dump Interface rx placement */
3665   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
3666
3667   if (sw_if_index_set)
3668     mp->sw_if_index = htonl (sw_if_index);
3669   else
3670     mp->sw_if_index = ~0;
3671
3672   S (mp);
3673
3674   /* Use a control ping for synchronization */
3675   MPING (CONTROL_PING, mp_ping);
3676   S (mp_ping);
3677
3678   W (ret);
3679   return ret;
3680 }
3681
3682 static int
3683 api_sw_interface_clear_stats (vat_main_t * vam)
3684 {
3685   unformat_input_t *i = vam->input;
3686   vl_api_sw_interface_clear_stats_t *mp;
3687   u32 sw_if_index;
3688   u8 sw_if_index_set = 0;
3689   int ret;
3690
3691   /* Parse args required to build the message */
3692   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3693     {
3694       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3695         sw_if_index_set = 1;
3696       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3697         sw_if_index_set = 1;
3698       else
3699         break;
3700     }
3701
3702   /* Construct the API message */
3703   M (SW_INTERFACE_CLEAR_STATS, mp);
3704
3705   if (sw_if_index_set == 1)
3706     mp->sw_if_index = ntohl (sw_if_index);
3707   else
3708     mp->sw_if_index = ~0;
3709
3710   /* send it... */
3711   S (mp);
3712
3713   /* Wait for a reply, return the good/bad news... */
3714   W (ret);
3715   return ret;
3716 }
3717
3718 static int
3719 api_sw_interface_add_del_address (vat_main_t * vam)
3720 {
3721   unformat_input_t *i = vam->input;
3722   vl_api_sw_interface_add_del_address_t *mp;
3723   u32 sw_if_index;
3724   u8 sw_if_index_set = 0;
3725   u8 is_add = 1, del_all = 0;
3726   u32 address_length = 0;
3727   u8 v4_address_set = 0;
3728   u8 v6_address_set = 0;
3729   ip4_address_t v4address;
3730   ip6_address_t v6address;
3731   int ret;
3732
3733   /* Parse args required to build the message */
3734   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3735     {
3736       if (unformat (i, "del-all"))
3737         del_all = 1;
3738       else if (unformat (i, "del"))
3739         is_add = 0;
3740       else
3741         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3742         sw_if_index_set = 1;
3743       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3744         sw_if_index_set = 1;
3745       else if (unformat (i, "%U/%d",
3746                          unformat_ip4_address, &v4address, &address_length))
3747         v4_address_set = 1;
3748       else if (unformat (i, "%U/%d",
3749                          unformat_ip6_address, &v6address, &address_length))
3750         v6_address_set = 1;
3751       else
3752         break;
3753     }
3754
3755   if (sw_if_index_set == 0)
3756     {
3757       errmsg ("missing interface name or sw_if_index");
3758       return -99;
3759     }
3760   if (v4_address_set && v6_address_set)
3761     {
3762       errmsg ("both v4 and v6 addresses set");
3763       return -99;
3764     }
3765   if (!v4_address_set && !v6_address_set && !del_all)
3766     {
3767       errmsg ("no addresses set");
3768       return -99;
3769     }
3770
3771   /* Construct the API message */
3772   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
3773
3774   mp->sw_if_index = ntohl (sw_if_index);
3775   mp->is_add = is_add;
3776   mp->del_all = del_all;
3777   if (v6_address_set)
3778     {
3779       mp->prefix.address.af = ADDRESS_IP6;
3780       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
3781     }
3782   else
3783     {
3784       mp->prefix.address.af = ADDRESS_IP4;
3785       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
3786     }
3787   mp->prefix.len = address_length;
3788
3789   /* send it... */
3790   S (mp);
3791
3792   /* Wait for a reply, return good/bad news  */
3793   W (ret);
3794   return ret;
3795 }
3796
3797 static int
3798 api_sw_interface_set_mpls_enable (vat_main_t * vam)
3799 {
3800   unformat_input_t *i = vam->input;
3801   vl_api_sw_interface_set_mpls_enable_t *mp;
3802   u32 sw_if_index;
3803   u8 sw_if_index_set = 0;
3804   u8 enable = 1;
3805   int ret;
3806
3807   /* Parse args required to build the message */
3808   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3809     {
3810       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3811         sw_if_index_set = 1;
3812       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3813         sw_if_index_set = 1;
3814       else if (unformat (i, "disable"))
3815         enable = 0;
3816       else if (unformat (i, "dis"))
3817         enable = 0;
3818       else
3819         break;
3820     }
3821
3822   if (sw_if_index_set == 0)
3823     {
3824       errmsg ("missing interface name or sw_if_index");
3825       return -99;
3826     }
3827
3828   /* Construct the API message */
3829   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
3830
3831   mp->sw_if_index = ntohl (sw_if_index);
3832   mp->enable = enable;
3833
3834   /* send it... */
3835   S (mp);
3836
3837   /* Wait for a reply... */
3838   W (ret);
3839   return ret;
3840 }
3841
3842 static int
3843 api_sw_interface_set_table (vat_main_t * vam)
3844 {
3845   unformat_input_t *i = vam->input;
3846   vl_api_sw_interface_set_table_t *mp;
3847   u32 sw_if_index, vrf_id = 0;
3848   u8 sw_if_index_set = 0;
3849   u8 is_ipv6 = 0;
3850   int ret;
3851
3852   /* Parse args required to build the message */
3853   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3854     {
3855       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3856         sw_if_index_set = 1;
3857       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3858         sw_if_index_set = 1;
3859       else if (unformat (i, "vrf %d", &vrf_id))
3860         ;
3861       else if (unformat (i, "ipv6"))
3862         is_ipv6 = 1;
3863       else
3864         break;
3865     }
3866
3867   if (sw_if_index_set == 0)
3868     {
3869       errmsg ("missing interface name or sw_if_index");
3870       return -99;
3871     }
3872
3873   /* Construct the API message */
3874   M (SW_INTERFACE_SET_TABLE, mp);
3875
3876   mp->sw_if_index = ntohl (sw_if_index);
3877   mp->is_ipv6 = is_ipv6;
3878   mp->vrf_id = ntohl (vrf_id);
3879
3880   /* send it... */
3881   S (mp);
3882
3883   /* Wait for a reply... */
3884   W (ret);
3885   return ret;
3886 }
3887
3888 static void vl_api_sw_interface_get_table_reply_t_handler
3889   (vl_api_sw_interface_get_table_reply_t * mp)
3890 {
3891   vat_main_t *vam = &vat_main;
3892
3893   print (vam->ofp, "%d", ntohl (mp->vrf_id));
3894
3895   vam->retval = ntohl (mp->retval);
3896   vam->result_ready = 1;
3897
3898 }
3899
3900 static void vl_api_sw_interface_get_table_reply_t_handler_json
3901   (vl_api_sw_interface_get_table_reply_t * mp)
3902 {
3903   vat_main_t *vam = &vat_main;
3904   vat_json_node_t node;
3905
3906   vat_json_init_object (&node);
3907   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
3908   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
3909
3910   vat_json_print (vam->ofp, &node);
3911   vat_json_free (&node);
3912
3913   vam->retval = ntohl (mp->retval);
3914   vam->result_ready = 1;
3915 }
3916
3917 static int
3918 api_sw_interface_get_table (vat_main_t * vam)
3919 {
3920   unformat_input_t *i = vam->input;
3921   vl_api_sw_interface_get_table_t *mp;
3922   u32 sw_if_index;
3923   u8 sw_if_index_set = 0;
3924   u8 is_ipv6 = 0;
3925   int ret;
3926
3927   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3928     {
3929       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3930         sw_if_index_set = 1;
3931       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3932         sw_if_index_set = 1;
3933       else if (unformat (i, "ipv6"))
3934         is_ipv6 = 1;
3935       else
3936         break;
3937     }
3938
3939   if (sw_if_index_set == 0)
3940     {
3941       errmsg ("missing interface name or sw_if_index");
3942       return -99;
3943     }
3944
3945   M (SW_INTERFACE_GET_TABLE, mp);
3946   mp->sw_if_index = htonl (sw_if_index);
3947   mp->is_ipv6 = is_ipv6;
3948
3949   S (mp);
3950   W (ret);
3951   return ret;
3952 }
3953
3954 static int
3955 api_sw_interface_set_vpath (vat_main_t * vam)
3956 {
3957   unformat_input_t *i = vam->input;
3958   vl_api_sw_interface_set_vpath_t *mp;
3959   u32 sw_if_index = 0;
3960   u8 sw_if_index_set = 0;
3961   u8 is_enable = 0;
3962   int ret;
3963
3964   /* Parse args required to build the message */
3965   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3966     {
3967       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3968         sw_if_index_set = 1;
3969       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3970         sw_if_index_set = 1;
3971       else if (unformat (i, "enable"))
3972         is_enable = 1;
3973       else if (unformat (i, "disable"))
3974         is_enable = 0;
3975       else
3976         break;
3977     }
3978
3979   if (sw_if_index_set == 0)
3980     {
3981       errmsg ("missing interface name or sw_if_index");
3982       return -99;
3983     }
3984
3985   /* Construct the API message */
3986   M (SW_INTERFACE_SET_VPATH, mp);
3987
3988   mp->sw_if_index = ntohl (sw_if_index);
3989   mp->enable = is_enable;
3990
3991   /* send it... */
3992   S (mp);
3993
3994   /* Wait for a reply... */
3995   W (ret);
3996   return ret;
3997 }
3998
3999 static int
4000 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
4001 {
4002   unformat_input_t *i = vam->input;
4003   vl_api_sw_interface_set_l2_xconnect_t *mp;
4004   u32 rx_sw_if_index;
4005   u8 rx_sw_if_index_set = 0;
4006   u32 tx_sw_if_index;
4007   u8 tx_sw_if_index_set = 0;
4008   u8 enable = 1;
4009   int ret;
4010
4011   /* Parse args required to build the message */
4012   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4013     {
4014       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4015         rx_sw_if_index_set = 1;
4016       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4017         tx_sw_if_index_set = 1;
4018       else if (unformat (i, "rx"))
4019         {
4020           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4021             {
4022               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4023                             &rx_sw_if_index))
4024                 rx_sw_if_index_set = 1;
4025             }
4026           else
4027             break;
4028         }
4029       else if (unformat (i, "tx"))
4030         {
4031           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4032             {
4033               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
4034                             &tx_sw_if_index))
4035                 tx_sw_if_index_set = 1;
4036             }
4037           else
4038             break;
4039         }
4040       else if (unformat (i, "enable"))
4041         enable = 1;
4042       else if (unformat (i, "disable"))
4043         enable = 0;
4044       else
4045         break;
4046     }
4047
4048   if (rx_sw_if_index_set == 0)
4049     {
4050       errmsg ("missing rx interface name or rx_sw_if_index");
4051       return -99;
4052     }
4053
4054   if (enable && (tx_sw_if_index_set == 0))
4055     {
4056       errmsg ("missing tx interface name or tx_sw_if_index");
4057       return -99;
4058     }
4059
4060   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
4061
4062   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4063   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4064   mp->enable = enable;
4065
4066   S (mp);
4067   W (ret);
4068   return ret;
4069 }
4070
4071 static int
4072 api_sw_interface_set_l2_bridge (vat_main_t * vam)
4073 {
4074   unformat_input_t *i = vam->input;
4075   vl_api_sw_interface_set_l2_bridge_t *mp;
4076   vl_api_l2_port_type_t port_type;
4077   u32 rx_sw_if_index;
4078   u8 rx_sw_if_index_set = 0;
4079   u32 bd_id;
4080   u8 bd_id_set = 0;
4081   u32 shg = 0;
4082   u8 enable = 1;
4083   int ret;
4084
4085   port_type = L2_API_PORT_TYPE_NORMAL;
4086
4087   /* Parse args required to build the message */
4088   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4089     {
4090       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
4091         rx_sw_if_index_set = 1;
4092       else if (unformat (i, "bd_id %d", &bd_id))
4093         bd_id_set = 1;
4094       else
4095         if (unformat
4096             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
4097         rx_sw_if_index_set = 1;
4098       else if (unformat (i, "shg %d", &shg))
4099         ;
4100       else if (unformat (i, "bvi"))
4101         port_type = L2_API_PORT_TYPE_BVI;
4102       else if (unformat (i, "uu-fwd"))
4103         port_type = L2_API_PORT_TYPE_UU_FWD;
4104       else if (unformat (i, "enable"))
4105         enable = 1;
4106       else if (unformat (i, "disable"))
4107         enable = 0;
4108       else
4109         break;
4110     }
4111
4112   if (rx_sw_if_index_set == 0)
4113     {
4114       errmsg ("missing rx interface name or sw_if_index");
4115       return -99;
4116     }
4117
4118   if (enable && (bd_id_set == 0))
4119     {
4120       errmsg ("missing bridge domain");
4121       return -99;
4122     }
4123
4124   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
4125
4126   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4127   mp->bd_id = ntohl (bd_id);
4128   mp->shg = (u8) shg;
4129   mp->port_type = ntohl (port_type);
4130   mp->enable = enable;
4131
4132   S (mp);
4133   W (ret);
4134   return ret;
4135 }
4136
4137 static int
4138 api_bridge_domain_dump (vat_main_t * vam)
4139 {
4140   unformat_input_t *i = vam->input;
4141   vl_api_bridge_domain_dump_t *mp;
4142   vl_api_control_ping_t *mp_ping;
4143   u32 bd_id = ~0;
4144   int ret;
4145
4146   /* Parse args required to build the message */
4147   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4148     {
4149       if (unformat (i, "bd_id %d", &bd_id))
4150         ;
4151       else
4152         break;
4153     }
4154
4155   M (BRIDGE_DOMAIN_DUMP, mp);
4156   mp->bd_id = ntohl (bd_id);
4157   S (mp);
4158
4159   /* Use a control ping for synchronization */
4160   MPING (CONTROL_PING, mp_ping);
4161   S (mp_ping);
4162
4163   W (ret);
4164   return ret;
4165 }
4166
4167 static int
4168 api_bridge_domain_add_del (vat_main_t * vam)
4169 {
4170   unformat_input_t *i = vam->input;
4171   vl_api_bridge_domain_add_del_t *mp;
4172   u32 bd_id = ~0;
4173   u8 is_add = 1;
4174   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
4175   u8 *bd_tag = NULL;
4176   u32 mac_age = 0;
4177   int ret;
4178
4179   /* Parse args required to build the message */
4180   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4181     {
4182       if (unformat (i, "bd_id %d", &bd_id))
4183         ;
4184       else if (unformat (i, "flood %d", &flood))
4185         ;
4186       else if (unformat (i, "uu-flood %d", &uu_flood))
4187         ;
4188       else if (unformat (i, "forward %d", &forward))
4189         ;
4190       else if (unformat (i, "learn %d", &learn))
4191         ;
4192       else if (unformat (i, "arp-term %d", &arp_term))
4193         ;
4194       else if (unformat (i, "mac-age %d", &mac_age))
4195         ;
4196       else if (unformat (i, "bd-tag %s", &bd_tag))
4197         ;
4198       else if (unformat (i, "del"))
4199         {
4200           is_add = 0;
4201           flood = uu_flood = forward = learn = 0;
4202         }
4203       else
4204         break;
4205     }
4206
4207   if (bd_id == ~0)
4208     {
4209       errmsg ("missing bridge domain");
4210       ret = -99;
4211       goto done;
4212     }
4213
4214   if (mac_age > 255)
4215     {
4216       errmsg ("mac age must be less than 256 ");
4217       ret = -99;
4218       goto done;
4219     }
4220
4221   if ((bd_tag) && (vec_len (bd_tag) > 63))
4222     {
4223       errmsg ("bd-tag cannot be longer than 63");
4224       ret = -99;
4225       goto done;
4226     }
4227
4228   M (BRIDGE_DOMAIN_ADD_DEL, mp);
4229
4230   mp->bd_id = ntohl (bd_id);
4231   mp->flood = flood;
4232   mp->uu_flood = uu_flood;
4233   mp->forward = forward;
4234   mp->learn = learn;
4235   mp->arp_term = arp_term;
4236   mp->is_add = is_add;
4237   mp->mac_age = (u8) mac_age;
4238   if (bd_tag)
4239     {
4240       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
4241       mp->bd_tag[vec_len (bd_tag)] = 0;
4242     }
4243   S (mp);
4244   W (ret);
4245
4246 done:
4247   vec_free (bd_tag);
4248   return ret;
4249 }
4250
4251 static int
4252 api_l2fib_flush_bd (vat_main_t * vam)
4253 {
4254   unformat_input_t *i = vam->input;
4255   vl_api_l2fib_flush_bd_t *mp;
4256   u32 bd_id = ~0;
4257   int ret;
4258
4259   /* Parse args required to build the message */
4260   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4261     {
4262       if (unformat (i, "bd_id %d", &bd_id));
4263       else
4264         break;
4265     }
4266
4267   if (bd_id == ~0)
4268     {
4269       errmsg ("missing bridge domain");
4270       return -99;
4271     }
4272
4273   M (L2FIB_FLUSH_BD, mp);
4274
4275   mp->bd_id = htonl (bd_id);
4276
4277   S (mp);
4278   W (ret);
4279   return ret;
4280 }
4281
4282 static int
4283 api_l2fib_flush_int (vat_main_t * vam)
4284 {
4285   unformat_input_t *i = vam->input;
4286   vl_api_l2fib_flush_int_t *mp;
4287   u32 sw_if_index = ~0;
4288   int ret;
4289
4290   /* Parse args required to build the message */
4291   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4292     {
4293       if (unformat (i, "sw_if_index %d", &sw_if_index));
4294       else
4295         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
4296       else
4297         break;
4298     }
4299
4300   if (sw_if_index == ~0)
4301     {
4302       errmsg ("missing interface name or sw_if_index");
4303       return -99;
4304     }
4305
4306   M (L2FIB_FLUSH_INT, mp);
4307
4308   mp->sw_if_index = ntohl (sw_if_index);
4309
4310   S (mp);
4311   W (ret);
4312   return ret;
4313 }
4314
4315 static int
4316 api_l2fib_add_del (vat_main_t * vam)
4317 {
4318   unformat_input_t *i = vam->input;
4319   vl_api_l2fib_add_del_t *mp;
4320   f64 timeout;
4321   u8 mac[6] = { 0 };
4322   u8 mac_set = 0;
4323   u32 bd_id;
4324   u8 bd_id_set = 0;
4325   u32 sw_if_index = 0;
4326   u8 sw_if_index_set = 0;
4327   u8 is_add = 1;
4328   u8 static_mac = 0;
4329   u8 filter_mac = 0;
4330   u8 bvi_mac = 0;
4331   int count = 1;
4332   f64 before = 0;
4333   int j;
4334
4335   /* Parse args required to build the message */
4336   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4337     {
4338       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
4339         mac_set = 1;
4340       else if (unformat (i, "bd_id %d", &bd_id))
4341         bd_id_set = 1;
4342       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4343         sw_if_index_set = 1;
4344       else if (unformat (i, "sw_if"))
4345         {
4346           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4347             {
4348               if (unformat
4349                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4350                 sw_if_index_set = 1;
4351             }
4352           else
4353             break;
4354         }
4355       else if (unformat (i, "static"))
4356         static_mac = 1;
4357       else if (unformat (i, "filter"))
4358         {
4359           filter_mac = 1;
4360           static_mac = 1;
4361         }
4362       else if (unformat (i, "bvi"))
4363         {
4364           bvi_mac = 1;
4365           static_mac = 1;
4366         }
4367       else if (unformat (i, "del"))
4368         is_add = 0;
4369       else if (unformat (i, "count %d", &count))
4370         ;
4371       else
4372         break;
4373     }
4374
4375   if (mac_set == 0)
4376     {
4377       errmsg ("missing mac address");
4378       return -99;
4379     }
4380
4381   if (bd_id_set == 0)
4382     {
4383       errmsg ("missing bridge domain");
4384       return -99;
4385     }
4386
4387   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
4388     {
4389       errmsg ("missing interface name or sw_if_index");
4390       return -99;
4391     }
4392
4393   if (count > 1)
4394     {
4395       /* Turn on async mode */
4396       vam->async_mode = 1;
4397       vam->async_errors = 0;
4398       before = vat_time_now (vam);
4399     }
4400
4401   for (j = 0; j < count; j++)
4402     {
4403       M (L2FIB_ADD_DEL, mp);
4404
4405       clib_memcpy (mp->mac, mac, 6);
4406       mp->bd_id = ntohl (bd_id);
4407       mp->is_add = is_add;
4408       mp->sw_if_index = ntohl (sw_if_index);
4409
4410       if (is_add)
4411         {
4412           mp->static_mac = static_mac;
4413           mp->filter_mac = filter_mac;
4414           mp->bvi_mac = bvi_mac;
4415         }
4416       increment_mac_address (mac);
4417       /* send it... */
4418       S (mp);
4419     }
4420
4421   if (count > 1)
4422     {
4423       vl_api_control_ping_t *mp_ping;
4424       f64 after;
4425
4426       /* Shut off async mode */
4427       vam->async_mode = 0;
4428
4429       MPING (CONTROL_PING, mp_ping);
4430       S (mp_ping);
4431
4432       timeout = vat_time_now (vam) + 1.0;
4433       while (vat_time_now (vam) < timeout)
4434         if (vam->result_ready == 1)
4435           goto out;
4436       vam->retval = -99;
4437
4438     out:
4439       if (vam->retval == -99)
4440         errmsg ("timeout");
4441
4442       if (vam->async_errors > 0)
4443         {
4444           errmsg ("%d asynchronous errors", vam->async_errors);
4445           vam->retval = -98;
4446         }
4447       vam->async_errors = 0;
4448       after = vat_time_now (vam);
4449
4450       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4451              count, after - before, count / (after - before));
4452     }
4453   else
4454     {
4455       int ret;
4456
4457       /* Wait for a reply... */
4458       W (ret);
4459       return ret;
4460     }
4461   /* Return the good/bad news */
4462   return (vam->retval);
4463 }
4464
4465 static int
4466 api_bridge_domain_set_mac_age (vat_main_t * vam)
4467 {
4468   unformat_input_t *i = vam->input;
4469   vl_api_bridge_domain_set_mac_age_t *mp;
4470   u32 bd_id = ~0;
4471   u32 mac_age = 0;
4472   int ret;
4473
4474   /* Parse args required to build the message */
4475   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4476     {
4477       if (unformat (i, "bd_id %d", &bd_id));
4478       else if (unformat (i, "mac-age %d", &mac_age));
4479       else
4480         break;
4481     }
4482
4483   if (bd_id == ~0)
4484     {
4485       errmsg ("missing bridge domain");
4486       return -99;
4487     }
4488
4489   if (mac_age > 255)
4490     {
4491       errmsg ("mac age must be less than 256 ");
4492       return -99;
4493     }
4494
4495   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
4496
4497   mp->bd_id = htonl (bd_id);
4498   mp->mac_age = (u8) mac_age;
4499
4500   S (mp);
4501   W (ret);
4502   return ret;
4503 }
4504
4505 static int
4506 api_l2_flags (vat_main_t * vam)
4507 {
4508   unformat_input_t *i = vam->input;
4509   vl_api_l2_flags_t *mp;
4510   u32 sw_if_index;
4511   u32 flags = 0;
4512   u8 sw_if_index_set = 0;
4513   u8 is_set = 0;
4514   int ret;
4515
4516   /* Parse args required to build the message */
4517   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4518     {
4519       if (unformat (i, "sw_if_index %d", &sw_if_index))
4520         sw_if_index_set = 1;
4521       else if (unformat (i, "sw_if"))
4522         {
4523           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4524             {
4525               if (unformat
4526                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4527                 sw_if_index_set = 1;
4528             }
4529           else
4530             break;
4531         }
4532       else if (unformat (i, "learn"))
4533         flags |= L2_LEARN;
4534       else if (unformat (i, "forward"))
4535         flags |= L2_FWD;
4536       else if (unformat (i, "flood"))
4537         flags |= L2_FLOOD;
4538       else if (unformat (i, "uu-flood"))
4539         flags |= L2_UU_FLOOD;
4540       else if (unformat (i, "arp-term"))
4541         flags |= L2_ARP_TERM;
4542       else if (unformat (i, "off"))
4543         is_set = 0;
4544       else if (unformat (i, "disable"))
4545         is_set = 0;
4546       else
4547         break;
4548     }
4549
4550   if (sw_if_index_set == 0)
4551     {
4552       errmsg ("missing interface name or sw_if_index");
4553       return -99;
4554     }
4555
4556   M (L2_FLAGS, mp);
4557
4558   mp->sw_if_index = ntohl (sw_if_index);
4559   mp->feature_bitmap = ntohl (flags);
4560   mp->is_set = is_set;
4561
4562   S (mp);
4563   W (ret);
4564   return ret;
4565 }
4566
4567 static int
4568 api_bridge_flags (vat_main_t * vam)
4569 {
4570   unformat_input_t *i = vam->input;
4571   vl_api_bridge_flags_t *mp;
4572   u32 bd_id;
4573   u8 bd_id_set = 0;
4574   u8 is_set = 1;
4575   bd_flags_t flags = 0;
4576   int ret;
4577
4578   /* Parse args required to build the message */
4579   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4580     {
4581       if (unformat (i, "bd_id %d", &bd_id))
4582         bd_id_set = 1;
4583       else if (unformat (i, "learn"))
4584         flags |= BRIDGE_API_FLAG_LEARN;
4585       else if (unformat (i, "forward"))
4586         flags |= BRIDGE_API_FLAG_FWD;
4587       else if (unformat (i, "flood"))
4588         flags |= BRIDGE_API_FLAG_FLOOD;
4589       else if (unformat (i, "uu-flood"))
4590         flags |= BRIDGE_API_FLAG_UU_FLOOD;
4591       else if (unformat (i, "arp-term"))
4592         flags |= BRIDGE_API_FLAG_ARP_TERM;
4593       else if (unformat (i, "off"))
4594         is_set = 0;
4595       else if (unformat (i, "disable"))
4596         is_set = 0;
4597       else
4598         break;
4599     }
4600
4601   if (bd_id_set == 0)
4602     {
4603       errmsg ("missing bridge domain");
4604       return -99;
4605     }
4606
4607   M (BRIDGE_FLAGS, mp);
4608
4609   mp->bd_id = ntohl (bd_id);
4610   mp->flags = ntohl (flags);
4611   mp->is_set = is_set;
4612
4613   S (mp);
4614   W (ret);
4615   return ret;
4616 }
4617
4618 static int
4619 api_bd_ip_mac_add_del (vat_main_t * vam)
4620 {
4621   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
4622   vl_api_mac_address_t mac = { 0 };
4623   unformat_input_t *i = vam->input;
4624   vl_api_bd_ip_mac_add_del_t *mp;
4625   u32 bd_id;
4626   u8 is_add = 1;
4627   u8 bd_id_set = 0;
4628   u8 ip_set = 0;
4629   u8 mac_set = 0;
4630   int ret;
4631
4632
4633   /* Parse args required to build the message */
4634   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4635     {
4636       if (unformat (i, "bd_id %d", &bd_id))
4637         {
4638           bd_id_set++;
4639         }
4640       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
4641         {
4642           ip_set++;
4643         }
4644       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
4645         {
4646           mac_set++;
4647         }
4648       else if (unformat (i, "del"))
4649         is_add = 0;
4650       else
4651         break;
4652     }
4653
4654   if (bd_id_set == 0)
4655     {
4656       errmsg ("missing bridge domain");
4657       return -99;
4658     }
4659   else if (ip_set == 0)
4660     {
4661       errmsg ("missing IP address");
4662       return -99;
4663     }
4664   else if (mac_set == 0)
4665     {
4666       errmsg ("missing MAC address");
4667       return -99;
4668     }
4669
4670   M (BD_IP_MAC_ADD_DEL, mp);
4671
4672   mp->entry.bd_id = ntohl (bd_id);
4673   mp->is_add = is_add;
4674
4675   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
4676   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
4677
4678   S (mp);
4679   W (ret);
4680   return ret;
4681 }
4682
4683 static int
4684 api_bd_ip_mac_flush (vat_main_t * vam)
4685 {
4686   unformat_input_t *i = vam->input;
4687   vl_api_bd_ip_mac_flush_t *mp;
4688   u32 bd_id;
4689   u8 bd_id_set = 0;
4690   int ret;
4691
4692   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4693     {
4694       if (unformat (i, "bd_id %d", &bd_id))
4695         {
4696           bd_id_set++;
4697         }
4698       else
4699         break;
4700     }
4701
4702   if (bd_id_set == 0)
4703     {
4704       errmsg ("missing bridge domain");
4705       return -99;
4706     }
4707
4708   M (BD_IP_MAC_FLUSH, mp);
4709
4710   mp->bd_id = ntohl (bd_id);
4711
4712   S (mp);
4713   W (ret);
4714   return ret;
4715 }
4716
4717 static void vl_api_bd_ip_mac_details_t_handler
4718   (vl_api_bd_ip_mac_details_t * mp)
4719 {
4720   vat_main_t *vam = &vat_main;
4721
4722   print (vam->ofp,
4723          "\n%-5d %U %U",
4724          ntohl (mp->entry.bd_id),
4725          format_vl_api_mac_address, mp->entry.mac,
4726          format_vl_api_address, &mp->entry.ip);
4727 }
4728
4729 static void vl_api_bd_ip_mac_details_t_handler_json
4730   (vl_api_bd_ip_mac_details_t * mp)
4731 {
4732   vat_main_t *vam = &vat_main;
4733   vat_json_node_t *node = NULL;
4734
4735   if (VAT_JSON_ARRAY != vam->json_tree.type)
4736     {
4737       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4738       vat_json_init_array (&vam->json_tree);
4739     }
4740   node = vat_json_array_add (&vam->json_tree);
4741
4742   vat_json_init_object (node);
4743   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
4744   vat_json_object_add_string_copy (node, "mac_address",
4745                                    format (0, "%U", format_vl_api_mac_address,
4746                                            &mp->entry.mac));
4747   u8 *ip = 0;
4748
4749   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
4750   vat_json_object_add_string_copy (node, "ip_address", ip);
4751   vec_free (ip);
4752 }
4753
4754 static int
4755 api_bd_ip_mac_dump (vat_main_t * vam)
4756 {
4757   unformat_input_t *i = vam->input;
4758   vl_api_bd_ip_mac_dump_t *mp;
4759   vl_api_control_ping_t *mp_ping;
4760   int ret;
4761   u32 bd_id;
4762   u8 bd_id_set = 0;
4763
4764   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4765     {
4766       if (unformat (i, "bd_id %d", &bd_id))
4767         {
4768           bd_id_set++;
4769         }
4770       else
4771         break;
4772     }
4773
4774   print (vam->ofp,
4775          "\n%-5s %-7s %-20s %-30s",
4776          "bd_id", "is_ipv6", "mac_address", "ip_address");
4777
4778   /* Dump Bridge Domain Ip to Mac entries */
4779   M (BD_IP_MAC_DUMP, mp);
4780
4781   if (bd_id_set)
4782     mp->bd_id = htonl (bd_id);
4783   else
4784     mp->bd_id = ~0;
4785
4786   S (mp);
4787
4788   /* Use a control ping for synchronization */
4789   MPING (CONTROL_PING, mp_ping);
4790   S (mp_ping);
4791
4792   W (ret);
4793   return ret;
4794 }
4795
4796 static int
4797 api_tap_create_v2 (vat_main_t * vam)
4798 {
4799   unformat_input_t *i = vam->input;
4800   vl_api_tap_create_v2_t *mp;
4801   u8 mac_address[6];
4802   u8 random_mac = 1;
4803   u32 id = ~0;
4804   u32 num_rx_queues = 0;
4805   u8 *host_if_name = 0;
4806   u8 host_if_name_set = 0;
4807   u8 *host_ns = 0;
4808   u8 host_ns_set = 0;
4809   u8 host_mac_addr[6];
4810   u8 host_mac_addr_set = 0;
4811   u8 *host_bridge = 0;
4812   u8 host_bridge_set = 0;
4813   u8 host_ip4_prefix_set = 0;
4814   u8 host_ip6_prefix_set = 0;
4815   ip4_address_t host_ip4_addr;
4816   ip4_address_t host_ip4_gw;
4817   u8 host_ip4_gw_set = 0;
4818   u32 host_ip4_prefix_len = 0;
4819   ip6_address_t host_ip6_addr;
4820   ip6_address_t host_ip6_gw;
4821   u8 host_ip6_gw_set = 0;
4822   u32 host_ip6_prefix_len = 0;
4823   u32 host_mtu_size = 0;
4824   u8 host_mtu_set = 0;
4825   u32 tap_flags = 0;
4826   int ret;
4827   u32 rx_ring_sz = 0, tx_ring_sz = 0;
4828
4829   clib_memset (mac_address, 0, sizeof (mac_address));
4830
4831   /* Parse args required to build the message */
4832   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4833     {
4834       if (unformat (i, "id %u", &id))
4835         ;
4836       else
4837         if (unformat
4838             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
4839         random_mac = 0;
4840       else if (unformat (i, "host-if-name %s", &host_if_name))
4841         host_if_name_set = 1;
4842       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
4843         ;
4844       else if (unformat (i, "host-ns %s", &host_ns))
4845         host_ns_set = 1;
4846       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
4847                          host_mac_addr))
4848         host_mac_addr_set = 1;
4849       else if (unformat (i, "host-bridge %s", &host_bridge))
4850         host_bridge_set = 1;
4851       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
4852                          &host_ip4_addr, &host_ip4_prefix_len))
4853         host_ip4_prefix_set = 1;
4854       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
4855                          &host_ip6_addr, &host_ip6_prefix_len))
4856         host_ip6_prefix_set = 1;
4857       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
4858                          &host_ip4_gw))
4859         host_ip4_gw_set = 1;
4860       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
4861                          &host_ip6_gw))
4862         host_ip6_gw_set = 1;
4863       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
4864         ;
4865       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
4866         ;
4867       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
4868         host_mtu_set = 1;
4869       else if (unformat (i, "no-gso"))
4870         tap_flags &= ~TAP_API_FLAG_GSO;
4871       else if (unformat (i, "gso"))
4872         tap_flags |= TAP_API_FLAG_GSO;
4873       else if (unformat (i, "csum-offload"))
4874         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
4875       else if (unformat (i, "persist"))
4876         tap_flags |= TAP_API_FLAG_PERSIST;
4877       else if (unformat (i, "attach"))
4878         tap_flags |= TAP_API_FLAG_ATTACH;
4879       else if (unformat (i, "tun"))
4880         tap_flags |= TAP_API_FLAG_TUN;
4881       else if (unformat (i, "gro-coalesce"))
4882         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
4883       else if (unformat (i, "packed"))
4884         tap_flags |= TAP_API_FLAG_PACKED;
4885       else if (unformat (i, "in-order"))
4886         tap_flags |= TAP_API_FLAG_IN_ORDER;
4887       else
4888         break;
4889     }
4890
4891   if (vec_len (host_if_name) > 63)
4892     {
4893       errmsg ("tap name too long. ");
4894       return -99;
4895     }
4896   if (vec_len (host_ns) > 63)
4897     {
4898       errmsg ("host name space too long. ");
4899       return -99;
4900     }
4901   if (vec_len (host_bridge) > 63)
4902     {
4903       errmsg ("host bridge name too long. ");
4904       return -99;
4905     }
4906   if (host_ip4_prefix_len > 32)
4907     {
4908       errmsg ("host ip4 prefix length not valid. ");
4909       return -99;
4910     }
4911   if (host_ip6_prefix_len > 128)
4912     {
4913       errmsg ("host ip6 prefix length not valid. ");
4914       return -99;
4915     }
4916   if (!is_pow2 (rx_ring_sz))
4917     {
4918       errmsg ("rx ring size must be power of 2. ");
4919       return -99;
4920     }
4921   if (rx_ring_sz > 32768)
4922     {
4923       errmsg ("rx ring size must be 32768 or lower. ");
4924       return -99;
4925     }
4926   if (!is_pow2 (tx_ring_sz))
4927     {
4928       errmsg ("tx ring size must be power of 2. ");
4929       return -99;
4930     }
4931   if (tx_ring_sz > 32768)
4932     {
4933       errmsg ("tx ring size must be 32768 or lower. ");
4934       return -99;
4935     }
4936   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
4937     {
4938       errmsg ("host MTU size must be in between 64 and 65355. ");
4939       return -99;
4940     }
4941
4942   /* Construct the API message */
4943   M (TAP_CREATE_V2, mp);
4944
4945   mp->id = ntohl (id);
4946   mp->use_random_mac = random_mac;
4947   mp->num_rx_queues = (u8) num_rx_queues;
4948   mp->tx_ring_sz = ntohs (tx_ring_sz);
4949   mp->rx_ring_sz = ntohs (rx_ring_sz);
4950   mp->host_mtu_set = host_mtu_set;
4951   mp->host_mtu_size = ntohl (host_mtu_size);
4952   mp->host_mac_addr_set = host_mac_addr_set;
4953   mp->host_ip4_prefix_set = host_ip4_prefix_set;
4954   mp->host_ip6_prefix_set = host_ip6_prefix_set;
4955   mp->host_ip4_gw_set = host_ip4_gw_set;
4956   mp->host_ip6_gw_set = host_ip6_gw_set;
4957   mp->tap_flags = ntohl (tap_flags);
4958   mp->host_namespace_set = host_ns_set;
4959   mp->host_if_name_set = host_if_name_set;
4960   mp->host_bridge_set = host_bridge_set;
4961
4962   if (random_mac == 0)
4963     clib_memcpy (mp->mac_address, mac_address, 6);
4964   if (host_mac_addr_set)
4965     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
4966   if (host_if_name_set)
4967     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
4968   if (host_ns_set)
4969     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
4970   if (host_bridge_set)
4971     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
4972   if (host_ip4_prefix_set)
4973     {
4974       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
4975       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
4976     }
4977   if (host_ip6_prefix_set)
4978     {
4979       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
4980       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
4981     }
4982   if (host_ip4_gw_set)
4983     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
4984   if (host_ip6_gw_set)
4985     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
4986
4987   vec_free (host_ns);
4988   vec_free (host_if_name);
4989   vec_free (host_bridge);
4990
4991   /* send it... */
4992   S (mp);
4993
4994   /* Wait for a reply... */
4995   W (ret);
4996   return ret;
4997 }
4998
4999 static int
5000 api_tap_delete_v2 (vat_main_t * vam)
5001 {
5002   unformat_input_t *i = vam->input;
5003   vl_api_tap_delete_v2_t *mp;
5004   u32 sw_if_index = ~0;
5005   u8 sw_if_index_set = 0;
5006   int ret;
5007
5008   /* Parse args required to build the message */
5009   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5010     {
5011       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5012         sw_if_index_set = 1;
5013       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5014         sw_if_index_set = 1;
5015       else
5016         break;
5017     }
5018
5019   if (sw_if_index_set == 0)
5020     {
5021       errmsg ("missing vpp interface name. ");
5022       return -99;
5023     }
5024
5025   /* Construct the API message */
5026   M (TAP_DELETE_V2, mp);
5027
5028   mp->sw_if_index = ntohl (sw_if_index);
5029
5030   /* send it... */
5031   S (mp);
5032
5033   /* Wait for a reply... */
5034   W (ret);
5035   return ret;
5036 }
5037
5038 uword
5039 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
5040 {
5041   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
5042   u32 x[4];
5043
5044   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
5045     return 0;
5046
5047   addr->domain = x[0];
5048   addr->bus = x[1];
5049   addr->slot = x[2];
5050   addr->function = x[3];
5051
5052   return 1;
5053 }
5054
5055 static int
5056 api_virtio_pci_create_v2 (vat_main_t * vam)
5057 {
5058   unformat_input_t *i = vam->input;
5059   vl_api_virtio_pci_create_v2_t *mp;
5060   u8 mac_address[6];
5061   u8 random_mac = 1;
5062   u32 pci_addr = 0;
5063   u64 features = (u64) ~ (0ULL);
5064   u32 virtio_flags = 0;
5065   int ret;
5066
5067   clib_memset (mac_address, 0, sizeof (mac_address));
5068
5069   /* Parse args required to build the message */
5070   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5071     {
5072       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5073         {
5074           random_mac = 0;
5075         }
5076       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
5077         ;
5078       else if (unformat (i, "features 0x%llx", &features))
5079         ;
5080       else if (unformat (i, "gso-enabled"))
5081         virtio_flags |= VIRTIO_API_FLAG_GSO;
5082       else if (unformat (i, "csum-offload-enabled"))
5083         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
5084       else if (unformat (i, "gro-coalesce"))
5085         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
5086       else if (unformat (i, "packed"))
5087         virtio_flags |= VIRTIO_API_FLAG_PACKED;
5088       else if (unformat (i, "in-order"))
5089         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
5090       else if (unformat (i, "buffering"))
5091         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
5092       else
5093         break;
5094     }
5095
5096   if (pci_addr == 0)
5097     {
5098       errmsg ("pci address must be non zero. ");
5099       return -99;
5100     }
5101
5102   /* Construct the API message */
5103   M (VIRTIO_PCI_CREATE_V2, mp);
5104
5105   mp->use_random_mac = random_mac;
5106
5107   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
5108   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
5109   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
5110   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
5111
5112   mp->features = clib_host_to_net_u64 (features);
5113   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
5114
5115   if (random_mac == 0)
5116     clib_memcpy (mp->mac_address, mac_address, 6);
5117
5118   /* send it... */
5119   S (mp);
5120
5121   /* Wait for a reply... */
5122   W (ret);
5123   return ret;
5124 }
5125
5126 static int
5127 api_virtio_pci_delete (vat_main_t * vam)
5128 {
5129   unformat_input_t *i = vam->input;
5130   vl_api_virtio_pci_delete_t *mp;
5131   u32 sw_if_index = ~0;
5132   u8 sw_if_index_set = 0;
5133   int ret;
5134
5135   /* Parse args required to build the message */
5136   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5137     {
5138       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5139         sw_if_index_set = 1;
5140       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5141         sw_if_index_set = 1;
5142       else
5143         break;
5144     }
5145
5146   if (sw_if_index_set == 0)
5147     {
5148       errmsg ("missing vpp interface name. ");
5149       return -99;
5150     }
5151
5152   /* Construct the API message */
5153   M (VIRTIO_PCI_DELETE, mp);
5154
5155   mp->sw_if_index = htonl (sw_if_index);
5156
5157   /* send it... */
5158   S (mp);
5159
5160   /* Wait for a reply... */
5161   W (ret);
5162   return ret;
5163 }
5164
5165 static int
5166 api_bond_create (vat_main_t * vam)
5167 {
5168   unformat_input_t *i = vam->input;
5169   vl_api_bond_create_t *mp;
5170   u8 mac_address[6];
5171   u8 custom_mac = 0;
5172   int ret;
5173   u8 mode;
5174   u8 lb;
5175   u8 mode_is_set = 0;
5176   u32 id = ~0;
5177   u8 numa_only = 0;
5178
5179   clib_memset (mac_address, 0, sizeof (mac_address));
5180   lb = BOND_LB_L2;
5181
5182   /* Parse args required to build the message */
5183   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5184     {
5185       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5186         mode_is_set = 1;
5187       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5188                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5189         ;
5190       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5191                          mac_address))
5192         custom_mac = 1;
5193       else if (unformat (i, "numa-only"))
5194         numa_only = 1;
5195       else if (unformat (i, "id %u", &id))
5196         ;
5197       else
5198         break;
5199     }
5200
5201   if (mode_is_set == 0)
5202     {
5203       errmsg ("Missing bond mode. ");
5204       return -99;
5205     }
5206
5207   /* Construct the API message */
5208   M (BOND_CREATE, mp);
5209
5210   mp->use_custom_mac = custom_mac;
5211
5212   mp->mode = htonl (mode);
5213   mp->lb = htonl (lb);
5214   mp->id = htonl (id);
5215   mp->numa_only = numa_only;
5216
5217   if (custom_mac)
5218     clib_memcpy (mp->mac_address, mac_address, 6);
5219
5220   /* send it... */
5221   S (mp);
5222
5223   /* Wait for a reply... */
5224   W (ret);
5225   return ret;
5226 }
5227
5228 static int
5229 api_bond_create2 (vat_main_t * vam)
5230 {
5231   unformat_input_t *i = vam->input;
5232   vl_api_bond_create2_t *mp;
5233   u8 mac_address[6];
5234   u8 custom_mac = 0;
5235   int ret;
5236   u8 mode;
5237   u8 lb;
5238   u8 mode_is_set = 0;
5239   u32 id = ~0;
5240   u8 numa_only = 0;
5241   u8 gso = 0;
5242
5243   clib_memset (mac_address, 0, sizeof (mac_address));
5244   lb = BOND_LB_L2;
5245
5246   /* Parse args required to build the message */
5247   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5248     {
5249       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5250         mode_is_set = 1;
5251       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5252                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5253         ;
5254       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5255                          mac_address))
5256         custom_mac = 1;
5257       else if (unformat (i, "numa-only"))
5258         numa_only = 1;
5259       else if (unformat (i, "gso"))
5260         gso = 1;
5261       else if (unformat (i, "id %u", &id))
5262         ;
5263       else
5264         break;
5265     }
5266
5267   if (mode_is_set == 0)
5268     {
5269       errmsg ("Missing bond mode. ");
5270       return -99;
5271     }
5272
5273   /* Construct the API message */
5274   M (BOND_CREATE2, mp);
5275
5276   mp->use_custom_mac = custom_mac;
5277
5278   mp->mode = htonl (mode);
5279   mp->lb = htonl (lb);
5280   mp->id = htonl (id);
5281   mp->numa_only = numa_only;
5282   mp->enable_gso = gso;
5283
5284   if (custom_mac)
5285     clib_memcpy (mp->mac_address, mac_address, 6);
5286
5287   /* send it... */
5288   S (mp);
5289
5290   /* Wait for a reply... */
5291   W (ret);
5292   return ret;
5293 }
5294
5295 static int
5296 api_bond_delete (vat_main_t * vam)
5297 {
5298   unformat_input_t *i = vam->input;
5299   vl_api_bond_delete_t *mp;
5300   u32 sw_if_index = ~0;
5301   u8 sw_if_index_set = 0;
5302   int ret;
5303
5304   /* Parse args required to build the message */
5305   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5306     {
5307       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5308         sw_if_index_set = 1;
5309       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5310         sw_if_index_set = 1;
5311       else
5312         break;
5313     }
5314
5315   if (sw_if_index_set == 0)
5316     {
5317       errmsg ("missing vpp interface name. ");
5318       return -99;
5319     }
5320
5321   /* Construct the API message */
5322   M (BOND_DELETE, mp);
5323
5324   mp->sw_if_index = ntohl (sw_if_index);
5325
5326   /* send it... */
5327   S (mp);
5328
5329   /* Wait for a reply... */
5330   W (ret);
5331   return ret;
5332 }
5333
5334 static int
5335 api_bond_add_member (vat_main_t * vam)
5336 {
5337   unformat_input_t *i = vam->input;
5338   vl_api_bond_add_member_t *mp;
5339   u32 bond_sw_if_index;
5340   int ret;
5341   u8 is_passive;
5342   u8 is_long_timeout;
5343   u32 bond_sw_if_index_is_set = 0;
5344   u32 sw_if_index;
5345   u8 sw_if_index_is_set = 0;
5346
5347   /* Parse args required to build the message */
5348   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5349     {
5350       if (unformat (i, "sw_if_index %d", &sw_if_index))
5351         sw_if_index_is_set = 1;
5352       else if (unformat (i, "bond %u", &bond_sw_if_index))
5353         bond_sw_if_index_is_set = 1;
5354       else if (unformat (i, "passive %d", &is_passive))
5355         ;
5356       else if (unformat (i, "long-timeout %d", &is_long_timeout))
5357         ;
5358       else
5359         break;
5360     }
5361
5362   if (bond_sw_if_index_is_set == 0)
5363     {
5364       errmsg ("Missing bond sw_if_index. ");
5365       return -99;
5366     }
5367   if (sw_if_index_is_set == 0)
5368     {
5369       errmsg ("Missing member sw_if_index. ");
5370       return -99;
5371     }
5372
5373   /* Construct the API message */
5374   M (BOND_ADD_MEMBER, mp);
5375
5376   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
5377   mp->sw_if_index = ntohl (sw_if_index);
5378   mp->is_long_timeout = is_long_timeout;
5379   mp->is_passive = is_passive;
5380
5381   /* send it... */
5382   S (mp);
5383
5384   /* Wait for a reply... */
5385   W (ret);
5386   return ret;
5387 }
5388
5389 static int
5390 api_bond_detach_member (vat_main_t * vam)
5391 {
5392   unformat_input_t *i = vam->input;
5393   vl_api_bond_detach_member_t *mp;
5394   u32 sw_if_index = ~0;
5395   u8 sw_if_index_set = 0;
5396   int ret;
5397
5398   /* Parse args required to build the message */
5399   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5400     {
5401       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5402         sw_if_index_set = 1;
5403       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5404         sw_if_index_set = 1;
5405       else
5406         break;
5407     }
5408
5409   if (sw_if_index_set == 0)
5410     {
5411       errmsg ("missing vpp interface name. ");
5412       return -99;
5413     }
5414
5415   /* Construct the API message */
5416   M (BOND_DETACH_MEMBER, mp);
5417
5418   mp->sw_if_index = ntohl (sw_if_index);
5419
5420   /* send it... */
5421   S (mp);
5422
5423   /* Wait for a reply... */
5424   W (ret);
5425   return ret;
5426 }
5427
5428 static int
5429 api_ip_table_add_del (vat_main_t * vam)
5430 {
5431   unformat_input_t *i = vam->input;
5432   vl_api_ip_table_add_del_t *mp;
5433   u32 table_id = ~0;
5434   u8 is_ipv6 = 0;
5435   u8 is_add = 1;
5436   int ret = 0;
5437
5438   /* Parse args required to build the message */
5439   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5440     {
5441       if (unformat (i, "ipv6"))
5442         is_ipv6 = 1;
5443       else if (unformat (i, "del"))
5444         is_add = 0;
5445       else if (unformat (i, "add"))
5446         is_add = 1;
5447       else if (unformat (i, "table %d", &table_id))
5448         ;
5449       else
5450         {
5451           clib_warning ("parse error '%U'", format_unformat_error, i);
5452           return -99;
5453         }
5454     }
5455
5456   if (~0 == table_id)
5457     {
5458       errmsg ("missing table-ID");
5459       return -99;
5460     }
5461
5462   /* Construct the API message */
5463   M (IP_TABLE_ADD_DEL, mp);
5464
5465   mp->table.table_id = ntohl (table_id);
5466   mp->table.is_ip6 = is_ipv6;
5467   mp->is_add = is_add;
5468
5469   /* send it... */
5470   S (mp);
5471
5472   /* Wait for a reply... */
5473   W (ret);
5474
5475   return ret;
5476 }
5477
5478 uword
5479 unformat_fib_path (unformat_input_t * input, va_list * args)
5480 {
5481   vat_main_t *vam = va_arg (*args, vat_main_t *);
5482   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
5483   u32 weight, preference;
5484   mpls_label_t out_label;
5485
5486   clib_memset (path, 0, sizeof (*path));
5487   path->weight = 1;
5488   path->sw_if_index = ~0;
5489   path->rpf_id = ~0;
5490   path->n_labels = 0;
5491
5492   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5493     {
5494       if (unformat (input, "%U %U",
5495                     unformat_vl_api_ip4_address,
5496                     &path->nh.address.ip4,
5497                     api_unformat_sw_if_index, vam, &path->sw_if_index))
5498         {
5499           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5500         }
5501       else if (unformat (input, "%U %U",
5502                          unformat_vl_api_ip6_address,
5503                          &path->nh.address.ip6,
5504                          api_unformat_sw_if_index, vam, &path->sw_if_index))
5505         {
5506           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5507         }
5508       else if (unformat (input, "weight %u", &weight))
5509         {
5510           path->weight = weight;
5511         }
5512       else if (unformat (input, "preference %u", &preference))
5513         {
5514           path->preference = preference;
5515         }
5516       else if (unformat (input, "%U next-hop-table %d",
5517                          unformat_vl_api_ip4_address,
5518                          &path->nh.address.ip4, &path->table_id))
5519         {
5520           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5521         }
5522       else if (unformat (input, "%U next-hop-table %d",
5523                          unformat_vl_api_ip6_address,
5524                          &path->nh.address.ip6, &path->table_id))
5525         {
5526           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5527         }
5528       else if (unformat (input, "%U",
5529                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
5530         {
5531           /*
5532            * the recursive next-hops are by default in the default table
5533            */
5534           path->table_id = 0;
5535           path->sw_if_index = ~0;
5536           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5537         }
5538       else if (unformat (input, "%U",
5539                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
5540         {
5541           /*
5542            * the recursive next-hops are by default in the default table
5543            */
5544           path->table_id = 0;
5545           path->sw_if_index = ~0;
5546           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5547         }
5548       else if (unformat (input, "resolve-via-host"))
5549         {
5550           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
5551         }
5552       else if (unformat (input, "resolve-via-attached"))
5553         {
5554           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
5555         }
5556       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
5557         {
5558           path->type = FIB_API_PATH_TYPE_LOCAL;
5559           path->sw_if_index = ~0;
5560           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5561         }
5562       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
5563         {
5564           path->type = FIB_API_PATH_TYPE_LOCAL;
5565           path->sw_if_index = ~0;
5566           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5567         }
5568       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
5569         ;
5570       else if (unformat (input, "via-label %d", &path->nh.via_label))
5571         {
5572           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
5573           path->sw_if_index = ~0;
5574         }
5575       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
5576         {
5577           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
5578           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
5579         }
5580       else if (unformat (input, "local"))
5581         {
5582           path->type = FIB_API_PATH_TYPE_LOCAL;
5583         }
5584       else if (unformat (input, "out-labels"))
5585         {
5586           while (unformat (input, "%d", &out_label))
5587             {
5588               path->label_stack[path->n_labels].label = out_label;
5589               path->label_stack[path->n_labels].is_uniform = 0;
5590               path->label_stack[path->n_labels].ttl = 64;
5591               path->n_labels++;
5592             }
5593         }
5594       else if (unformat (input, "via"))
5595         {
5596           /* new path, back up and return */
5597           unformat_put_input (input);
5598           unformat_put_input (input);
5599           unformat_put_input (input);
5600           unformat_put_input (input);
5601           break;
5602         }
5603       else
5604         {
5605           return (0);
5606         }
5607     }
5608
5609   path->proto = ntohl (path->proto);
5610   path->type = ntohl (path->type);
5611   path->flags = ntohl (path->flags);
5612   path->table_id = ntohl (path->table_id);
5613   path->sw_if_index = ntohl (path->sw_if_index);
5614
5615   return (1);
5616 }
5617
5618 static int
5619 api_ip_route_add_del (vat_main_t * vam)
5620 {
5621   unformat_input_t *i = vam->input;
5622   vl_api_ip_route_add_del_t *mp;
5623   u32 vrf_id = 0;
5624   u8 is_add = 1;
5625   u8 is_multipath = 0;
5626   u8 prefix_set = 0;
5627   u8 path_count = 0;
5628   vl_api_prefix_t pfx = { };
5629   vl_api_fib_path_t paths[8];
5630   int count = 1;
5631   int j;
5632   f64 before = 0;
5633   u32 random_add_del = 0;
5634   u32 *random_vector = 0;
5635   u32 random_seed = 0xdeaddabe;
5636
5637   /* Parse args required to build the message */
5638   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5639     {
5640       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5641         prefix_set = 1;
5642       else if (unformat (i, "del"))
5643         is_add = 0;
5644       else if (unformat (i, "add"))
5645         is_add = 1;
5646       else if (unformat (i, "vrf %d", &vrf_id))
5647         ;
5648       else if (unformat (i, "count %d", &count))
5649         ;
5650       else if (unformat (i, "random"))
5651         random_add_del = 1;
5652       else if (unformat (i, "multipath"))
5653         is_multipath = 1;
5654       else if (unformat (i, "seed %d", &random_seed))
5655         ;
5656       else
5657         if (unformat
5658             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5659         {
5660           path_count++;
5661           if (8 == path_count)
5662             {
5663               errmsg ("max 8 paths");
5664               return -99;
5665             }
5666         }
5667       else
5668         {
5669           clib_warning ("parse error '%U'", format_unformat_error, i);
5670           return -99;
5671         }
5672     }
5673
5674   if (!path_count)
5675     {
5676       errmsg ("specify a path; via ...");
5677       return -99;
5678     }
5679   if (prefix_set == 0)
5680     {
5681       errmsg ("missing prefix");
5682       return -99;
5683     }
5684
5685   /* Generate a pile of unique, random routes */
5686   if (random_add_del)
5687     {
5688       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
5689       u32 this_random_address;
5690       uword *random_hash;
5691
5692       random_hash = hash_create (count, sizeof (uword));
5693
5694       hash_set (random_hash, i->as_u32, 1);
5695       for (j = 0; j <= count; j++)
5696         {
5697           do
5698             {
5699               this_random_address = random_u32 (&random_seed);
5700               this_random_address =
5701                 clib_host_to_net_u32 (this_random_address);
5702             }
5703           while (hash_get (random_hash, this_random_address));
5704           vec_add1 (random_vector, this_random_address);
5705           hash_set (random_hash, this_random_address, 1);
5706         }
5707       hash_free (random_hash);
5708       set_ip4_address (&pfx.address, random_vector[0]);
5709     }
5710
5711   if (count > 1)
5712     {
5713       /* Turn on async mode */
5714       vam->async_mode = 1;
5715       vam->async_errors = 0;
5716       before = vat_time_now (vam);
5717     }
5718
5719   for (j = 0; j < count; j++)
5720     {
5721       /* Construct the API message */
5722       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5723
5724       mp->is_add = is_add;
5725       mp->is_multipath = is_multipath;
5726
5727       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5728       mp->route.table_id = ntohl (vrf_id);
5729       mp->route.n_paths = path_count;
5730
5731       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
5732
5733       if (random_add_del)
5734         set_ip4_address (&pfx.address, random_vector[j + 1]);
5735       else
5736         increment_address (&pfx.address);
5737       /* send it... */
5738       S (mp);
5739       /* If we receive SIGTERM, stop now... */
5740       if (vam->do_exit)
5741         break;
5742     }
5743
5744   /* When testing multiple add/del ops, use a control-ping to sync */
5745   if (count > 1)
5746     {
5747       vl_api_control_ping_t *mp_ping;
5748       f64 after;
5749       f64 timeout;
5750
5751       /* Shut off async mode */
5752       vam->async_mode = 0;
5753
5754       MPING (CONTROL_PING, mp_ping);
5755       S (mp_ping);
5756
5757       timeout = vat_time_now (vam) + 1.0;
5758       while (vat_time_now (vam) < timeout)
5759         if (vam->result_ready == 1)
5760           goto out;
5761       vam->retval = -99;
5762
5763     out:
5764       if (vam->retval == -99)
5765         errmsg ("timeout");
5766
5767       if (vam->async_errors > 0)
5768         {
5769           errmsg ("%d asynchronous errors", vam->async_errors);
5770           vam->retval = -98;
5771         }
5772       vam->async_errors = 0;
5773       after = vat_time_now (vam);
5774
5775       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5776       if (j > 0)
5777         count = j;
5778
5779       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5780              count, after - before, count / (after - before));
5781     }
5782   else
5783     {
5784       int ret;
5785
5786       /* Wait for a reply... */
5787       W (ret);
5788       return ret;
5789     }
5790
5791   /* Return the good/bad news */
5792   return (vam->retval);
5793 }
5794
5795 static int
5796 api_ip_mroute_add_del (vat_main_t * vam)
5797 {
5798   unformat_input_t *i = vam->input;
5799   u8 path_set = 0, prefix_set = 0, is_add = 1;
5800   vl_api_ip_mroute_add_del_t *mp;
5801   mfib_entry_flags_t eflags = 0;
5802   vl_api_mfib_path_t path;
5803   vl_api_mprefix_t pfx = { };
5804   u32 vrf_id = 0;
5805   int ret;
5806
5807   /* Parse args required to build the message */
5808   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5809     {
5810       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
5811         {
5812           prefix_set = 1;
5813           pfx.grp_address_length = htons (pfx.grp_address_length);
5814         }
5815       else if (unformat (i, "del"))
5816         is_add = 0;
5817       else if (unformat (i, "add"))
5818         is_add = 1;
5819       else if (unformat (i, "vrf %d", &vrf_id))
5820         ;
5821       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
5822         path.itf_flags = htonl (path.itf_flags);
5823       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
5824         ;
5825       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
5826         path_set = 1;
5827       else
5828         {
5829           clib_warning ("parse error '%U'", format_unformat_error, i);
5830           return -99;
5831         }
5832     }
5833
5834   if (prefix_set == 0)
5835     {
5836       errmsg ("missing addresses\n");
5837       return -99;
5838     }
5839   if (path_set == 0)
5840     {
5841       errmsg ("missing path\n");
5842       return -99;
5843     }
5844
5845   /* Construct the API message */
5846   M (IP_MROUTE_ADD_DEL, mp);
5847
5848   mp->is_add = is_add;
5849   mp->is_multipath = 1;
5850
5851   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5852   mp->route.table_id = htonl (vrf_id);
5853   mp->route.n_paths = 1;
5854   mp->route.entry_flags = htonl (eflags);
5855
5856   clib_memcpy (&mp->route.paths, &path, sizeof (path));
5857
5858   /* send it... */
5859   S (mp);
5860   /* Wait for a reply... */
5861   W (ret);
5862   return ret;
5863 }
5864
5865 static int
5866 api_mpls_table_add_del (vat_main_t * vam)
5867 {
5868   unformat_input_t *i = vam->input;
5869   vl_api_mpls_table_add_del_t *mp;
5870   u32 table_id = ~0;
5871   u8 is_add = 1;
5872   int ret = 0;
5873
5874   /* Parse args required to build the message */
5875   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5876     {
5877       if (unformat (i, "table %d", &table_id))
5878         ;
5879       else if (unformat (i, "del"))
5880         is_add = 0;
5881       else if (unformat (i, "add"))
5882         is_add = 1;
5883       else
5884         {
5885           clib_warning ("parse error '%U'", format_unformat_error, i);
5886           return -99;
5887         }
5888     }
5889
5890   if (~0 == table_id)
5891     {
5892       errmsg ("missing table-ID");
5893       return -99;
5894     }
5895
5896   /* Construct the API message */
5897   M (MPLS_TABLE_ADD_DEL, mp);
5898
5899   mp->mt_table.mt_table_id = ntohl (table_id);
5900   mp->mt_is_add = is_add;
5901
5902   /* send it... */
5903   S (mp);
5904
5905   /* Wait for a reply... */
5906   W (ret);
5907
5908   return ret;
5909 }
5910
5911 static int
5912 api_mpls_route_add_del (vat_main_t * vam)
5913 {
5914   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
5915   mpls_label_t local_label = MPLS_LABEL_INVALID;
5916   unformat_input_t *i = vam->input;
5917   vl_api_mpls_route_add_del_t *mp;
5918   vl_api_fib_path_t paths[8];
5919   int count = 1, j;
5920   f64 before = 0;
5921
5922   /* Parse args required to build the message */
5923   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5924     {
5925       if (unformat (i, "%d", &local_label))
5926         ;
5927       else if (unformat (i, "eos"))
5928         is_eos = 1;
5929       else if (unformat (i, "non-eos"))
5930         is_eos = 0;
5931       else if (unformat (i, "del"))
5932         is_add = 0;
5933       else if (unformat (i, "add"))
5934         is_add = 1;
5935       else if (unformat (i, "multipath"))
5936         is_multipath = 1;
5937       else if (unformat (i, "count %d", &count))
5938         ;
5939       else
5940         if (unformat
5941             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5942         {
5943           path_count++;
5944           if (8 == path_count)
5945             {
5946               errmsg ("max 8 paths");
5947               return -99;
5948             }
5949         }
5950       else
5951         {
5952           clib_warning ("parse error '%U'", format_unformat_error, i);
5953           return -99;
5954         }
5955     }
5956
5957   if (!path_count)
5958     {
5959       errmsg ("specify a path; via ...");
5960       return -99;
5961     }
5962
5963   if (MPLS_LABEL_INVALID == local_label)
5964     {
5965       errmsg ("missing label");
5966       return -99;
5967     }
5968
5969   if (count > 1)
5970     {
5971       /* Turn on async mode */
5972       vam->async_mode = 1;
5973       vam->async_errors = 0;
5974       before = vat_time_now (vam);
5975     }
5976
5977   for (j = 0; j < count; j++)
5978     {
5979       /* Construct the API message */
5980       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5981
5982       mp->mr_is_add = is_add;
5983       mp->mr_is_multipath = is_multipath;
5984
5985       mp->mr_route.mr_label = local_label;
5986       mp->mr_route.mr_eos = is_eos;
5987       mp->mr_route.mr_table_id = 0;
5988       mp->mr_route.mr_n_paths = path_count;
5989
5990       clib_memcpy (&mp->mr_route.mr_paths, paths,
5991                    sizeof (paths[0]) * path_count);
5992
5993       local_label++;
5994
5995       /* send it... */
5996       S (mp);
5997       /* If we receive SIGTERM, stop now... */
5998       if (vam->do_exit)
5999         break;
6000     }
6001
6002   /* When testing multiple add/del ops, use a control-ping to sync */
6003   if (count > 1)
6004     {
6005       vl_api_control_ping_t *mp_ping;
6006       f64 after;
6007       f64 timeout;
6008
6009       /* Shut off async mode */
6010       vam->async_mode = 0;
6011
6012       MPING (CONTROL_PING, mp_ping);
6013       S (mp_ping);
6014
6015       timeout = vat_time_now (vam) + 1.0;
6016       while (vat_time_now (vam) < timeout)
6017         if (vam->result_ready == 1)
6018           goto out;
6019       vam->retval = -99;
6020
6021     out:
6022       if (vam->retval == -99)
6023         errmsg ("timeout");
6024
6025       if (vam->async_errors > 0)
6026         {
6027           errmsg ("%d asynchronous errors", vam->async_errors);
6028           vam->retval = -98;
6029         }
6030       vam->async_errors = 0;
6031       after = vat_time_now (vam);
6032
6033       /* slim chance, but we might have eaten SIGTERM on the first iteration */
6034       if (j > 0)
6035         count = j;
6036
6037       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
6038              count, after - before, count / (after - before));
6039     }
6040   else
6041     {
6042       int ret;
6043
6044       /* Wait for a reply... */
6045       W (ret);
6046       return ret;
6047     }
6048
6049   /* Return the good/bad news */
6050   return (vam->retval);
6051   return (0);
6052 }
6053
6054 static int
6055 api_mpls_ip_bind_unbind (vat_main_t * vam)
6056 {
6057   unformat_input_t *i = vam->input;
6058   vl_api_mpls_ip_bind_unbind_t *mp;
6059   u32 ip_table_id = 0;
6060   u8 is_bind = 1;
6061   vl_api_prefix_t pfx;
6062   u8 prefix_set = 0;
6063   mpls_label_t local_label = MPLS_LABEL_INVALID;
6064   int ret;
6065
6066   /* Parse args required to build the message */
6067   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6068     {
6069       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6070         prefix_set = 1;
6071       else if (unformat (i, "%d", &local_label))
6072         ;
6073       else if (unformat (i, "table-id %d", &ip_table_id))
6074         ;
6075       else if (unformat (i, "unbind"))
6076         is_bind = 0;
6077       else if (unformat (i, "bind"))
6078         is_bind = 1;
6079       else
6080         {
6081           clib_warning ("parse error '%U'", format_unformat_error, i);
6082           return -99;
6083         }
6084     }
6085
6086   if (!prefix_set)
6087     {
6088       errmsg ("IP prefix not set");
6089       return -99;
6090     }
6091
6092   if (MPLS_LABEL_INVALID == local_label)
6093     {
6094       errmsg ("missing label");
6095       return -99;
6096     }
6097
6098   /* Construct the API message */
6099   M (MPLS_IP_BIND_UNBIND, mp);
6100
6101   mp->mb_is_bind = is_bind;
6102   mp->mb_ip_table_id = ntohl (ip_table_id);
6103   mp->mb_mpls_table_id = 0;
6104   mp->mb_label = ntohl (local_label);
6105   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
6106
6107   /* send it... */
6108   S (mp);
6109
6110   /* Wait for a reply... */
6111   W (ret);
6112   return ret;
6113   return (0);
6114 }
6115
6116 static int
6117 api_sr_mpls_policy_add (vat_main_t * vam)
6118 {
6119   unformat_input_t *i = vam->input;
6120   vl_api_sr_mpls_policy_add_t *mp;
6121   u32 bsid = 0;
6122   u32 weight = 1;
6123   u8 type = 0;
6124   u8 n_segments = 0;
6125   u32 sid;
6126   u32 *segments = NULL;
6127   int ret;
6128
6129   /* Parse args required to build the message */
6130   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6131     {
6132       if (unformat (i, "bsid %d", &bsid))
6133         ;
6134       else if (unformat (i, "weight %d", &weight))
6135         ;
6136       else if (unformat (i, "spray"))
6137         type = 1;
6138       else if (unformat (i, "next %d", &sid))
6139         {
6140           n_segments += 1;
6141           vec_add1 (segments, htonl (sid));
6142         }
6143       else
6144         {
6145           clib_warning ("parse error '%U'", format_unformat_error, i);
6146           return -99;
6147         }
6148     }
6149
6150   if (bsid == 0)
6151     {
6152       errmsg ("bsid not set");
6153       return -99;
6154     }
6155
6156   if (n_segments == 0)
6157     {
6158       errmsg ("no sid in segment stack");
6159       return -99;
6160     }
6161
6162   /* Construct the API message */
6163   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
6164
6165   mp->bsid = htonl (bsid);
6166   mp->weight = htonl (weight);
6167   mp->is_spray = type;
6168   mp->n_segments = n_segments;
6169   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
6170   vec_free (segments);
6171
6172   /* send it... */
6173   S (mp);
6174
6175   /* Wait for a reply... */
6176   W (ret);
6177   return ret;
6178 }
6179
6180 static int
6181 api_sr_mpls_policy_del (vat_main_t * vam)
6182 {
6183   unformat_input_t *i = vam->input;
6184   vl_api_sr_mpls_policy_del_t *mp;
6185   u32 bsid = 0;
6186   int ret;
6187
6188   /* Parse args required to build the message */
6189   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6190     {
6191       if (unformat (i, "bsid %d", &bsid))
6192         ;
6193       else
6194         {
6195           clib_warning ("parse error '%U'", format_unformat_error, i);
6196           return -99;
6197         }
6198     }
6199
6200   if (bsid == 0)
6201     {
6202       errmsg ("bsid not set");
6203       return -99;
6204     }
6205
6206   /* Construct the API message */
6207   M (SR_MPLS_POLICY_DEL, mp);
6208
6209   mp->bsid = htonl (bsid);
6210
6211   /* send it... */
6212   S (mp);
6213
6214   /* Wait for a reply... */
6215   W (ret);
6216   return ret;
6217 }
6218
6219 static int
6220 api_mpls_tunnel_add_del (vat_main_t * vam)
6221 {
6222   unformat_input_t *i = vam->input;
6223   vl_api_mpls_tunnel_add_del_t *mp;
6224
6225   vl_api_fib_path_t paths[8];
6226   u32 sw_if_index = ~0;
6227   u8 path_count = 0;
6228   u8 l2_only = 0;
6229   u8 is_add = 1;
6230   int ret;
6231
6232   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6233     {
6234       if (unformat (i, "add"))
6235         is_add = 1;
6236       else
6237         if (unformat
6238             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
6239         is_add = 0;
6240       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
6241         is_add = 0;
6242       else if (unformat (i, "l2-only"))
6243         l2_only = 1;
6244       else
6245         if (unformat
6246             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6247         {
6248           path_count++;
6249           if (8 == path_count)
6250             {
6251               errmsg ("max 8 paths");
6252               return -99;
6253             }
6254         }
6255       else
6256         {
6257           clib_warning ("parse error '%U'", format_unformat_error, i);
6258           return -99;
6259         }
6260     }
6261
6262   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6263
6264   mp->mt_is_add = is_add;
6265   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
6266   mp->mt_tunnel.mt_l2_only = l2_only;
6267   mp->mt_tunnel.mt_is_multicast = 0;
6268   mp->mt_tunnel.mt_n_paths = path_count;
6269
6270   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
6271                sizeof (paths[0]) * path_count);
6272
6273   S (mp);
6274   W (ret);
6275   return ret;
6276 }
6277
6278 static int
6279 api_sw_interface_set_unnumbered (vat_main_t * vam)
6280 {
6281   unformat_input_t *i = vam->input;
6282   vl_api_sw_interface_set_unnumbered_t *mp;
6283   u32 sw_if_index;
6284   u32 unnum_sw_index = ~0;
6285   u8 is_add = 1;
6286   u8 sw_if_index_set = 0;
6287   int ret;
6288
6289   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6290     {
6291       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6292         sw_if_index_set = 1;
6293       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6294         sw_if_index_set = 1;
6295       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
6296         ;
6297       else if (unformat (i, "del"))
6298         is_add = 0;
6299       else
6300         {
6301           clib_warning ("parse error '%U'", format_unformat_error, i);
6302           return -99;
6303         }
6304     }
6305
6306   if (sw_if_index_set == 0)
6307     {
6308       errmsg ("missing interface name or sw_if_index");
6309       return -99;
6310     }
6311
6312   M (SW_INTERFACE_SET_UNNUMBERED, mp);
6313
6314   mp->sw_if_index = ntohl (sw_if_index);
6315   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
6316   mp->is_add = is_add;
6317
6318   S (mp);
6319   W (ret);
6320   return ret;
6321 }
6322
6323
6324 static int
6325 api_create_vlan_subif (vat_main_t * vam)
6326 {
6327   unformat_input_t *i = vam->input;
6328   vl_api_create_vlan_subif_t *mp;
6329   u32 sw_if_index;
6330   u8 sw_if_index_set = 0;
6331   u32 vlan_id;
6332   u8 vlan_id_set = 0;
6333   int ret;
6334
6335   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6336     {
6337       if (unformat (i, "sw_if_index %d", &sw_if_index))
6338         sw_if_index_set = 1;
6339       else
6340         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6341         sw_if_index_set = 1;
6342       else if (unformat (i, "vlan %d", &vlan_id))
6343         vlan_id_set = 1;
6344       else
6345         {
6346           clib_warning ("parse error '%U'", format_unformat_error, i);
6347           return -99;
6348         }
6349     }
6350
6351   if (sw_if_index_set == 0)
6352     {
6353       errmsg ("missing interface name or sw_if_index");
6354       return -99;
6355     }
6356
6357   if (vlan_id_set == 0)
6358     {
6359       errmsg ("missing vlan_id");
6360       return -99;
6361     }
6362   M (CREATE_VLAN_SUBIF, mp);
6363
6364   mp->sw_if_index = ntohl (sw_if_index);
6365   mp->vlan_id = ntohl (vlan_id);
6366
6367   S (mp);
6368   W (ret);
6369   return ret;
6370 }
6371
6372 #define foreach_create_subif_bit                \
6373 _(no_tags)                                      \
6374 _(one_tag)                                      \
6375 _(two_tags)                                     \
6376 _(dot1ad)                                       \
6377 _(exact_match)                                  \
6378 _(default_sub)                                  \
6379 _(outer_vlan_id_any)                            \
6380 _(inner_vlan_id_any)
6381
6382 #define foreach_create_subif_flag               \
6383 _(0, "no_tags")                                 \
6384 _(1, "one_tag")                                 \
6385 _(2, "two_tags")                                \
6386 _(3, "dot1ad")                                  \
6387 _(4, "exact_match")                             \
6388 _(5, "default_sub")                             \
6389 _(6, "outer_vlan_id_any")                       \
6390 _(7, "inner_vlan_id_any")
6391
6392 static int
6393 api_create_subif (vat_main_t * vam)
6394 {
6395   unformat_input_t *i = vam->input;
6396   vl_api_create_subif_t *mp;
6397   u32 sw_if_index;
6398   u8 sw_if_index_set = 0;
6399   u32 sub_id;
6400   u8 sub_id_set = 0;
6401   u32 __attribute__ ((unused)) no_tags = 0;
6402   u32 __attribute__ ((unused)) one_tag = 0;
6403   u32 __attribute__ ((unused)) two_tags = 0;
6404   u32 __attribute__ ((unused)) dot1ad = 0;
6405   u32 __attribute__ ((unused)) exact_match = 0;
6406   u32 __attribute__ ((unused)) default_sub = 0;
6407   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
6408   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
6409   u32 tmp;
6410   u16 outer_vlan_id = 0;
6411   u16 inner_vlan_id = 0;
6412   int ret;
6413
6414   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6415     {
6416       if (unformat (i, "sw_if_index %d", &sw_if_index))
6417         sw_if_index_set = 1;
6418       else
6419         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6420         sw_if_index_set = 1;
6421       else if (unformat (i, "sub_id %d", &sub_id))
6422         sub_id_set = 1;
6423       else if (unformat (i, "outer_vlan_id %d", &tmp))
6424         outer_vlan_id = tmp;
6425       else if (unformat (i, "inner_vlan_id %d", &tmp))
6426         inner_vlan_id = tmp;
6427
6428 #define _(a) else if (unformat (i, #a)) a = 1 ;
6429       foreach_create_subif_bit
6430 #undef _
6431         else
6432         {
6433           clib_warning ("parse error '%U'", format_unformat_error, i);
6434           return -99;
6435         }
6436     }
6437
6438   if (sw_if_index_set == 0)
6439     {
6440       errmsg ("missing interface name or sw_if_index");
6441       return -99;
6442     }
6443
6444   if (sub_id_set == 0)
6445     {
6446       errmsg ("missing sub_id");
6447       return -99;
6448     }
6449   M (CREATE_SUBIF, mp);
6450
6451   mp->sw_if_index = ntohl (sw_if_index);
6452   mp->sub_id = ntohl (sub_id);
6453
6454 #define _(a,b) mp->sub_if_flags |= (1 << a);
6455   foreach_create_subif_flag;
6456 #undef _
6457
6458   mp->outer_vlan_id = ntohs (outer_vlan_id);
6459   mp->inner_vlan_id = ntohs (inner_vlan_id);
6460
6461   S (mp);
6462   W (ret);
6463   return ret;
6464 }
6465
6466 static int
6467 api_ip_table_replace_begin (vat_main_t * vam)
6468 {
6469   unformat_input_t *i = vam->input;
6470   vl_api_ip_table_replace_begin_t *mp;
6471   u32 table_id = 0;
6472   u8 is_ipv6 = 0;
6473
6474   int ret;
6475   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6476     {
6477       if (unformat (i, "table %d", &table_id))
6478         ;
6479       else if (unformat (i, "ipv6"))
6480         is_ipv6 = 1;
6481       else
6482         {
6483           clib_warning ("parse error '%U'", format_unformat_error, i);
6484           return -99;
6485         }
6486     }
6487
6488   M (IP_TABLE_REPLACE_BEGIN, mp);
6489
6490   mp->table.table_id = ntohl (table_id);
6491   mp->table.is_ip6 = is_ipv6;
6492
6493   S (mp);
6494   W (ret);
6495   return ret;
6496 }
6497
6498 static int
6499 api_ip_table_flush (vat_main_t * vam)
6500 {
6501   unformat_input_t *i = vam->input;
6502   vl_api_ip_table_flush_t *mp;
6503   u32 table_id = 0;
6504   u8 is_ipv6 = 0;
6505
6506   int ret;
6507   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6508     {
6509       if (unformat (i, "table %d", &table_id))
6510         ;
6511       else if (unformat (i, "ipv6"))
6512         is_ipv6 = 1;
6513       else
6514         {
6515           clib_warning ("parse error '%U'", format_unformat_error, i);
6516           return -99;
6517         }
6518     }
6519
6520   M (IP_TABLE_FLUSH, mp);
6521
6522   mp->table.table_id = ntohl (table_id);
6523   mp->table.is_ip6 = is_ipv6;
6524
6525   S (mp);
6526   W (ret);
6527   return ret;
6528 }
6529
6530 static int
6531 api_ip_table_replace_end (vat_main_t * vam)
6532 {
6533   unformat_input_t *i = vam->input;
6534   vl_api_ip_table_replace_end_t *mp;
6535   u32 table_id = 0;
6536   u8 is_ipv6 = 0;
6537
6538   int ret;
6539   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6540     {
6541       if (unformat (i, "table %d", &table_id))
6542         ;
6543       else if (unformat (i, "ipv6"))
6544         is_ipv6 = 1;
6545       else
6546         {
6547           clib_warning ("parse error '%U'", format_unformat_error, i);
6548           return -99;
6549         }
6550     }
6551
6552   M (IP_TABLE_REPLACE_END, mp);
6553
6554   mp->table.table_id = ntohl (table_id);
6555   mp->table.is_ip6 = is_ipv6;
6556
6557   S (mp);
6558   W (ret);
6559   return ret;
6560 }
6561
6562 static int
6563 api_set_ip_flow_hash (vat_main_t * vam)
6564 {
6565   unformat_input_t *i = vam->input;
6566   vl_api_set_ip_flow_hash_t *mp;
6567   u32 vrf_id = 0;
6568   u8 is_ipv6 = 0;
6569   u8 vrf_id_set = 0;
6570   u8 src = 0;
6571   u8 dst = 0;
6572   u8 sport = 0;
6573   u8 dport = 0;
6574   u8 proto = 0;
6575   u8 reverse = 0;
6576   int ret;
6577
6578   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6579     {
6580       if (unformat (i, "vrf %d", &vrf_id))
6581         vrf_id_set = 1;
6582       else if (unformat (i, "ipv6"))
6583         is_ipv6 = 1;
6584       else if (unformat (i, "src"))
6585         src = 1;
6586       else if (unformat (i, "dst"))
6587         dst = 1;
6588       else if (unformat (i, "sport"))
6589         sport = 1;
6590       else if (unformat (i, "dport"))
6591         dport = 1;
6592       else if (unformat (i, "proto"))
6593         proto = 1;
6594       else if (unformat (i, "reverse"))
6595         reverse = 1;
6596
6597       else
6598         {
6599           clib_warning ("parse error '%U'", format_unformat_error, i);
6600           return -99;
6601         }
6602     }
6603
6604   if (vrf_id_set == 0)
6605     {
6606       errmsg ("missing vrf id");
6607       return -99;
6608     }
6609
6610   M (SET_IP_FLOW_HASH, mp);
6611   mp->src = src;
6612   mp->dst = dst;
6613   mp->sport = sport;
6614   mp->dport = dport;
6615   mp->proto = proto;
6616   mp->reverse = reverse;
6617   mp->vrf_id = ntohl (vrf_id);
6618   mp->is_ipv6 = is_ipv6;
6619
6620   S (mp);
6621   W (ret);
6622   return ret;
6623 }
6624
6625 static int
6626 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
6627 {
6628   unformat_input_t *i = vam->input;
6629   vl_api_sw_interface_ip6_enable_disable_t *mp;
6630   u32 sw_if_index;
6631   u8 sw_if_index_set = 0;
6632   u8 enable = 0;
6633   int ret;
6634
6635   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6636     {
6637       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6638         sw_if_index_set = 1;
6639       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6640         sw_if_index_set = 1;
6641       else if (unformat (i, "enable"))
6642         enable = 1;
6643       else if (unformat (i, "disable"))
6644         enable = 0;
6645       else
6646         {
6647           clib_warning ("parse error '%U'", format_unformat_error, i);
6648           return -99;
6649         }
6650     }
6651
6652   if (sw_if_index_set == 0)
6653     {
6654       errmsg ("missing interface name or sw_if_index");
6655       return -99;
6656     }
6657
6658   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
6659
6660   mp->sw_if_index = ntohl (sw_if_index);
6661   mp->enable = enable;
6662
6663   S (mp);
6664   W (ret);
6665   return ret;
6666 }
6667
6668
6669 static int
6670 api_l2_patch_add_del (vat_main_t * vam)
6671 {
6672   unformat_input_t *i = vam->input;
6673   vl_api_l2_patch_add_del_t *mp;
6674   u32 rx_sw_if_index;
6675   u8 rx_sw_if_index_set = 0;
6676   u32 tx_sw_if_index;
6677   u8 tx_sw_if_index_set = 0;
6678   u8 is_add = 1;
6679   int ret;
6680
6681   /* Parse args required to build the message */
6682   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6683     {
6684       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
6685         rx_sw_if_index_set = 1;
6686       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
6687         tx_sw_if_index_set = 1;
6688       else if (unformat (i, "rx"))
6689         {
6690           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6691             {
6692               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6693                             &rx_sw_if_index))
6694                 rx_sw_if_index_set = 1;
6695             }
6696           else
6697             break;
6698         }
6699       else if (unformat (i, "tx"))
6700         {
6701           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6702             {
6703               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6704                             &tx_sw_if_index))
6705                 tx_sw_if_index_set = 1;
6706             }
6707           else
6708             break;
6709         }
6710       else if (unformat (i, "del"))
6711         is_add = 0;
6712       else
6713         break;
6714     }
6715
6716   if (rx_sw_if_index_set == 0)
6717     {
6718       errmsg ("missing rx interface name or rx_sw_if_index");
6719       return -99;
6720     }
6721
6722   if (tx_sw_if_index_set == 0)
6723     {
6724       errmsg ("missing tx interface name or tx_sw_if_index");
6725       return -99;
6726     }
6727
6728   M (L2_PATCH_ADD_DEL, mp);
6729
6730   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
6731   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
6732   mp->is_add = is_add;
6733
6734   S (mp);
6735   W (ret);
6736   return ret;
6737 }
6738
6739 u8 is_del;
6740 u8 localsid_addr[16];
6741 u8 end_psp;
6742 u8 behavior;
6743 u32 sw_if_index;
6744 u32 vlan_index;
6745 u32 fib_table;
6746 u8 nh_addr[16];
6747
6748 static int
6749 api_sr_localsid_add_del (vat_main_t * vam)
6750 {
6751   unformat_input_t *i = vam->input;
6752   vl_api_sr_localsid_add_del_t *mp;
6753
6754   u8 is_del;
6755   ip6_address_t localsid;
6756   u8 end_psp = 0;
6757   u8 behavior = ~0;
6758   u32 sw_if_index;
6759   u32 fib_table = ~(u32) 0;
6760   ip46_address_t nh_addr;
6761   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
6762
6763   bool nexthop_set = 0;
6764
6765   int ret;
6766
6767   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6768     {
6769       if (unformat (i, "del"))
6770         is_del = 1;
6771       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
6772       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
6773         nexthop_set = 1;
6774       else if (unformat (i, "behavior %u", &behavior));
6775       else if (unformat (i, "sw_if_index %u", &sw_if_index));
6776       else if (unformat (i, "fib-table %u", &fib_table));
6777       else if (unformat (i, "end.psp %u", &behavior));
6778       else
6779         break;
6780     }
6781
6782   M (SR_LOCALSID_ADD_DEL, mp);
6783
6784   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
6785
6786   if (nexthop_set)
6787     {
6788       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
6789     }
6790   mp->behavior = behavior;
6791   mp->sw_if_index = ntohl (sw_if_index);
6792   mp->fib_table = ntohl (fib_table);
6793   mp->end_psp = end_psp;
6794   mp->is_del = is_del;
6795
6796   S (mp);
6797   W (ret);
6798   return ret;
6799 }
6800
6801 static int
6802 api_ioam_enable (vat_main_t * vam)
6803 {
6804   unformat_input_t *input = vam->input;
6805   vl_api_ioam_enable_t *mp;
6806   u32 id = 0;
6807   int has_trace_option = 0;
6808   int has_pot_option = 0;
6809   int has_seqno_option = 0;
6810   int has_analyse_option = 0;
6811   int ret;
6812
6813   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6814     {
6815       if (unformat (input, "trace"))
6816         has_trace_option = 1;
6817       else if (unformat (input, "pot"))
6818         has_pot_option = 1;
6819       else if (unformat (input, "seqno"))
6820         has_seqno_option = 1;
6821       else if (unformat (input, "analyse"))
6822         has_analyse_option = 1;
6823       else
6824         break;
6825     }
6826   M (IOAM_ENABLE, mp);
6827   mp->id = htons (id);
6828   mp->seqno = has_seqno_option;
6829   mp->analyse = has_analyse_option;
6830   mp->pot_enable = has_pot_option;
6831   mp->trace_enable = has_trace_option;
6832
6833   S (mp);
6834   W (ret);
6835   return ret;
6836 }
6837
6838
6839 static int
6840 api_ioam_disable (vat_main_t * vam)
6841 {
6842   vl_api_ioam_disable_t *mp;
6843   int ret;
6844
6845   M (IOAM_DISABLE, mp);
6846   S (mp);
6847   W (ret);
6848   return ret;
6849 }
6850
6851 #define foreach_tcp_proto_field                 \
6852 _(src_port)                                     \
6853 _(dst_port)
6854
6855 #define foreach_udp_proto_field                 \
6856 _(src_port)                                     \
6857 _(dst_port)
6858
6859 #define foreach_ip4_proto_field                 \
6860 _(src_address)                                  \
6861 _(dst_address)                                  \
6862 _(tos)                                          \
6863 _(length)                                       \
6864 _(fragment_id)                                  \
6865 _(ttl)                                          \
6866 _(protocol)                                     \
6867 _(checksum)
6868
6869 typedef struct
6870 {
6871   u16 src_port, dst_port;
6872 } tcpudp_header_t;
6873
6874 #if VPP_API_TEST_BUILTIN == 0
6875 uword
6876 unformat_tcp_mask (unformat_input_t * input, va_list * args)
6877 {
6878   u8 **maskp = va_arg (*args, u8 **);
6879   u8 *mask = 0;
6880   u8 found_something = 0;
6881   tcp_header_t *tcp;
6882
6883 #define _(a) u8 a=0;
6884   foreach_tcp_proto_field;
6885 #undef _
6886
6887   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6888     {
6889       if (0);
6890 #define _(a) else if (unformat (input, #a)) a=1;
6891       foreach_tcp_proto_field
6892 #undef _
6893         else
6894         break;
6895     }
6896
6897 #define _(a) found_something += a;
6898   foreach_tcp_proto_field;
6899 #undef _
6900
6901   if (found_something == 0)
6902     return 0;
6903
6904   vec_validate (mask, sizeof (*tcp) - 1);
6905
6906   tcp = (tcp_header_t *) mask;
6907
6908 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
6909   foreach_tcp_proto_field;
6910 #undef _
6911
6912   *maskp = mask;
6913   return 1;
6914 }
6915
6916 uword
6917 unformat_udp_mask (unformat_input_t * input, va_list * args)
6918 {
6919   u8 **maskp = va_arg (*args, u8 **);
6920   u8 *mask = 0;
6921   u8 found_something = 0;
6922   udp_header_t *udp;
6923
6924 #define _(a) u8 a=0;
6925   foreach_udp_proto_field;
6926 #undef _
6927
6928   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6929     {
6930       if (0);
6931 #define _(a) else if (unformat (input, #a)) a=1;
6932       foreach_udp_proto_field
6933 #undef _
6934         else
6935         break;
6936     }
6937
6938 #define _(a) found_something += a;
6939   foreach_udp_proto_field;
6940 #undef _
6941
6942   if (found_something == 0)
6943     return 0;
6944
6945   vec_validate (mask, sizeof (*udp) - 1);
6946
6947   udp = (udp_header_t *) mask;
6948
6949 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
6950   foreach_udp_proto_field;
6951 #undef _
6952
6953   *maskp = mask;
6954   return 1;
6955 }
6956
6957 uword
6958 unformat_l4_mask (unformat_input_t * input, va_list * args)
6959 {
6960   u8 **maskp = va_arg (*args, u8 **);
6961   u16 src_port = 0, dst_port = 0;
6962   tcpudp_header_t *tcpudp;
6963
6964   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6965     {
6966       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
6967         return 1;
6968       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
6969         return 1;
6970       else if (unformat (input, "src_port"))
6971         src_port = 0xFFFF;
6972       else if (unformat (input, "dst_port"))
6973         dst_port = 0xFFFF;
6974       else
6975         return 0;
6976     }
6977
6978   if (!src_port && !dst_port)
6979     return 0;
6980
6981   u8 *mask = 0;
6982   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
6983
6984   tcpudp = (tcpudp_header_t *) mask;
6985   tcpudp->src_port = src_port;
6986   tcpudp->dst_port = dst_port;
6987
6988   *maskp = mask;
6989
6990   return 1;
6991 }
6992
6993 uword
6994 unformat_ip4_mask (unformat_input_t * input, va_list * args)
6995 {
6996   u8 **maskp = va_arg (*args, u8 **);
6997   u8 *mask = 0;
6998   u8 found_something = 0;
6999   ip4_header_t *ip;
7000
7001 #define _(a) u8 a=0;
7002   foreach_ip4_proto_field;
7003 #undef _
7004   u8 version = 0;
7005   u8 hdr_length = 0;
7006
7007
7008   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7009     {
7010       if (unformat (input, "version"))
7011         version = 1;
7012       else if (unformat (input, "hdr_length"))
7013         hdr_length = 1;
7014       else if (unformat (input, "src"))
7015         src_address = 1;
7016       else if (unformat (input, "dst"))
7017         dst_address = 1;
7018       else if (unformat (input, "proto"))
7019         protocol = 1;
7020
7021 #define _(a) else if (unformat (input, #a)) a=1;
7022       foreach_ip4_proto_field
7023 #undef _
7024         else
7025         break;
7026     }
7027
7028 #define _(a) found_something += a;
7029   foreach_ip4_proto_field;
7030 #undef _
7031
7032   if (found_something == 0)
7033     return 0;
7034
7035   vec_validate (mask, sizeof (*ip) - 1);
7036
7037   ip = (ip4_header_t *) mask;
7038
7039 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7040   foreach_ip4_proto_field;
7041 #undef _
7042
7043   ip->ip_version_and_header_length = 0;
7044
7045   if (version)
7046     ip->ip_version_and_header_length |= 0xF0;
7047
7048   if (hdr_length)
7049     ip->ip_version_and_header_length |= 0x0F;
7050
7051   *maskp = mask;
7052   return 1;
7053 }
7054
7055 #define foreach_ip6_proto_field                 \
7056 _(src_address)                                  \
7057 _(dst_address)                                  \
7058 _(payload_length)                               \
7059 _(hop_limit)                                    \
7060 _(protocol)
7061
7062 uword
7063 unformat_ip6_mask (unformat_input_t * input, va_list * args)
7064 {
7065   u8 **maskp = va_arg (*args, u8 **);
7066   u8 *mask = 0;
7067   u8 found_something = 0;
7068   ip6_header_t *ip;
7069   u32 ip_version_traffic_class_and_flow_label;
7070
7071 #define _(a) u8 a=0;
7072   foreach_ip6_proto_field;
7073 #undef _
7074   u8 version = 0;
7075   u8 traffic_class = 0;
7076   u8 flow_label = 0;
7077
7078   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7079     {
7080       if (unformat (input, "version"))
7081         version = 1;
7082       else if (unformat (input, "traffic-class"))
7083         traffic_class = 1;
7084       else if (unformat (input, "flow-label"))
7085         flow_label = 1;
7086       else if (unformat (input, "src"))
7087         src_address = 1;
7088       else if (unformat (input, "dst"))
7089         dst_address = 1;
7090       else if (unformat (input, "proto"))
7091         protocol = 1;
7092
7093 #define _(a) else if (unformat (input, #a)) a=1;
7094       foreach_ip6_proto_field
7095 #undef _
7096         else
7097         break;
7098     }
7099
7100 #define _(a) found_something += a;
7101   foreach_ip6_proto_field;
7102 #undef _
7103
7104   if (found_something == 0)
7105     return 0;
7106
7107   vec_validate (mask, sizeof (*ip) - 1);
7108
7109   ip = (ip6_header_t *) mask;
7110
7111 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7112   foreach_ip6_proto_field;
7113 #undef _
7114
7115   ip_version_traffic_class_and_flow_label = 0;
7116
7117   if (version)
7118     ip_version_traffic_class_and_flow_label |= 0xF0000000;
7119
7120   if (traffic_class)
7121     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
7122
7123   if (flow_label)
7124     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
7125
7126   ip->ip_version_traffic_class_and_flow_label =
7127     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7128
7129   *maskp = mask;
7130   return 1;
7131 }
7132
7133 uword
7134 unformat_l3_mask (unformat_input_t * input, va_list * args)
7135 {
7136   u8 **maskp = va_arg (*args, u8 **);
7137
7138   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7139     {
7140       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
7141         return 1;
7142       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
7143         return 1;
7144       else
7145         break;
7146     }
7147   return 0;
7148 }
7149
7150 uword
7151 unformat_l2_mask (unformat_input_t * input, va_list * args)
7152 {
7153   u8 **maskp = va_arg (*args, u8 **);
7154   u8 *mask = 0;
7155   u8 src = 0;
7156   u8 dst = 0;
7157   u8 proto = 0;
7158   u8 tag1 = 0;
7159   u8 tag2 = 0;
7160   u8 ignore_tag1 = 0;
7161   u8 ignore_tag2 = 0;
7162   u8 cos1 = 0;
7163   u8 cos2 = 0;
7164   u8 dot1q = 0;
7165   u8 dot1ad = 0;
7166   int len = 14;
7167
7168   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7169     {
7170       if (unformat (input, "src"))
7171         src = 1;
7172       else if (unformat (input, "dst"))
7173         dst = 1;
7174       else if (unformat (input, "proto"))
7175         proto = 1;
7176       else if (unformat (input, "tag1"))
7177         tag1 = 1;
7178       else if (unformat (input, "tag2"))
7179         tag2 = 1;
7180       else if (unformat (input, "ignore-tag1"))
7181         ignore_tag1 = 1;
7182       else if (unformat (input, "ignore-tag2"))
7183         ignore_tag2 = 1;
7184       else if (unformat (input, "cos1"))
7185         cos1 = 1;
7186       else if (unformat (input, "cos2"))
7187         cos2 = 1;
7188       else if (unformat (input, "dot1q"))
7189         dot1q = 1;
7190       else if (unformat (input, "dot1ad"))
7191         dot1ad = 1;
7192       else
7193         break;
7194     }
7195   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7196        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7197     return 0;
7198
7199   if (tag1 || ignore_tag1 || cos1 || dot1q)
7200     len = 18;
7201   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7202     len = 22;
7203
7204   vec_validate (mask, len - 1);
7205
7206   if (dst)
7207     clib_memset (mask, 0xff, 6);
7208
7209   if (src)
7210     clib_memset (mask + 6, 0xff, 6);
7211
7212   if (tag2 || dot1ad)
7213     {
7214       /* inner vlan tag */
7215       if (tag2)
7216         {
7217           mask[19] = 0xff;
7218           mask[18] = 0x0f;
7219         }
7220       if (cos2)
7221         mask[18] |= 0xe0;
7222       if (proto)
7223         mask[21] = mask[20] = 0xff;
7224       if (tag1)
7225         {
7226           mask[15] = 0xff;
7227           mask[14] = 0x0f;
7228         }
7229       if (cos1)
7230         mask[14] |= 0xe0;
7231       *maskp = mask;
7232       return 1;
7233     }
7234   if (tag1 | dot1q)
7235     {
7236       if (tag1)
7237         {
7238           mask[15] = 0xff;
7239           mask[14] = 0x0f;
7240         }
7241       if (cos1)
7242         mask[14] |= 0xe0;
7243       if (proto)
7244         mask[16] = mask[17] = 0xff;
7245
7246       *maskp = mask;
7247       return 1;
7248     }
7249   if (cos2)
7250     mask[18] |= 0xe0;
7251   if (cos1)
7252     mask[14] |= 0xe0;
7253   if (proto)
7254     mask[12] = mask[13] = 0xff;
7255
7256   *maskp = mask;
7257   return 1;
7258 }
7259
7260 uword
7261 unformat_classify_mask (unformat_input_t * input, va_list * args)
7262 {
7263   u8 **maskp = va_arg (*args, u8 **);
7264   u32 *skipp = va_arg (*args, u32 *);
7265   u32 *matchp = va_arg (*args, u32 *);
7266   u32 match;
7267   u8 *mask = 0;
7268   u8 *l2 = 0;
7269   u8 *l3 = 0;
7270   u8 *l4 = 0;
7271   int i;
7272
7273   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7274     {
7275       if (unformat (input, "hex %U", unformat_hex_string, &mask))
7276         ;
7277       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7278         ;
7279       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7280         ;
7281       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
7282         ;
7283       else
7284         break;
7285     }
7286
7287   if (l4 && !l3)
7288     {
7289       vec_free (mask);
7290       vec_free (l2);
7291       vec_free (l4);
7292       return 0;
7293     }
7294
7295   if (mask || l2 || l3 || l4)
7296     {
7297       if (l2 || l3 || l4)
7298         {
7299           /* "With a free Ethernet header in every package" */
7300           if (l2 == 0)
7301             vec_validate (l2, 13);
7302           mask = l2;
7303           if (vec_len (l3))
7304             {
7305               vec_append (mask, l3);
7306               vec_free (l3);
7307             }
7308           if (vec_len (l4))
7309             {
7310               vec_append (mask, l4);
7311               vec_free (l4);
7312             }
7313         }
7314
7315       /* Scan forward looking for the first significant mask octet */
7316       for (i = 0; i < vec_len (mask); i++)
7317         if (mask[i])
7318           break;
7319
7320       /* compute (skip, match) params */
7321       *skipp = i / sizeof (u32x4);
7322       vec_delete (mask, *skipp * sizeof (u32x4), 0);
7323
7324       /* Pad mask to an even multiple of the vector size */
7325       while (vec_len (mask) % sizeof (u32x4))
7326         vec_add1 (mask, 0);
7327
7328       match = vec_len (mask) / sizeof (u32x4);
7329
7330       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
7331         {
7332           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
7333           if (*tmp || *(tmp + 1))
7334             break;
7335           match--;
7336         }
7337       if (match == 0)
7338         clib_warning ("BUG: match 0");
7339
7340       _vec_len (mask) = match * sizeof (u32x4);
7341
7342       *matchp = match;
7343       *maskp = mask;
7344
7345       return 1;
7346     }
7347
7348   return 0;
7349 }
7350 #endif /* VPP_API_TEST_BUILTIN */
7351
7352 #define foreach_l2_next                         \
7353 _(drop, DROP)                                   \
7354 _(ethernet, ETHERNET_INPUT)                     \
7355 _(ip4, IP4_INPUT)                               \
7356 _(ip6, IP6_INPUT)
7357
7358 uword
7359 unformat_l2_next_index (unformat_input_t * input, va_list * args)
7360 {
7361   u32 *miss_next_indexp = va_arg (*args, u32 *);
7362   u32 next_index = 0;
7363   u32 tmp;
7364
7365 #define _(n,N) \
7366   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
7367   foreach_l2_next;
7368 #undef _
7369
7370   if (unformat (input, "%d", &tmp))
7371     {
7372       next_index = tmp;
7373       goto out;
7374     }
7375
7376   return 0;
7377
7378 out:
7379   *miss_next_indexp = next_index;
7380   return 1;
7381 }
7382
7383 #define foreach_ip_next                         \
7384 _(drop, DROP)                                   \
7385 _(local, LOCAL)                                 \
7386 _(rewrite, REWRITE)
7387
7388 uword
7389 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
7390 {
7391   u32 *miss_next_indexp = va_arg (*args, u32 *);
7392   u32 next_index = 0;
7393   u32 tmp;
7394
7395 #define _(n,N) \
7396   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
7397   foreach_ip_next;
7398 #undef _
7399
7400   if (unformat (input, "%d", &tmp))
7401     {
7402       next_index = tmp;
7403       goto out;
7404     }
7405
7406   return 0;
7407
7408 out:
7409   *miss_next_indexp = next_index;
7410   return 1;
7411 }
7412
7413 #define foreach_acl_next                        \
7414 _(deny, DENY)
7415
7416 uword
7417 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
7418 {
7419   u32 *miss_next_indexp = va_arg (*args, u32 *);
7420   u32 next_index = 0;
7421   u32 tmp;
7422
7423 #define _(n,N) \
7424   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
7425   foreach_acl_next;
7426 #undef _
7427
7428   if (unformat (input, "permit"))
7429     {
7430       next_index = ~0;
7431       goto out;
7432     }
7433   else if (unformat (input, "%d", &tmp))
7434     {
7435       next_index = tmp;
7436       goto out;
7437     }
7438
7439   return 0;
7440
7441 out:
7442   *miss_next_indexp = next_index;
7443   return 1;
7444 }
7445
7446 uword
7447 unformat_policer_precolor (unformat_input_t * input, va_list * args)
7448 {
7449   u32 *r = va_arg (*args, u32 *);
7450
7451   if (unformat (input, "conform-color"))
7452     *r = POLICE_CONFORM;
7453   else if (unformat (input, "exceed-color"))
7454     *r = POLICE_EXCEED;
7455   else
7456     return 0;
7457
7458   return 1;
7459 }
7460
7461 #if VPP_API_TEST_BUILTIN == 0
7462 uword
7463 unformat_l4_match (unformat_input_t * input, va_list * args)
7464 {
7465   u8 **matchp = va_arg (*args, u8 **);
7466
7467   u8 *proto_header = 0;
7468   int src_port = 0;
7469   int dst_port = 0;
7470
7471   tcpudp_header_t h;
7472
7473   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7474     {
7475       if (unformat (input, "src_port %d", &src_port))
7476         ;
7477       else if (unformat (input, "dst_port %d", &dst_port))
7478         ;
7479       else
7480         return 0;
7481     }
7482
7483   h.src_port = clib_host_to_net_u16 (src_port);
7484   h.dst_port = clib_host_to_net_u16 (dst_port);
7485   vec_validate (proto_header, sizeof (h) - 1);
7486   memcpy (proto_header, &h, sizeof (h));
7487
7488   *matchp = proto_header;
7489
7490   return 1;
7491 }
7492
7493 uword
7494 unformat_ip4_match (unformat_input_t * input, va_list * args)
7495 {
7496   u8 **matchp = va_arg (*args, u8 **);
7497   u8 *match = 0;
7498   ip4_header_t *ip;
7499   int version = 0;
7500   u32 version_val;
7501   int hdr_length = 0;
7502   u32 hdr_length_val;
7503   int src = 0, dst = 0;
7504   ip4_address_t src_val, dst_val;
7505   int proto = 0;
7506   u32 proto_val;
7507   int tos = 0;
7508   u32 tos_val;
7509   int length = 0;
7510   u32 length_val;
7511   int fragment_id = 0;
7512   u32 fragment_id_val;
7513   int ttl = 0;
7514   int ttl_val;
7515   int checksum = 0;
7516   u32 checksum_val;
7517
7518   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7519     {
7520       if (unformat (input, "version %d", &version_val))
7521         version = 1;
7522       else if (unformat (input, "hdr_length %d", &hdr_length_val))
7523         hdr_length = 1;
7524       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
7525         src = 1;
7526       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
7527         dst = 1;
7528       else if (unformat (input, "proto %d", &proto_val))
7529         proto = 1;
7530       else if (unformat (input, "tos %d", &tos_val))
7531         tos = 1;
7532       else if (unformat (input, "length %d", &length_val))
7533         length = 1;
7534       else if (unformat (input, "fragment_id %d", &fragment_id_val))
7535         fragment_id = 1;
7536       else if (unformat (input, "ttl %d", &ttl_val))
7537         ttl = 1;
7538       else if (unformat (input, "checksum %d", &checksum_val))
7539         checksum = 1;
7540       else
7541         break;
7542     }
7543
7544   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
7545       + ttl + checksum == 0)
7546     return 0;
7547
7548   /*
7549    * Aligned because we use the real comparison functions
7550    */
7551   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7552
7553   ip = (ip4_header_t *) match;
7554
7555   /* These are realistically matched in practice */
7556   if (src)
7557     ip->src_address.as_u32 = src_val.as_u32;
7558
7559   if (dst)
7560     ip->dst_address.as_u32 = dst_val.as_u32;
7561
7562   if (proto)
7563     ip->protocol = proto_val;
7564
7565
7566   /* These are not, but they're included for completeness */
7567   if (version)
7568     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
7569
7570   if (hdr_length)
7571     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
7572
7573   if (tos)
7574     ip->tos = tos_val;
7575
7576   if (length)
7577     ip->length = clib_host_to_net_u16 (length_val);
7578
7579   if (ttl)
7580     ip->ttl = ttl_val;
7581
7582   if (checksum)
7583     ip->checksum = clib_host_to_net_u16 (checksum_val);
7584
7585   *matchp = match;
7586   return 1;
7587 }
7588
7589 uword
7590 unformat_ip6_match (unformat_input_t * input, va_list * args)
7591 {
7592   u8 **matchp = va_arg (*args, u8 **);
7593   u8 *match = 0;
7594   ip6_header_t *ip;
7595   int version = 0;
7596   u32 version_val;
7597   u8 traffic_class = 0;
7598   u32 traffic_class_val = 0;
7599   u8 flow_label = 0;
7600   u8 flow_label_val;
7601   int src = 0, dst = 0;
7602   ip6_address_t src_val, dst_val;
7603   int proto = 0;
7604   u32 proto_val;
7605   int payload_length = 0;
7606   u32 payload_length_val;
7607   int hop_limit = 0;
7608   int hop_limit_val;
7609   u32 ip_version_traffic_class_and_flow_label;
7610
7611   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7612     {
7613       if (unformat (input, "version %d", &version_val))
7614         version = 1;
7615       else if (unformat (input, "traffic_class %d", &traffic_class_val))
7616         traffic_class = 1;
7617       else if (unformat (input, "flow_label %d", &flow_label_val))
7618         flow_label = 1;
7619       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
7620         src = 1;
7621       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
7622         dst = 1;
7623       else if (unformat (input, "proto %d", &proto_val))
7624         proto = 1;
7625       else if (unformat (input, "payload_length %d", &payload_length_val))
7626         payload_length = 1;
7627       else if (unformat (input, "hop_limit %d", &hop_limit_val))
7628         hop_limit = 1;
7629       else
7630         break;
7631     }
7632
7633   if (version + traffic_class + flow_label + src + dst + proto +
7634       payload_length + hop_limit == 0)
7635     return 0;
7636
7637   /*
7638    * Aligned because we use the real comparison functions
7639    */
7640   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7641
7642   ip = (ip6_header_t *) match;
7643
7644   if (src)
7645     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
7646
7647   if (dst)
7648     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
7649
7650   if (proto)
7651     ip->protocol = proto_val;
7652
7653   ip_version_traffic_class_and_flow_label = 0;
7654
7655   if (version)
7656     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
7657
7658   if (traffic_class)
7659     ip_version_traffic_class_and_flow_label |=
7660       (traffic_class_val & 0xFF) << 20;
7661
7662   if (flow_label)
7663     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
7664
7665   ip->ip_version_traffic_class_and_flow_label =
7666     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7667
7668   if (payload_length)
7669     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
7670
7671   if (hop_limit)
7672     ip->hop_limit = hop_limit_val;
7673
7674   *matchp = match;
7675   return 1;
7676 }
7677
7678 uword
7679 unformat_l3_match (unformat_input_t * input, va_list * args)
7680 {
7681   u8 **matchp = va_arg (*args, u8 **);
7682
7683   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7684     {
7685       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
7686         return 1;
7687       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
7688         return 1;
7689       else
7690         break;
7691     }
7692   return 0;
7693 }
7694
7695 uword
7696 unformat_vlan_tag (unformat_input_t * input, va_list * args)
7697 {
7698   u8 *tagp = va_arg (*args, u8 *);
7699   u32 tag;
7700
7701   if (unformat (input, "%d", &tag))
7702     {
7703       tagp[0] = (tag >> 8) & 0x0F;
7704       tagp[1] = tag & 0xFF;
7705       return 1;
7706     }
7707
7708   return 0;
7709 }
7710
7711 uword
7712 unformat_l2_match (unformat_input_t * input, va_list * args)
7713 {
7714   u8 **matchp = va_arg (*args, u8 **);
7715   u8 *match = 0;
7716   u8 src = 0;
7717   u8 src_val[6];
7718   u8 dst = 0;
7719   u8 dst_val[6];
7720   u8 proto = 0;
7721   u16 proto_val;
7722   u8 tag1 = 0;
7723   u8 tag1_val[2];
7724   u8 tag2 = 0;
7725   u8 tag2_val[2];
7726   int len = 14;
7727   u8 ignore_tag1 = 0;
7728   u8 ignore_tag2 = 0;
7729   u8 cos1 = 0;
7730   u8 cos2 = 0;
7731   u32 cos1_val = 0;
7732   u32 cos2_val = 0;
7733
7734   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7735     {
7736       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
7737         src = 1;
7738       else
7739         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
7740         dst = 1;
7741       else if (unformat (input, "proto %U",
7742                          unformat_ethernet_type_host_byte_order, &proto_val))
7743         proto = 1;
7744       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
7745         tag1 = 1;
7746       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
7747         tag2 = 1;
7748       else if (unformat (input, "ignore-tag1"))
7749         ignore_tag1 = 1;
7750       else if (unformat (input, "ignore-tag2"))
7751         ignore_tag2 = 1;
7752       else if (unformat (input, "cos1 %d", &cos1_val))
7753         cos1 = 1;
7754       else if (unformat (input, "cos2 %d", &cos2_val))
7755         cos2 = 1;
7756       else
7757         break;
7758     }
7759   if ((src + dst + proto + tag1 + tag2 +
7760        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7761     return 0;
7762
7763   if (tag1 || ignore_tag1 || cos1)
7764     len = 18;
7765   if (tag2 || ignore_tag2 || cos2)
7766     len = 22;
7767
7768   vec_validate_aligned (match, len - 1, sizeof (u32x4));
7769
7770   if (dst)
7771     clib_memcpy (match, dst_val, 6);
7772
7773   if (src)
7774     clib_memcpy (match + 6, src_val, 6);
7775
7776   if (tag2)
7777     {
7778       /* inner vlan tag */
7779       match[19] = tag2_val[1];
7780       match[18] = tag2_val[0];
7781       if (cos2)
7782         match[18] |= (cos2_val & 0x7) << 5;
7783       if (proto)
7784         {
7785           match[21] = proto_val & 0xff;
7786           match[20] = proto_val >> 8;
7787         }
7788       if (tag1)
7789         {
7790           match[15] = tag1_val[1];
7791           match[14] = tag1_val[0];
7792         }
7793       if (cos1)
7794         match[14] |= (cos1_val & 0x7) << 5;
7795       *matchp = match;
7796       return 1;
7797     }
7798   if (tag1)
7799     {
7800       match[15] = tag1_val[1];
7801       match[14] = tag1_val[0];
7802       if (proto)
7803         {
7804           match[17] = proto_val & 0xff;
7805           match[16] = proto_val >> 8;
7806         }
7807       if (cos1)
7808         match[14] |= (cos1_val & 0x7) << 5;
7809
7810       *matchp = match;
7811       return 1;
7812     }
7813   if (cos2)
7814     match[18] |= (cos2_val & 0x7) << 5;
7815   if (cos1)
7816     match[14] |= (cos1_val & 0x7) << 5;
7817   if (proto)
7818     {
7819       match[13] = proto_val & 0xff;
7820       match[12] = proto_val >> 8;
7821     }
7822
7823   *matchp = match;
7824   return 1;
7825 }
7826
7827 uword
7828 unformat_qos_source (unformat_input_t * input, va_list * args)
7829 {
7830   int *qs = va_arg (*args, int *);
7831
7832   if (unformat (input, "ip"))
7833     *qs = QOS_SOURCE_IP;
7834   else if (unformat (input, "mpls"))
7835     *qs = QOS_SOURCE_MPLS;
7836   else if (unformat (input, "ext"))
7837     *qs = QOS_SOURCE_EXT;
7838   else if (unformat (input, "vlan"))
7839     *qs = QOS_SOURCE_VLAN;
7840   else
7841     return 0;
7842
7843   return 1;
7844 }
7845 #endif
7846
7847 uword
7848 api_unformat_classify_match (unformat_input_t * input, va_list * args)
7849 {
7850   u8 **matchp = va_arg (*args, u8 **);
7851   u32 skip_n_vectors = va_arg (*args, u32);
7852   u32 match_n_vectors = va_arg (*args, u32);
7853
7854   u8 *match = 0;
7855   u8 *l2 = 0;
7856   u8 *l3 = 0;
7857   u8 *l4 = 0;
7858
7859   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7860     {
7861       if (unformat (input, "hex %U", unformat_hex_string, &match))
7862         ;
7863       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
7864         ;
7865       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
7866         ;
7867       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
7868         ;
7869       else
7870         break;
7871     }
7872
7873   if (l4 && !l3)
7874     {
7875       vec_free (match);
7876       vec_free (l2);
7877       vec_free (l4);
7878       return 0;
7879     }
7880
7881   if (match || l2 || l3 || l4)
7882     {
7883       if (l2 || l3 || l4)
7884         {
7885           /* "Win a free Ethernet header in every packet" */
7886           if (l2 == 0)
7887             vec_validate_aligned (l2, 13, sizeof (u32x4));
7888           match = l2;
7889           if (vec_len (l3))
7890             {
7891               vec_append_aligned (match, l3, sizeof (u32x4));
7892               vec_free (l3);
7893             }
7894           if (vec_len (l4))
7895             {
7896               vec_append_aligned (match, l4, sizeof (u32x4));
7897               vec_free (l4);
7898             }
7899         }
7900
7901       /* Make sure the vector is big enough even if key is all 0's */
7902       vec_validate_aligned
7903         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
7904          sizeof (u32x4));
7905
7906       /* Set size, include skipped vectors */
7907       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
7908
7909       *matchp = match;
7910
7911       return 1;
7912     }
7913
7914   return 0;
7915 }
7916
7917 static int
7918 api_set_ipfix_exporter (vat_main_t *vam)
7919 {
7920   unformat_input_t *i = vam->input;
7921   vl_api_set_ipfix_exporter_t *mp;
7922   ip4_address_t collector_address;
7923   u8 collector_address_set = 0;
7924   u32 collector_port = ~0;
7925   ip4_address_t src_address;
7926   u8 src_address_set = 0;
7927   u32 vrf_id = ~0;
7928   u32 path_mtu = ~0;
7929   u32 template_interval = ~0;
7930   u8 udp_checksum = 0;
7931   int ret;
7932
7933   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7934     {
7935       if (unformat (i, "collector_address %U", unformat_ip4_address,
7936                     &collector_address))
7937         collector_address_set = 1;
7938       else if (unformat (i, "collector_port %d", &collector_port))
7939         ;
7940       else if (unformat (i, "src_address %U", unformat_ip4_address,
7941                          &src_address))
7942         src_address_set = 1;
7943       else if (unformat (i, "vrf_id %d", &vrf_id))
7944         ;
7945       else if (unformat (i, "path_mtu %d", &path_mtu))
7946         ;
7947       else if (unformat (i, "template_interval %d", &template_interval))
7948         ;
7949       else if (unformat (i, "udp_checksum"))
7950         udp_checksum = 1;
7951       else
7952         break;
7953     }
7954
7955   if (collector_address_set == 0)
7956     {
7957       errmsg ("collector_address required");
7958       return -99;
7959     }
7960
7961   if (src_address_set == 0)
7962     {
7963       errmsg ("src_address required");
7964       return -99;
7965     }
7966
7967   M (SET_IPFIX_EXPORTER, mp);
7968
7969   memcpy (mp->collector_address.un.ip4, collector_address.data,
7970           sizeof (collector_address.data));
7971   mp->collector_port = htons ((u16) collector_port);
7972   memcpy (mp->src_address.un.ip4, src_address.data,
7973           sizeof (src_address.data));
7974   mp->vrf_id = htonl (vrf_id);
7975   mp->path_mtu = htonl (path_mtu);
7976   mp->template_interval = htonl (template_interval);
7977   mp->udp_checksum = udp_checksum;
7978
7979   S (mp);
7980   W (ret);
7981   return ret;
7982 }
7983
7984 static int
7985 api_set_ipfix_classify_stream (vat_main_t * vam)
7986 {
7987   unformat_input_t *i = vam->input;
7988   vl_api_set_ipfix_classify_stream_t *mp;
7989   u32 domain_id = 0;
7990   u32 src_port = UDP_DST_PORT_ipfix;
7991   int ret;
7992
7993   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7994     {
7995       if (unformat (i, "domain %d", &domain_id))
7996         ;
7997       else if (unformat (i, "src_port %d", &src_port))
7998         ;
7999       else
8000         {
8001           errmsg ("unknown input `%U'", format_unformat_error, i);
8002           return -99;
8003         }
8004     }
8005
8006   M (SET_IPFIX_CLASSIFY_STREAM, mp);
8007
8008   mp->domain_id = htonl (domain_id);
8009   mp->src_port = htons ((u16) src_port);
8010
8011   S (mp);
8012   W (ret);
8013   return ret;
8014 }
8015
8016 static int
8017 api_ipfix_classify_table_add_del (vat_main_t * vam)
8018 {
8019   unformat_input_t *i = vam->input;
8020   vl_api_ipfix_classify_table_add_del_t *mp;
8021   int is_add = -1;
8022   u32 classify_table_index = ~0;
8023   u8 ip_version = 0;
8024   u8 transport_protocol = 255;
8025   int ret;
8026
8027   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8028     {
8029       if (unformat (i, "add"))
8030         is_add = 1;
8031       else if (unformat (i, "del"))
8032         is_add = 0;
8033       else if (unformat (i, "table %d", &classify_table_index))
8034         ;
8035       else if (unformat (i, "ip4"))
8036         ip_version = 4;
8037       else if (unformat (i, "ip6"))
8038         ip_version = 6;
8039       else if (unformat (i, "tcp"))
8040         transport_protocol = 6;
8041       else if (unformat (i, "udp"))
8042         transport_protocol = 17;
8043       else
8044         {
8045           errmsg ("unknown input `%U'", format_unformat_error, i);
8046           return -99;
8047         }
8048     }
8049
8050   if (is_add == -1)
8051     {
8052       errmsg ("expecting: add|del");
8053       return -99;
8054     }
8055   if (classify_table_index == ~0)
8056     {
8057       errmsg ("classifier table not specified");
8058       return -99;
8059     }
8060   if (ip_version == 0)
8061     {
8062       errmsg ("IP version not specified");
8063       return -99;
8064     }
8065
8066   M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp);
8067
8068   mp->is_add = is_add;
8069   mp->table_id = htonl (classify_table_index);
8070   mp->ip_version = ip_version;
8071   mp->transport_protocol = transport_protocol;
8072
8073   S (mp);
8074   W (ret);
8075   return ret;
8076 }
8077
8078 static int
8079 api_get_node_index (vat_main_t * vam)
8080 {
8081   unformat_input_t *i = vam->input;
8082   vl_api_get_node_index_t *mp;
8083   u8 *name = 0;
8084   int ret;
8085
8086   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8087     {
8088       if (unformat (i, "node %s", &name))
8089         ;
8090       else
8091         break;
8092     }
8093   if (name == 0)
8094     {
8095       errmsg ("node name required");
8096       return -99;
8097     }
8098   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
8099     {
8100       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
8101       return -99;
8102     }
8103
8104   M (GET_NODE_INDEX, mp);
8105   clib_memcpy (mp->node_name, name, vec_len (name));
8106   vec_free (name);
8107
8108   S (mp);
8109   W (ret);
8110   return ret;
8111 }
8112
8113 static int
8114 api_get_next_index (vat_main_t * vam)
8115 {
8116   unformat_input_t *i = vam->input;
8117   vl_api_get_next_index_t *mp;
8118   u8 *node_name = 0, *next_node_name = 0;
8119   int ret;
8120
8121   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8122     {
8123       if (unformat (i, "node-name %s", &node_name))
8124         ;
8125       else if (unformat (i, "next-node-name %s", &next_node_name))
8126         break;
8127     }
8128
8129   if (node_name == 0)
8130     {
8131       errmsg ("node name required");
8132       return -99;
8133     }
8134   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
8135     {
8136       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
8137       return -99;
8138     }
8139
8140   if (next_node_name == 0)
8141     {
8142       errmsg ("next node name required");
8143       return -99;
8144     }
8145   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
8146     {
8147       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
8148       return -99;
8149     }
8150
8151   M (GET_NEXT_INDEX, mp);
8152   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
8153   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
8154   vec_free (node_name);
8155   vec_free (next_node_name);
8156
8157   S (mp);
8158   W (ret);
8159   return ret;
8160 }
8161
8162 static int
8163 api_add_node_next (vat_main_t * vam)
8164 {
8165   unformat_input_t *i = vam->input;
8166   vl_api_add_node_next_t *mp;
8167   u8 *name = 0;
8168   u8 *next = 0;
8169   int ret;
8170
8171   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8172     {
8173       if (unformat (i, "node %s", &name))
8174         ;
8175       else if (unformat (i, "next %s", &next))
8176         ;
8177       else
8178         break;
8179     }
8180   if (name == 0)
8181     {
8182       errmsg ("node name required");
8183       return -99;
8184     }
8185   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
8186     {
8187       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
8188       return -99;
8189     }
8190   if (next == 0)
8191     {
8192       errmsg ("next node required");
8193       return -99;
8194     }
8195   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
8196     {
8197       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
8198       return -99;
8199     }
8200
8201   M (ADD_NODE_NEXT, mp);
8202   clib_memcpy (mp->node_name, name, vec_len (name));
8203   clib_memcpy (mp->next_name, next, vec_len (next));
8204   vec_free (name);
8205   vec_free (next);
8206
8207   S (mp);
8208   W (ret);
8209   return ret;
8210 }
8211
8212 static void vl_api_sw_interface_tap_v2_details_t_handler
8213   (vl_api_sw_interface_tap_v2_details_t * mp)
8214 {
8215   vat_main_t *vam = &vat_main;
8216
8217   u8 *ip4 =
8218     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
8219             mp->host_ip4_prefix.len);
8220   u8 *ip6 =
8221     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
8222             mp->host_ip6_prefix.len);
8223
8224   print (vam->ofp,
8225          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
8226          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
8227          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
8228          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
8229          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
8230
8231   vec_free (ip4);
8232   vec_free (ip6);
8233 }
8234
8235 static void vl_api_sw_interface_tap_v2_details_t_handler_json
8236   (vl_api_sw_interface_tap_v2_details_t * mp)
8237 {
8238   vat_main_t *vam = &vat_main;
8239   vat_json_node_t *node = NULL;
8240
8241   if (VAT_JSON_ARRAY != vam->json_tree.type)
8242     {
8243       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8244       vat_json_init_array (&vam->json_tree);
8245     }
8246   node = vat_json_array_add (&vam->json_tree);
8247
8248   vat_json_init_object (node);
8249   vat_json_object_add_uint (node, "id", ntohl (mp->id));
8250   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8251   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
8252   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
8253   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
8254   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
8255   vat_json_object_add_string_copy (node, "host_mac_addr",
8256                                    format (0, "%U", format_ethernet_address,
8257                                            &mp->host_mac_addr));
8258   vat_json_object_add_string_copy (node, "host_namespace",
8259                                    mp->host_namespace);
8260   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
8261   vat_json_object_add_string_copy (node, "host_ip4_addr",
8262                                    format (0, "%U/%d", format_ip4_address,
8263                                            mp->host_ip4_prefix.address,
8264                                            mp->host_ip4_prefix.len));
8265   vat_json_object_add_string_copy (node, "host_ip6_prefix",
8266                                    format (0, "%U/%d", format_ip6_address,
8267                                            mp->host_ip6_prefix.address,
8268                                            mp->host_ip6_prefix.len));
8269
8270 }
8271
8272 static int
8273 api_sw_interface_tap_v2_dump (vat_main_t * vam)
8274 {
8275   vl_api_sw_interface_tap_v2_dump_t *mp;
8276   vl_api_control_ping_t *mp_ping;
8277   int ret;
8278
8279   print (vam->ofp,
8280          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
8281          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
8282          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
8283          "host_ip6_addr");
8284
8285   /* Get list of tap interfaces */
8286   M (SW_INTERFACE_TAP_V2_DUMP, mp);
8287   S (mp);
8288
8289   /* Use a control ping for synchronization */
8290   MPING (CONTROL_PING, mp_ping);
8291   S (mp_ping);
8292
8293   W (ret);
8294   return ret;
8295 }
8296
8297 static void vl_api_sw_interface_virtio_pci_details_t_handler
8298   (vl_api_sw_interface_virtio_pci_details_t * mp)
8299 {
8300   vat_main_t *vam = &vat_main;
8301
8302   typedef union
8303   {
8304     struct
8305     {
8306       u16 domain;
8307       u8 bus;
8308       u8 slot:5;
8309       u8 function:3;
8310     };
8311     u32 as_u32;
8312   } pci_addr_t;
8313   pci_addr_t addr;
8314
8315   addr.domain = ntohs (mp->pci_addr.domain);
8316   addr.bus = mp->pci_addr.bus;
8317   addr.slot = mp->pci_addr.slot;
8318   addr.function = mp->pci_addr.function;
8319
8320   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
8321                          addr.slot, addr.function);
8322
8323   print (vam->ofp,
8324          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
8325          pci_addr, ntohl (mp->sw_if_index),
8326          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
8327          format_ethernet_address, mp->mac_addr,
8328          clib_net_to_host_u64 (mp->features));
8329   vec_free (pci_addr);
8330 }
8331
8332 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
8333   (vl_api_sw_interface_virtio_pci_details_t * mp)
8334 {
8335   vat_main_t *vam = &vat_main;
8336   vat_json_node_t *node = NULL;
8337   vlib_pci_addr_t pci_addr;
8338
8339   if (VAT_JSON_ARRAY != vam->json_tree.type)
8340     {
8341       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8342       vat_json_init_array (&vam->json_tree);
8343     }
8344   node = vat_json_array_add (&vam->json_tree);
8345
8346   pci_addr.domain = ntohs (mp->pci_addr.domain);
8347   pci_addr.bus = mp->pci_addr.bus;
8348   pci_addr.slot = mp->pci_addr.slot;
8349   pci_addr.function = mp->pci_addr.function;
8350
8351   vat_json_init_object (node);
8352   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
8353   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8354   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
8355   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
8356   vat_json_object_add_uint (node, "features",
8357                             clib_net_to_host_u64 (mp->features));
8358   vat_json_object_add_string_copy (node, "mac_addr",
8359                                    format (0, "%U", format_ethernet_address,
8360                                            &mp->mac_addr));
8361 }
8362
8363 static int
8364 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
8365 {
8366   vl_api_sw_interface_virtio_pci_dump_t *mp;
8367   vl_api_control_ping_t *mp_ping;
8368   int ret;
8369
8370   print (vam->ofp,
8371          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
8372          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
8373          "mac_addr", "features");
8374
8375   /* Get list of tap interfaces */
8376   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
8377   S (mp);
8378
8379   /* Use a control ping for synchronization */
8380   MPING (CONTROL_PING, mp_ping);
8381   S (mp_ping);
8382
8383   W (ret);
8384   return ret;
8385 }
8386
8387 static int
8388 api_l2_fib_clear_table (vat_main_t * vam)
8389 {
8390 //  unformat_input_t * i = vam->input;
8391   vl_api_l2_fib_clear_table_t *mp;
8392   int ret;
8393
8394   M (L2_FIB_CLEAR_TABLE, mp);
8395
8396   S (mp);
8397   W (ret);
8398   return ret;
8399 }
8400
8401 static int
8402 api_l2_interface_efp_filter (vat_main_t * vam)
8403 {
8404   unformat_input_t *i = vam->input;
8405   vl_api_l2_interface_efp_filter_t *mp;
8406   u32 sw_if_index;
8407   u8 enable = 1;
8408   u8 sw_if_index_set = 0;
8409   int ret;
8410
8411   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8412     {
8413       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8414         sw_if_index_set = 1;
8415       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8416         sw_if_index_set = 1;
8417       else if (unformat (i, "enable"))
8418         enable = 1;
8419       else if (unformat (i, "disable"))
8420         enable = 0;
8421       else
8422         {
8423           clib_warning ("parse error '%U'", format_unformat_error, i);
8424           return -99;
8425         }
8426     }
8427
8428   if (sw_if_index_set == 0)
8429     {
8430       errmsg ("missing sw_if_index");
8431       return -99;
8432     }
8433
8434   M (L2_INTERFACE_EFP_FILTER, mp);
8435
8436   mp->sw_if_index = ntohl (sw_if_index);
8437   mp->enable_disable = enable;
8438
8439   S (mp);
8440   W (ret);
8441   return ret;
8442 }
8443
8444 #define foreach_vtr_op                          \
8445 _("disable",  L2_VTR_DISABLED)                  \
8446 _("push-1",  L2_VTR_PUSH_1)                     \
8447 _("push-2",  L2_VTR_PUSH_2)                     \
8448 _("pop-1",  L2_VTR_POP_1)                       \
8449 _("pop-2",  L2_VTR_POP_2)                       \
8450 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
8451 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
8452 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
8453 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
8454
8455 static int
8456 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
8457 {
8458   unformat_input_t *i = vam->input;
8459   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
8460   u32 sw_if_index;
8461   u8 sw_if_index_set = 0;
8462   u8 vtr_op_set = 0;
8463   u32 vtr_op = 0;
8464   u32 push_dot1q = 1;
8465   u32 tag1 = ~0;
8466   u32 tag2 = ~0;
8467   int ret;
8468
8469   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8470     {
8471       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8472         sw_if_index_set = 1;
8473       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8474         sw_if_index_set = 1;
8475       else if (unformat (i, "vtr_op %d", &vtr_op))
8476         vtr_op_set = 1;
8477 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
8478       foreach_vtr_op
8479 #undef _
8480         else if (unformat (i, "push_dot1q %d", &push_dot1q))
8481         ;
8482       else if (unformat (i, "tag1 %d", &tag1))
8483         ;
8484       else if (unformat (i, "tag2 %d", &tag2))
8485         ;
8486       else
8487         {
8488           clib_warning ("parse error '%U'", format_unformat_error, i);
8489           return -99;
8490         }
8491     }
8492
8493   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
8494     {
8495       errmsg ("missing vtr operation or sw_if_index");
8496       return -99;
8497     }
8498
8499   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
8500   mp->sw_if_index = ntohl (sw_if_index);
8501   mp->vtr_op = ntohl (vtr_op);
8502   mp->push_dot1q = ntohl (push_dot1q);
8503   mp->tag1 = ntohl (tag1);
8504   mp->tag2 = ntohl (tag2);
8505
8506   S (mp);
8507   W (ret);
8508   return ret;
8509 }
8510
8511 static int
8512 api_create_vhost_user_if (vat_main_t * vam)
8513 {
8514   unformat_input_t *i = vam->input;
8515   vl_api_create_vhost_user_if_t *mp;
8516   u8 *file_name;
8517   u8 is_server = 0;
8518   u8 file_name_set = 0;
8519   u32 custom_dev_instance = ~0;
8520   u8 hwaddr[6];
8521   u8 use_custom_mac = 0;
8522   u8 disable_mrg_rxbuf = 0;
8523   u8 disable_indirect_desc = 0;
8524   u8 *tag = 0;
8525   u8 enable_gso = 0;
8526   u8 enable_packed = 0;
8527   int ret;
8528
8529   /* Shut up coverity */
8530   clib_memset (hwaddr, 0, sizeof (hwaddr));
8531
8532   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8533     {
8534       if (unformat (i, "socket %s", &file_name))
8535         {
8536           file_name_set = 1;
8537         }
8538       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8539         ;
8540       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8541         use_custom_mac = 1;
8542       else if (unformat (i, "server"))
8543         is_server = 1;
8544       else if (unformat (i, "disable_mrg_rxbuf"))
8545         disable_mrg_rxbuf = 1;
8546       else if (unformat (i, "disable_indirect_desc"))
8547         disable_indirect_desc = 1;
8548       else if (unformat (i, "gso"))
8549         enable_gso = 1;
8550       else if (unformat (i, "packed"))
8551         enable_packed = 1;
8552       else if (unformat (i, "tag %s", &tag))
8553         ;
8554       else
8555         break;
8556     }
8557
8558   if (file_name_set == 0)
8559     {
8560       errmsg ("missing socket file name");
8561       return -99;
8562     }
8563
8564   if (vec_len (file_name) > 255)
8565     {
8566       errmsg ("socket file name too long");
8567       return -99;
8568     }
8569   vec_add1 (file_name, 0);
8570
8571   M (CREATE_VHOST_USER_IF, mp);
8572
8573   mp->is_server = is_server;
8574   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8575   mp->disable_indirect_desc = disable_indirect_desc;
8576   mp->enable_gso = enable_gso;
8577   mp->enable_packed = enable_packed;
8578   mp->custom_dev_instance = ntohl (custom_dev_instance);
8579   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8580   vec_free (file_name);
8581   if (custom_dev_instance != ~0)
8582     mp->renumber = 1;
8583
8584   mp->use_custom_mac = use_custom_mac;
8585   clib_memcpy (mp->mac_address, hwaddr, 6);
8586   if (tag)
8587     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8588   vec_free (tag);
8589
8590   S (mp);
8591   W (ret);
8592   return ret;
8593 }
8594
8595 static int
8596 api_modify_vhost_user_if (vat_main_t * vam)
8597 {
8598   unformat_input_t *i = vam->input;
8599   vl_api_modify_vhost_user_if_t *mp;
8600   u8 *file_name;
8601   u8 is_server = 0;
8602   u8 file_name_set = 0;
8603   u32 custom_dev_instance = ~0;
8604   u8 sw_if_index_set = 0;
8605   u32 sw_if_index = (u32) ~ 0;
8606   u8 enable_gso = 0;
8607   u8 enable_packed = 0;
8608   int ret;
8609
8610   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8611     {
8612       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8613         sw_if_index_set = 1;
8614       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8615         sw_if_index_set = 1;
8616       else if (unformat (i, "socket %s", &file_name))
8617         {
8618           file_name_set = 1;
8619         }
8620       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8621         ;
8622       else if (unformat (i, "server"))
8623         is_server = 1;
8624       else if (unformat (i, "gso"))
8625         enable_gso = 1;
8626       else if (unformat (i, "packed"))
8627         enable_packed = 1;
8628       else
8629         break;
8630     }
8631
8632   if (sw_if_index_set == 0)
8633     {
8634       errmsg ("missing sw_if_index or interface name");
8635       return -99;
8636     }
8637
8638   if (file_name_set == 0)
8639     {
8640       errmsg ("missing socket file name");
8641       return -99;
8642     }
8643
8644   if (vec_len (file_name) > 255)
8645     {
8646       errmsg ("socket file name too long");
8647       return -99;
8648     }
8649   vec_add1 (file_name, 0);
8650
8651   M (MODIFY_VHOST_USER_IF, mp);
8652
8653   mp->sw_if_index = ntohl (sw_if_index);
8654   mp->is_server = is_server;
8655   mp->enable_gso = enable_gso;
8656   mp->enable_packed = enable_packed;
8657   mp->custom_dev_instance = ntohl (custom_dev_instance);
8658   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8659   vec_free (file_name);
8660   if (custom_dev_instance != ~0)
8661     mp->renumber = 1;
8662
8663   S (mp);
8664   W (ret);
8665   return ret;
8666 }
8667
8668 static int
8669 api_create_vhost_user_if_v2 (vat_main_t * vam)
8670 {
8671   unformat_input_t *i = vam->input;
8672   vl_api_create_vhost_user_if_v2_t *mp;
8673   u8 *file_name;
8674   u8 is_server = 0;
8675   u8 file_name_set = 0;
8676   u32 custom_dev_instance = ~0;
8677   u8 hwaddr[6];
8678   u8 use_custom_mac = 0;
8679   u8 disable_mrg_rxbuf = 0;
8680   u8 disable_indirect_desc = 0;
8681   u8 *tag = 0;
8682   u8 enable_gso = 0;
8683   u8 enable_packed = 0;
8684   u8 enable_event_idx = 0;
8685   int ret;
8686
8687   /* Shut up coverity */
8688   clib_memset (hwaddr, 0, sizeof (hwaddr));
8689
8690   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8691     {
8692       if (unformat (i, "socket %s", &file_name))
8693         {
8694           file_name_set = 1;
8695         }
8696       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8697         ;
8698       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8699         use_custom_mac = 1;
8700       else if (unformat (i, "server"))
8701         is_server = 1;
8702       else if (unformat (i, "disable_mrg_rxbuf"))
8703         disable_mrg_rxbuf = 1;
8704       else if (unformat (i, "disable_indirect_desc"))
8705         disable_indirect_desc = 1;
8706       else if (unformat (i, "gso"))
8707         enable_gso = 1;
8708       else if (unformat (i, "packed"))
8709         enable_packed = 1;
8710       else if (unformat (i, "event-idx"))
8711         enable_event_idx = 1;
8712       else if (unformat (i, "tag %s", &tag))
8713         ;
8714       else
8715         break;
8716     }
8717
8718   if (file_name_set == 0)
8719     {
8720       errmsg ("missing socket file name");
8721       return -99;
8722     }
8723
8724   if (vec_len (file_name) > 255)
8725     {
8726       errmsg ("socket file name too long");
8727       return -99;
8728     }
8729   vec_add1 (file_name, 0);
8730
8731   M (CREATE_VHOST_USER_IF_V2, mp);
8732
8733   mp->is_server = is_server;
8734   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8735   mp->disable_indirect_desc = disable_indirect_desc;
8736   mp->enable_gso = enable_gso;
8737   mp->enable_packed = enable_packed;
8738   mp->enable_event_idx = enable_event_idx;
8739   mp->custom_dev_instance = ntohl (custom_dev_instance);
8740   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8741   vec_free (file_name);
8742   if (custom_dev_instance != ~0)
8743     mp->renumber = 1;
8744
8745   mp->use_custom_mac = use_custom_mac;
8746   clib_memcpy (mp->mac_address, hwaddr, 6);
8747   if (tag)
8748     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8749   vec_free (tag);
8750
8751   S (mp);
8752   W (ret);
8753   return ret;
8754 }
8755
8756 static int
8757 api_modify_vhost_user_if_v2 (vat_main_t * vam)
8758 {
8759   unformat_input_t *i = vam->input;
8760   vl_api_modify_vhost_user_if_v2_t *mp;
8761   u8 *file_name;
8762   u8 is_server = 0;
8763   u8 file_name_set = 0;
8764   u32 custom_dev_instance = ~0;
8765   u8 sw_if_index_set = 0;
8766   u32 sw_if_index = (u32) ~ 0;
8767   u8 enable_gso = 0;
8768   u8 enable_packed = 0;
8769   u8 enable_event_idx = 0;
8770   int ret;
8771
8772   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8773     {
8774       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8775         sw_if_index_set = 1;
8776       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8777         sw_if_index_set = 1;
8778       else if (unformat (i, "socket %s", &file_name))
8779         {
8780           file_name_set = 1;
8781         }
8782       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8783         ;
8784       else if (unformat (i, "server"))
8785         is_server = 1;
8786       else if (unformat (i, "gso"))
8787         enable_gso = 1;
8788       else if (unformat (i, "packed"))
8789         enable_packed = 1;
8790       else if (unformat (i, "event-idx"))
8791         enable_event_idx = 1;
8792       else
8793         break;
8794     }
8795
8796   if (sw_if_index_set == 0)
8797     {
8798       errmsg ("missing sw_if_index or interface name");
8799       return -99;
8800     }
8801
8802   if (file_name_set == 0)
8803     {
8804       errmsg ("missing socket file name");
8805       return -99;
8806     }
8807
8808   if (vec_len (file_name) > 255)
8809     {
8810       errmsg ("socket file name too long");
8811       return -99;
8812     }
8813   vec_add1 (file_name, 0);
8814
8815   M (MODIFY_VHOST_USER_IF_V2, mp);
8816
8817   mp->sw_if_index = ntohl (sw_if_index);
8818   mp->is_server = is_server;
8819   mp->enable_gso = enable_gso;
8820   mp->enable_packed = enable_packed;
8821   mp->enable_event_idx = enable_event_idx;
8822   mp->custom_dev_instance = ntohl (custom_dev_instance);
8823   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8824   vec_free (file_name);
8825   if (custom_dev_instance != ~0)
8826     mp->renumber = 1;
8827
8828   S (mp);
8829   W (ret);
8830   return ret;
8831 }
8832
8833 static int
8834 api_delete_vhost_user_if (vat_main_t * vam)
8835 {
8836   unformat_input_t *i = vam->input;
8837   vl_api_delete_vhost_user_if_t *mp;
8838   u32 sw_if_index = ~0;
8839   u8 sw_if_index_set = 0;
8840   int ret;
8841
8842   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8843     {
8844       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8845         sw_if_index_set = 1;
8846       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8847         sw_if_index_set = 1;
8848       else
8849         break;
8850     }
8851
8852   if (sw_if_index_set == 0)
8853     {
8854       errmsg ("missing sw_if_index or interface name");
8855       return -99;
8856     }
8857
8858
8859   M (DELETE_VHOST_USER_IF, mp);
8860
8861   mp->sw_if_index = ntohl (sw_if_index);
8862
8863   S (mp);
8864   W (ret);
8865   return ret;
8866 }
8867
8868 static void vl_api_sw_interface_vhost_user_details_t_handler
8869   (vl_api_sw_interface_vhost_user_details_t * mp)
8870 {
8871   vat_main_t *vam = &vat_main;
8872   u64 features;
8873
8874   features =
8875     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
8876                                                     clib_net_to_host_u32
8877                                                     (mp->features_last_32) <<
8878                                                     32);
8879
8880   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %16llx %6d %7d %s",
8881          (char *) mp->interface_name, ntohl (mp->sw_if_index),
8882          ntohl (mp->virtio_net_hdr_sz), features, mp->is_server,
8883          ntohl (mp->num_regions), (char *) mp->sock_filename);
8884   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
8885 }
8886
8887 static void vl_api_sw_interface_vhost_user_details_t_handler_json
8888   (vl_api_sw_interface_vhost_user_details_t * mp)
8889 {
8890   vat_main_t *vam = &vat_main;
8891   vat_json_node_t *node = NULL;
8892
8893   if (VAT_JSON_ARRAY != vam->json_tree.type)
8894     {
8895       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8896       vat_json_init_array (&vam->json_tree);
8897     }
8898   node = vat_json_array_add (&vam->json_tree);
8899
8900   vat_json_init_object (node);
8901   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8902   vat_json_object_add_string_copy (node, "interface_name",
8903                                    mp->interface_name);
8904   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
8905                             ntohl (mp->virtio_net_hdr_sz));
8906   vat_json_object_add_uint (node, "features_first_32",
8907                             clib_net_to_host_u32 (mp->features_first_32));
8908   vat_json_object_add_uint (node, "features_last_32",
8909                             clib_net_to_host_u32 (mp->features_last_32));
8910   vat_json_object_add_uint (node, "is_server", mp->is_server);
8911   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
8912   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
8913   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
8914 }
8915
8916 static int
8917 api_sw_interface_vhost_user_dump (vat_main_t * vam)
8918 {
8919   unformat_input_t *i = vam->input;
8920   vl_api_sw_interface_vhost_user_dump_t *mp;
8921   vl_api_control_ping_t *mp_ping;
8922   int ret;
8923   u32 sw_if_index = ~0;
8924
8925   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8926     {
8927       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8928         ;
8929       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8930         ;
8931       else
8932         break;
8933     }
8934
8935   print (vam->ofp, "Interface name            idx hdr_sz         features "
8936                    "server regions filename");
8937
8938   /* Get list of vhost-user interfaces */
8939   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
8940   mp->sw_if_index = ntohl (sw_if_index);
8941   S (mp);
8942
8943   /* Use a control ping for synchronization */
8944   MPING (CONTROL_PING, mp_ping);
8945   S (mp_ping);
8946
8947   W (ret);
8948   return ret;
8949 }
8950
8951 static int
8952 api_show_version (vat_main_t * vam)
8953 {
8954   vl_api_show_version_t *mp;
8955   int ret;
8956
8957   M (SHOW_VERSION, mp);
8958
8959   S (mp);
8960   W (ret);
8961   return ret;
8962 }
8963
8964 static void vl_api_l2_fib_table_details_t_handler
8965   (vl_api_l2_fib_table_details_t * mp)
8966 {
8967   vat_main_t *vam = &vat_main;
8968
8969   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
8970          "       %d       %d     %d",
8971          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
8972          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
8973          mp->bvi_mac);
8974 }
8975
8976 static void vl_api_l2_fib_table_details_t_handler_json
8977   (vl_api_l2_fib_table_details_t * mp)
8978 {
8979   vat_main_t *vam = &vat_main;
8980   vat_json_node_t *node = NULL;
8981
8982   if (VAT_JSON_ARRAY != vam->json_tree.type)
8983     {
8984       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8985       vat_json_init_array (&vam->json_tree);
8986     }
8987   node = vat_json_array_add (&vam->json_tree);
8988
8989   vat_json_init_object (node);
8990   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
8991   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
8992   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8993   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
8994   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
8995   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
8996 }
8997
8998 static int
8999 api_l2_fib_table_dump (vat_main_t * vam)
9000 {
9001   unformat_input_t *i = vam->input;
9002   vl_api_l2_fib_table_dump_t *mp;
9003   vl_api_control_ping_t *mp_ping;
9004   u32 bd_id;
9005   u8 bd_id_set = 0;
9006   int ret;
9007
9008   /* Parse args required to build the message */
9009   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9010     {
9011       if (unformat (i, "bd_id %d", &bd_id))
9012         bd_id_set = 1;
9013       else
9014         break;
9015     }
9016
9017   if (bd_id_set == 0)
9018     {
9019       errmsg ("missing bridge domain");
9020       return -99;
9021     }
9022
9023   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
9024
9025   /* Get list of l2 fib entries */
9026   M (L2_FIB_TABLE_DUMP, mp);
9027
9028   mp->bd_id = ntohl (bd_id);
9029   S (mp);
9030
9031   /* Use a control ping for synchronization */
9032   MPING (CONTROL_PING, mp_ping);
9033   S (mp_ping);
9034
9035   W (ret);
9036   return ret;
9037 }
9038
9039
9040 static int
9041 api_interface_name_renumber (vat_main_t * vam)
9042 {
9043   unformat_input_t *line_input = vam->input;
9044   vl_api_interface_name_renumber_t *mp;
9045   u32 sw_if_index = ~0;
9046   u32 new_show_dev_instance = ~0;
9047   int ret;
9048
9049   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9050     {
9051       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
9052                     &sw_if_index))
9053         ;
9054       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
9055         ;
9056       else if (unformat (line_input, "new_show_dev_instance %d",
9057                          &new_show_dev_instance))
9058         ;
9059       else
9060         break;
9061     }
9062
9063   if (sw_if_index == ~0)
9064     {
9065       errmsg ("missing interface name or sw_if_index");
9066       return -99;
9067     }
9068
9069   if (new_show_dev_instance == ~0)
9070     {
9071       errmsg ("missing new_show_dev_instance");
9072       return -99;
9073     }
9074
9075   M (INTERFACE_NAME_RENUMBER, mp);
9076
9077   mp->sw_if_index = ntohl (sw_if_index);
9078   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
9079
9080   S (mp);
9081   W (ret);
9082   return ret;
9083 }
9084
9085 static int
9086 api_want_l2_macs_events (vat_main_t * vam)
9087 {
9088   unformat_input_t *line_input = vam->input;
9089   vl_api_want_l2_macs_events_t *mp;
9090   u8 enable_disable = 1;
9091   u32 scan_delay = 0;
9092   u32 max_macs_in_event = 0;
9093   u32 learn_limit = 0;
9094   int ret;
9095
9096   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
9097     {
9098       if (unformat (line_input, "learn-limit %d", &learn_limit))
9099         ;
9100       else if (unformat (line_input, "scan-delay %d", &scan_delay))
9101         ;
9102       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
9103         ;
9104       else if (unformat (line_input, "disable"))
9105         enable_disable = 0;
9106       else
9107         break;
9108     }
9109
9110   M (WANT_L2_MACS_EVENTS, mp);
9111   mp->enable_disable = enable_disable;
9112   mp->pid = htonl (getpid ());
9113   mp->learn_limit = htonl (learn_limit);
9114   mp->scan_delay = (u8) scan_delay;
9115   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
9116   S (mp);
9117   W (ret);
9118   return ret;
9119 }
9120
9121 static int
9122 api_ip_address_dump (vat_main_t * vam)
9123 {
9124   unformat_input_t *i = vam->input;
9125   vl_api_ip_address_dump_t *mp;
9126   vl_api_control_ping_t *mp_ping;
9127   u32 sw_if_index = ~0;
9128   u8 sw_if_index_set = 0;
9129   u8 ipv4_set = 0;
9130   u8 ipv6_set = 0;
9131   int ret;
9132
9133   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9134     {
9135       if (unformat (i, "sw_if_index %d", &sw_if_index))
9136         sw_if_index_set = 1;
9137       else
9138         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9139         sw_if_index_set = 1;
9140       else if (unformat (i, "ipv4"))
9141         ipv4_set = 1;
9142       else if (unformat (i, "ipv6"))
9143         ipv6_set = 1;
9144       else
9145         break;
9146     }
9147
9148   if (ipv4_set && ipv6_set)
9149     {
9150       errmsg ("ipv4 and ipv6 flags cannot be both set");
9151       return -99;
9152     }
9153
9154   if ((!ipv4_set) && (!ipv6_set))
9155     {
9156       errmsg ("no ipv4 nor ipv6 flag set");
9157       return -99;
9158     }
9159
9160   if (sw_if_index_set == 0)
9161     {
9162       errmsg ("missing interface name or sw_if_index");
9163       return -99;
9164     }
9165
9166   vam->current_sw_if_index = sw_if_index;
9167   vam->is_ipv6 = ipv6_set;
9168
9169   M (IP_ADDRESS_DUMP, mp);
9170   mp->sw_if_index = ntohl (sw_if_index);
9171   mp->is_ipv6 = ipv6_set;
9172   S (mp);
9173
9174   /* Use a control ping for synchronization */
9175   MPING (CONTROL_PING, mp_ping);
9176   S (mp_ping);
9177
9178   W (ret);
9179   return ret;
9180 }
9181
9182 static int
9183 api_ip_dump (vat_main_t * vam)
9184 {
9185   vl_api_ip_dump_t *mp;
9186   vl_api_control_ping_t *mp_ping;
9187   unformat_input_t *in = vam->input;
9188   int ipv4_set = 0;
9189   int ipv6_set = 0;
9190   int is_ipv6;
9191   int i;
9192   int ret;
9193
9194   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
9195     {
9196       if (unformat (in, "ipv4"))
9197         ipv4_set = 1;
9198       else if (unformat (in, "ipv6"))
9199         ipv6_set = 1;
9200       else
9201         break;
9202     }
9203
9204   if (ipv4_set && ipv6_set)
9205     {
9206       errmsg ("ipv4 and ipv6 flags cannot be both set");
9207       return -99;
9208     }
9209
9210   if ((!ipv4_set) && (!ipv6_set))
9211     {
9212       errmsg ("no ipv4 nor ipv6 flag set");
9213       return -99;
9214     }
9215
9216   is_ipv6 = ipv6_set;
9217   vam->is_ipv6 = is_ipv6;
9218
9219   /* free old data */
9220   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
9221     {
9222       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
9223     }
9224   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
9225
9226   M (IP_DUMP, mp);
9227   mp->is_ipv6 = ipv6_set;
9228   S (mp);
9229
9230   /* Use a control ping for synchronization */
9231   MPING (CONTROL_PING, mp_ping);
9232   S (mp_ping);
9233
9234   W (ret);
9235   return ret;
9236 }
9237
9238 static int
9239 api_ipsec_spd_add_del (vat_main_t * vam)
9240 {
9241   unformat_input_t *i = vam->input;
9242   vl_api_ipsec_spd_add_del_t *mp;
9243   u32 spd_id = ~0;
9244   u8 is_add = 1;
9245   int ret;
9246
9247   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9248     {
9249       if (unformat (i, "spd_id %d", &spd_id))
9250         ;
9251       else if (unformat (i, "del"))
9252         is_add = 0;
9253       else
9254         {
9255           clib_warning ("parse error '%U'", format_unformat_error, i);
9256           return -99;
9257         }
9258     }
9259   if (spd_id == ~0)
9260     {
9261       errmsg ("spd_id must be set");
9262       return -99;
9263     }
9264
9265   M (IPSEC_SPD_ADD_DEL, mp);
9266
9267   mp->spd_id = ntohl (spd_id);
9268   mp->is_add = is_add;
9269
9270   S (mp);
9271   W (ret);
9272   return ret;
9273 }
9274
9275 static int
9276 api_ipsec_interface_add_del_spd (vat_main_t * vam)
9277 {
9278   unformat_input_t *i = vam->input;
9279   vl_api_ipsec_interface_add_del_spd_t *mp;
9280   u32 sw_if_index;
9281   u8 sw_if_index_set = 0;
9282   u32 spd_id = (u32) ~ 0;
9283   u8 is_add = 1;
9284   int ret;
9285
9286   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9287     {
9288       if (unformat (i, "del"))
9289         is_add = 0;
9290       else if (unformat (i, "spd_id %d", &spd_id))
9291         ;
9292       else
9293         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9294         sw_if_index_set = 1;
9295       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9296         sw_if_index_set = 1;
9297       else
9298         {
9299           clib_warning ("parse error '%U'", format_unformat_error, i);
9300           return -99;
9301         }
9302
9303     }
9304
9305   if (spd_id == (u32) ~ 0)
9306     {
9307       errmsg ("spd_id must be set");
9308       return -99;
9309     }
9310
9311   if (sw_if_index_set == 0)
9312     {
9313       errmsg ("missing interface name or sw_if_index");
9314       return -99;
9315     }
9316
9317   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
9318
9319   mp->spd_id = ntohl (spd_id);
9320   mp->sw_if_index = ntohl (sw_if_index);
9321   mp->is_add = is_add;
9322
9323   S (mp);
9324   W (ret);
9325   return ret;
9326 }
9327
9328 static int
9329 api_ipsec_spd_entry_add_del (vat_main_t * vam)
9330 {
9331   unformat_input_t *i = vam->input;
9332   vl_api_ipsec_spd_entry_add_del_t *mp;
9333   u8 is_add = 1, is_outbound = 0;
9334   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
9335   i32 priority = 0;
9336   u32 rport_start = 0, rport_stop = (u32) ~ 0;
9337   u32 lport_start = 0, lport_stop = (u32) ~ 0;
9338   vl_api_address_t laddr_start = { }, laddr_stop =
9339   {
9340   }, raddr_start =
9341   {
9342   }, raddr_stop =
9343   {
9344   };
9345   int ret;
9346
9347   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9348     {
9349       if (unformat (i, "del"))
9350         is_add = 0;
9351       if (unformat (i, "outbound"))
9352         is_outbound = 1;
9353       if (unformat (i, "inbound"))
9354         is_outbound = 0;
9355       else if (unformat (i, "spd_id %d", &spd_id))
9356         ;
9357       else if (unformat (i, "sa_id %d", &sa_id))
9358         ;
9359       else if (unformat (i, "priority %d", &priority))
9360         ;
9361       else if (unformat (i, "protocol %d", &protocol))
9362         ;
9363       else if (unformat (i, "lport_start %d", &lport_start))
9364         ;
9365       else if (unformat (i, "lport_stop %d", &lport_stop))
9366         ;
9367       else if (unformat (i, "rport_start %d", &rport_start))
9368         ;
9369       else if (unformat (i, "rport_stop %d", &rport_stop))
9370         ;
9371       else if (unformat (i, "laddr_start %U",
9372                          unformat_vl_api_address, &laddr_start))
9373         ;
9374       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
9375                          &laddr_stop))
9376         ;
9377       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
9378                          &raddr_start))
9379         ;
9380       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
9381                          &raddr_stop))
9382         ;
9383       else
9384         if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
9385         {
9386           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
9387             {
9388               clib_warning ("unsupported action: 'resolve'");
9389               return -99;
9390             }
9391         }
9392       else
9393         {
9394           clib_warning ("parse error '%U'", format_unformat_error, i);
9395           return -99;
9396         }
9397
9398     }
9399
9400   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
9401
9402   mp->is_add = is_add;
9403
9404   mp->entry.spd_id = ntohl (spd_id);
9405   mp->entry.priority = ntohl (priority);
9406   mp->entry.is_outbound = is_outbound;
9407
9408   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
9409                sizeof (vl_api_address_t));
9410   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
9411                sizeof (vl_api_address_t));
9412   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
9413                sizeof (vl_api_address_t));
9414   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
9415                sizeof (vl_api_address_t));
9416
9417   mp->entry.protocol = (u8) protocol;
9418   mp->entry.local_port_start = ntohs ((u16) lport_start);
9419   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
9420   mp->entry.remote_port_start = ntohs ((u16) rport_start);
9421   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
9422   mp->entry.policy = (u8) policy;
9423   mp->entry.sa_id = ntohl (sa_id);
9424
9425   S (mp);
9426   W (ret);
9427   return ret;
9428 }
9429
9430 static int
9431 api_ipsec_sad_entry_add_del (vat_main_t * vam)
9432 {
9433   unformat_input_t *i = vam->input;
9434   vl_api_ipsec_sad_entry_add_del_t *mp;
9435   u32 sad_id = 0, spi = 0;
9436   u8 *ck = 0, *ik = 0;
9437   u8 is_add = 1;
9438
9439   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
9440   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
9441   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
9442   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
9443   vl_api_address_t tun_src, tun_dst;
9444   int ret;
9445
9446   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9447     {
9448       if (unformat (i, "del"))
9449         is_add = 0;
9450       else if (unformat (i, "sad_id %d", &sad_id))
9451         ;
9452       else if (unformat (i, "spi %d", &spi))
9453         ;
9454       else if (unformat (i, "esp"))
9455         protocol = IPSEC_API_PROTO_ESP;
9456       else
9457         if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
9458         {
9459           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
9460           if (ADDRESS_IP6 == tun_src.af)
9461             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
9462         }
9463       else
9464         if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
9465         {
9466           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
9467           if (ADDRESS_IP6 == tun_src.af)
9468             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
9469         }
9470       else
9471         if (unformat (i, "crypto_alg %U",
9472                       unformat_ipsec_api_crypto_alg, &crypto_alg))
9473         ;
9474       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
9475         ;
9476       else if (unformat (i, "integ_alg %U",
9477                          unformat_ipsec_api_integ_alg, &integ_alg))
9478         ;
9479       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
9480         ;
9481       else
9482         {
9483           clib_warning ("parse error '%U'", format_unformat_error, i);
9484           return -99;
9485         }
9486
9487     }
9488
9489   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
9490
9491   mp->is_add = is_add;
9492   mp->entry.sad_id = ntohl (sad_id);
9493   mp->entry.protocol = protocol;
9494   mp->entry.spi = ntohl (spi);
9495   mp->entry.flags = flags;
9496
9497   mp->entry.crypto_algorithm = crypto_alg;
9498   mp->entry.integrity_algorithm = integ_alg;
9499   mp->entry.crypto_key.length = vec_len (ck);
9500   mp->entry.integrity_key.length = vec_len (ik);
9501
9502   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
9503     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
9504
9505   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
9506     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
9507
9508   if (ck)
9509     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
9510   if (ik)
9511     clib_memcpy (mp->entry.integrity_key.data, ik,
9512                  mp->entry.integrity_key.length);
9513
9514   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
9515     {
9516       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
9517                    sizeof (mp->entry.tunnel_src));
9518       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
9519                    sizeof (mp->entry.tunnel_dst));
9520     }
9521
9522   S (mp);
9523   W (ret);
9524   return ret;
9525 }
9526
9527 static void
9528 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
9529 {
9530   vat_main_t *vam = &vat_main;
9531
9532   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
9533          "crypto_key %U integ_alg %u integ_key %U flags %x "
9534          "tunnel_src_addr %U tunnel_dst_addr %U "
9535          "salt %u seq_outbound %lu last_seq_inbound %lu "
9536          "replay_window %lu stat_index %u\n",
9537          ntohl (mp->entry.sad_id),
9538          ntohl (mp->sw_if_index),
9539          ntohl (mp->entry.spi),
9540          ntohl (mp->entry.protocol),
9541          ntohl (mp->entry.crypto_algorithm),
9542          format_hex_bytes, mp->entry.crypto_key.data,
9543          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
9544          format_hex_bytes, mp->entry.integrity_key.data,
9545          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
9546          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
9547          &mp->entry.tunnel_dst, ntohl (mp->salt),
9548          clib_net_to_host_u64 (mp->seq_outbound),
9549          clib_net_to_host_u64 (mp->last_seq_inbound),
9550          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
9551 }
9552
9553 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
9554 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
9555
9556 static void vl_api_ipsec_sa_details_t_handler_json
9557   (vl_api_ipsec_sa_details_t * mp)
9558 {
9559   vat_main_t *vam = &vat_main;
9560   vat_json_node_t *node = NULL;
9561   vl_api_ipsec_sad_flags_t flags;
9562
9563   if (VAT_JSON_ARRAY != vam->json_tree.type)
9564     {
9565       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9566       vat_json_init_array (&vam->json_tree);
9567     }
9568   node = vat_json_array_add (&vam->json_tree);
9569
9570   vat_json_init_object (node);
9571   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
9572   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9573   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
9574   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
9575   vat_json_object_add_uint (node, "crypto_alg",
9576                             ntohl (mp->entry.crypto_algorithm));
9577   vat_json_object_add_uint (node, "integ_alg",
9578                             ntohl (mp->entry.integrity_algorithm));
9579   flags = ntohl (mp->entry.flags);
9580   vat_json_object_add_uint (node, "use_esn",
9581                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
9582   vat_json_object_add_uint (node, "use_anti_replay",
9583                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
9584   vat_json_object_add_uint (node, "is_tunnel",
9585                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
9586   vat_json_object_add_uint (node, "is_tunnel_ip6",
9587                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
9588   vat_json_object_add_uint (node, "udp_encap",
9589                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
9590   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
9591                              mp->entry.crypto_key.length);
9592   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
9593                              mp->entry.integrity_key.length);
9594   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
9595   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
9596   vat_json_object_add_uint (node, "replay_window",
9597                             clib_net_to_host_u64 (mp->replay_window));
9598   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
9599 }
9600
9601 static int
9602 api_ipsec_sa_dump (vat_main_t * vam)
9603 {
9604   unformat_input_t *i = vam->input;
9605   vl_api_ipsec_sa_dump_t *mp;
9606   vl_api_control_ping_t *mp_ping;
9607   u32 sa_id = ~0;
9608   int ret;
9609
9610   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9611     {
9612       if (unformat (i, "sa_id %d", &sa_id))
9613         ;
9614       else
9615         {
9616           clib_warning ("parse error '%U'", format_unformat_error, i);
9617           return -99;
9618         }
9619     }
9620
9621   M (IPSEC_SA_DUMP, mp);
9622
9623   mp->sa_id = ntohl (sa_id);
9624
9625   S (mp);
9626
9627   /* Use a control ping for synchronization */
9628   M (CONTROL_PING, mp_ping);
9629   S (mp_ping);
9630
9631   W (ret);
9632   return ret;
9633 }
9634
9635 static int
9636 api_get_first_msg_id (vat_main_t * vam)
9637 {
9638   vl_api_get_first_msg_id_t *mp;
9639   unformat_input_t *i = vam->input;
9640   u8 *name;
9641   u8 name_set = 0;
9642   int ret;
9643
9644   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9645     {
9646       if (unformat (i, "client %s", &name))
9647         name_set = 1;
9648       else
9649         break;
9650     }
9651
9652   if (name_set == 0)
9653     {
9654       errmsg ("missing client name");
9655       return -99;
9656     }
9657   vec_add1 (name, 0);
9658
9659   if (vec_len (name) > 63)
9660     {
9661       errmsg ("client name too long");
9662       return -99;
9663     }
9664
9665   M (GET_FIRST_MSG_ID, mp);
9666   clib_memcpy (mp->name, name, vec_len (name));
9667   S (mp);
9668   W (ret);
9669   return ret;
9670 }
9671
9672 static int
9673 api_get_node_graph (vat_main_t * vam)
9674 {
9675   vl_api_get_node_graph_t *mp;
9676   int ret;
9677
9678   M (GET_NODE_GRAPH, mp);
9679
9680   /* send it... */
9681   S (mp);
9682   /* Wait for the reply */
9683   W (ret);
9684   return ret;
9685 }
9686
9687 static int
9688 api_af_packet_create (vat_main_t * vam)
9689 {
9690   unformat_input_t *i = vam->input;
9691   vl_api_af_packet_create_t *mp;
9692   u8 *host_if_name = 0;
9693   u8 hw_addr[6];
9694   u8 random_hw_addr = 1;
9695   int ret;
9696
9697   clib_memset (hw_addr, 0, sizeof (hw_addr));
9698
9699   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9700     {
9701       if (unformat (i, "name %s", &host_if_name))
9702         vec_add1 (host_if_name, 0);
9703       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
9704         random_hw_addr = 0;
9705       else
9706         break;
9707     }
9708
9709   if (!vec_len (host_if_name))
9710     {
9711       errmsg ("host-interface name must be specified");
9712       return -99;
9713     }
9714
9715   if (vec_len (host_if_name) > 64)
9716     {
9717       errmsg ("host-interface name too long");
9718       return -99;
9719     }
9720
9721   M (AF_PACKET_CREATE, mp);
9722
9723   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9724   clib_memcpy (mp->hw_addr, hw_addr, 6);
9725   mp->use_random_hw_addr = random_hw_addr;
9726   vec_free (host_if_name);
9727
9728   S (mp);
9729
9730   /* *INDENT-OFF* */
9731   W2 (ret,
9732       ({
9733         if (ret == 0)
9734           fprintf (vam->ofp ? vam->ofp : stderr,
9735                    " new sw_if_index = %d\n", vam->sw_if_index);
9736       }));
9737   /* *INDENT-ON* */
9738   return ret;
9739 }
9740
9741 static int
9742 api_af_packet_delete (vat_main_t * vam)
9743 {
9744   unformat_input_t *i = vam->input;
9745   vl_api_af_packet_delete_t *mp;
9746   u8 *host_if_name = 0;
9747   int ret;
9748
9749   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9750     {
9751       if (unformat (i, "name %s", &host_if_name))
9752         vec_add1 (host_if_name, 0);
9753       else
9754         break;
9755     }
9756
9757   if (!vec_len (host_if_name))
9758     {
9759       errmsg ("host-interface name must be specified");
9760       return -99;
9761     }
9762
9763   if (vec_len (host_if_name) > 64)
9764     {
9765       errmsg ("host-interface name too long");
9766       return -99;
9767     }
9768
9769   M (AF_PACKET_DELETE, mp);
9770
9771   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9772   vec_free (host_if_name);
9773
9774   S (mp);
9775   W (ret);
9776   return ret;
9777 }
9778
9779 static void vl_api_af_packet_details_t_handler
9780   (vl_api_af_packet_details_t * mp)
9781 {
9782   vat_main_t *vam = &vat_main;
9783
9784   print (vam->ofp, "%-16s %d",
9785          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
9786 }
9787
9788 static void vl_api_af_packet_details_t_handler_json
9789   (vl_api_af_packet_details_t * mp)
9790 {
9791   vat_main_t *vam = &vat_main;
9792   vat_json_node_t *node = NULL;
9793
9794   if (VAT_JSON_ARRAY != vam->json_tree.type)
9795     {
9796       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9797       vat_json_init_array (&vam->json_tree);
9798     }
9799   node = vat_json_array_add (&vam->json_tree);
9800
9801   vat_json_init_object (node);
9802   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9803   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
9804 }
9805
9806 static int
9807 api_af_packet_dump (vat_main_t * vam)
9808 {
9809   vl_api_af_packet_dump_t *mp;
9810   vl_api_control_ping_t *mp_ping;
9811   int ret;
9812
9813   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
9814   /* Get list of tap interfaces */
9815   M (AF_PACKET_DUMP, mp);
9816   S (mp);
9817
9818   /* Use a control ping for synchronization */
9819   MPING (CONTROL_PING, mp_ping);
9820   S (mp_ping);
9821
9822   W (ret);
9823   return ret;
9824 }
9825
9826 static int
9827 api_policer_add_del (vat_main_t * vam)
9828 {
9829   unformat_input_t *i = vam->input;
9830   vl_api_policer_add_del_t *mp;
9831   u8 is_add = 1;
9832   u8 *name = 0;
9833   u32 cir = 0;
9834   u32 eir = 0;
9835   u64 cb = 0;
9836   u64 eb = 0;
9837   u8 rate_type = 0;
9838   u8 round_type = 0;
9839   u8 type = 0;
9840   u8 color_aware = 0;
9841   qos_pol_action_params_st conform_action, exceed_action, violate_action;
9842   int ret;
9843
9844   conform_action.action_type = QOS_ACTION_TRANSMIT;
9845   conform_action.dscp = 0;
9846   exceed_action.action_type = QOS_ACTION_MARK_AND_TRANSMIT;
9847   exceed_action.dscp = 0;
9848   violate_action.action_type = QOS_ACTION_DROP;
9849   violate_action.dscp = 0;
9850
9851   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9852     {
9853       if (unformat (i, "del"))
9854         is_add = 0;
9855       else if (unformat (i, "name %s", &name))
9856         vec_add1 (name, 0);
9857       else if (unformat (i, "cir %u", &cir))
9858         ;
9859       else if (unformat (i, "eir %u", &eir))
9860         ;
9861       else if (unformat (i, "cb %u", &cb))
9862         ;
9863       else if (unformat (i, "eb %u", &eb))
9864         ;
9865       else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
9866                          &rate_type))
9867         ;
9868       else if (unformat (i, "round_type %U", unformat_policer_round_type,
9869                          &round_type))
9870         ;
9871       else if (unformat (i, "type %U", unformat_policer_type, &type))
9872         ;
9873       else if (unformat (i, "conform_action %U", unformat_policer_action_type,
9874                          &conform_action))
9875         ;
9876       else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
9877                          &exceed_action))
9878         ;
9879       else if (unformat (i, "violate_action %U", unformat_policer_action_type,
9880                          &violate_action))
9881         ;
9882       else if (unformat (i, "color-aware"))
9883         color_aware = 1;
9884       else
9885         break;
9886     }
9887
9888   if (!vec_len (name))
9889     {
9890       errmsg ("policer name must be specified");
9891       return -99;
9892     }
9893
9894   if (vec_len (name) > 64)
9895     {
9896       errmsg ("policer name too long");
9897       return -99;
9898     }
9899
9900   M (POLICER_ADD_DEL, mp);
9901
9902   clib_memcpy (mp->name, name, vec_len (name));
9903   vec_free (name);
9904   mp->is_add = is_add;
9905   mp->cir = ntohl (cir);
9906   mp->eir = ntohl (eir);
9907   mp->cb = clib_net_to_host_u64 (cb);
9908   mp->eb = clib_net_to_host_u64 (eb);
9909   mp->rate_type = rate_type;
9910   mp->round_type = round_type;
9911   mp->type = type;
9912   mp->conform_action.type =
9913     (vl_api_sse2_qos_action_type_t) conform_action.action_type;
9914   mp->conform_action.dscp = conform_action.dscp;
9915   mp->exceed_action.type =
9916     (vl_api_sse2_qos_action_type_t) exceed_action.action_type;
9917   mp->exceed_action.dscp = exceed_action.dscp;
9918   mp->violate_action.type =
9919     (vl_api_sse2_qos_action_type_t) violate_action.action_type;
9920   mp->violate_action.dscp = violate_action.dscp;
9921   mp->color_aware = color_aware;
9922
9923   S (mp);
9924   W (ret);
9925   return ret;
9926 }
9927
9928 static int
9929 api_policer_dump (vat_main_t * vam)
9930 {
9931   unformat_input_t *i = vam->input;
9932   vl_api_policer_dump_t *mp;
9933   vl_api_control_ping_t *mp_ping;
9934   u8 *match_name = 0;
9935   u8 match_name_valid = 0;
9936   int ret;
9937
9938   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9939     {
9940       if (unformat (i, "name %s", &match_name))
9941         {
9942           vec_add1 (match_name, 0);
9943           match_name_valid = 1;
9944         }
9945       else
9946         break;
9947     }
9948
9949   M (POLICER_DUMP, mp);
9950   mp->match_name_valid = match_name_valid;
9951   clib_memcpy (mp->match_name, match_name, vec_len (match_name));
9952   vec_free (match_name);
9953   /* send it... */
9954   S (mp);
9955
9956   /* Use a control ping for synchronization */
9957   MPING (CONTROL_PING, mp_ping);
9958   S (mp_ping);
9959
9960   /* Wait for a reply... */
9961   W (ret);
9962   return ret;
9963 }
9964
9965 static u8 *
9966 format_fib_api_path_nh_proto (u8 * s, va_list * args)
9967 {
9968   vl_api_fib_path_nh_proto_t proto =
9969     va_arg (*args, vl_api_fib_path_nh_proto_t);
9970
9971   switch (proto)
9972     {
9973     case FIB_API_PATH_NH_PROTO_IP4:
9974       s = format (s, "ip4");
9975       break;
9976     case FIB_API_PATH_NH_PROTO_IP6:
9977       s = format (s, "ip6");
9978       break;
9979     case FIB_API_PATH_NH_PROTO_MPLS:
9980       s = format (s, "mpls");
9981       break;
9982     case FIB_API_PATH_NH_PROTO_BIER:
9983       s = format (s, "bier");
9984       break;
9985     case FIB_API_PATH_NH_PROTO_ETHERNET:
9986       s = format (s, "ethernet");
9987       break;
9988     }
9989
9990   return (s);
9991 }
9992
9993 static u8 *
9994 format_vl_api_ip_address_union (u8 * s, va_list * args)
9995 {
9996   vl_api_address_family_t af = va_arg (*args, int);
9997   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
9998
9999   switch (af)
10000     {
10001     case ADDRESS_IP4:
10002       s = format (s, "%U", format_ip4_address, u->ip4);
10003       break;
10004     case ADDRESS_IP6:
10005       s = format (s, "%U", format_ip6_address, u->ip6);
10006       break;
10007     }
10008   return (s);
10009 }
10010
10011 static u8 *
10012 format_vl_api_fib_path_type (u8 * s, va_list * args)
10013 {
10014   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
10015
10016   switch (t)
10017     {
10018     case FIB_API_PATH_TYPE_NORMAL:
10019       s = format (s, "normal");
10020       break;
10021     case FIB_API_PATH_TYPE_LOCAL:
10022       s = format (s, "local");
10023       break;
10024     case FIB_API_PATH_TYPE_DROP:
10025       s = format (s, "drop");
10026       break;
10027     case FIB_API_PATH_TYPE_UDP_ENCAP:
10028       s = format (s, "udp-encap");
10029       break;
10030     case FIB_API_PATH_TYPE_BIER_IMP:
10031       s = format (s, "bier-imp");
10032       break;
10033     case FIB_API_PATH_TYPE_ICMP_UNREACH:
10034       s = format (s, "unreach");
10035       break;
10036     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
10037       s = format (s, "prohibit");
10038       break;
10039     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
10040       s = format (s, "src-lookup");
10041       break;
10042     case FIB_API_PATH_TYPE_DVR:
10043       s = format (s, "dvr");
10044       break;
10045     case FIB_API_PATH_TYPE_INTERFACE_RX:
10046       s = format (s, "interface-rx");
10047       break;
10048     case FIB_API_PATH_TYPE_CLASSIFY:
10049       s = format (s, "classify");
10050       break;
10051     }
10052
10053   return (s);
10054 }
10055
10056 static void
10057 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
10058 {
10059   print (vam->ofp,
10060          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
10061          ntohl (fp->weight), ntohl (fp->sw_if_index),
10062          format_vl_api_fib_path_type, fp->type,
10063          format_fib_api_path_nh_proto, fp->proto,
10064          format_vl_api_ip_address_union, &fp->nh.address);
10065 }
10066
10067 static void
10068 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
10069                                  vl_api_fib_path_t * fp)
10070 {
10071   struct in_addr ip4;
10072   struct in6_addr ip6;
10073
10074   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
10075   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
10076   vat_json_object_add_uint (node, "type", fp->type);
10077   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
10078   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
10079     {
10080       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
10081       vat_json_object_add_ip4 (node, "next_hop", ip4);
10082     }
10083   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
10084     {
10085       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
10086       vat_json_object_add_ip6 (node, "next_hop", ip6);
10087     }
10088 }
10089
10090 static void
10091 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
10092 {
10093   vat_main_t *vam = &vat_main;
10094   int count = ntohl (mp->mt_tunnel.mt_n_paths);
10095   vl_api_fib_path_t *fp;
10096   i32 i;
10097
10098   print (vam->ofp, "sw_if_index %d via:",
10099          ntohl (mp->mt_tunnel.mt_sw_if_index));
10100   fp = mp->mt_tunnel.mt_paths;
10101   for (i = 0; i < count; i++)
10102     {
10103       vl_api_fib_path_print (vam, fp);
10104       fp++;
10105     }
10106
10107   print (vam->ofp, "");
10108 }
10109
10110 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
10111 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
10112
10113 static void
10114 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
10115 {
10116   vat_main_t *vam = &vat_main;
10117   vat_json_node_t *node = NULL;
10118   int count = ntohl (mp->mt_tunnel.mt_n_paths);
10119   vl_api_fib_path_t *fp;
10120   i32 i;
10121
10122   if (VAT_JSON_ARRAY != vam->json_tree.type)
10123     {
10124       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10125       vat_json_init_array (&vam->json_tree);
10126     }
10127   node = vat_json_array_add (&vam->json_tree);
10128
10129   vat_json_init_object (node);
10130   vat_json_object_add_uint (node, "sw_if_index",
10131                             ntohl (mp->mt_tunnel.mt_sw_if_index));
10132
10133   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
10134
10135   fp = mp->mt_tunnel.mt_paths;
10136   for (i = 0; i < count; i++)
10137     {
10138       vl_api_mpls_fib_path_json_print (node, fp);
10139       fp++;
10140     }
10141 }
10142
10143 static int
10144 api_mpls_tunnel_dump (vat_main_t * vam)
10145 {
10146   vl_api_mpls_tunnel_dump_t *mp;
10147   vl_api_control_ping_t *mp_ping;
10148   int ret;
10149
10150   M (MPLS_TUNNEL_DUMP, mp);
10151
10152   S (mp);
10153
10154   /* Use a control ping for synchronization */
10155   MPING (CONTROL_PING, mp_ping);
10156   S (mp_ping);
10157
10158   W (ret);
10159   return ret;
10160 }
10161
10162 #define vl_api_mpls_table_details_t_endian vl_noop_handler
10163 #define vl_api_mpls_table_details_t_print vl_noop_handler
10164
10165
10166 static void
10167 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
10168 {
10169   vat_main_t *vam = &vat_main;
10170
10171   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
10172 }
10173
10174 static void vl_api_mpls_table_details_t_handler_json
10175   (vl_api_mpls_table_details_t * mp)
10176 {
10177   vat_main_t *vam = &vat_main;
10178   vat_json_node_t *node = NULL;
10179
10180   if (VAT_JSON_ARRAY != vam->json_tree.type)
10181     {
10182       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10183       vat_json_init_array (&vam->json_tree);
10184     }
10185   node = vat_json_array_add (&vam->json_tree);
10186
10187   vat_json_init_object (node);
10188   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
10189 }
10190
10191 static int
10192 api_mpls_table_dump (vat_main_t * vam)
10193 {
10194   vl_api_mpls_table_dump_t *mp;
10195   vl_api_control_ping_t *mp_ping;
10196   int ret;
10197
10198   M (MPLS_TABLE_DUMP, mp);
10199   S (mp);
10200
10201   /* Use a control ping for synchronization */
10202   MPING (CONTROL_PING, mp_ping);
10203   S (mp_ping);
10204
10205   W (ret);
10206   return ret;
10207 }
10208
10209 #define vl_api_mpls_route_details_t_endian vl_noop_handler
10210 #define vl_api_mpls_route_details_t_print vl_noop_handler
10211
10212 static void
10213 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
10214 {
10215   vat_main_t *vam = &vat_main;
10216   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
10217   vl_api_fib_path_t *fp;
10218   int i;
10219
10220   print (vam->ofp,
10221          "table-id %d, label %u, ess_bit %u",
10222          ntohl (mp->mr_route.mr_table_id),
10223          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
10224   fp = mp->mr_route.mr_paths;
10225   for (i = 0; i < count; i++)
10226     {
10227       vl_api_fib_path_print (vam, fp);
10228       fp++;
10229     }
10230 }
10231
10232 static void vl_api_mpls_route_details_t_handler_json
10233   (vl_api_mpls_route_details_t * mp)
10234 {
10235   vat_main_t *vam = &vat_main;
10236   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
10237   vat_json_node_t *node = NULL;
10238   vl_api_fib_path_t *fp;
10239   int i;
10240
10241   if (VAT_JSON_ARRAY != vam->json_tree.type)
10242     {
10243       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10244       vat_json_init_array (&vam->json_tree);
10245     }
10246   node = vat_json_array_add (&vam->json_tree);
10247
10248   vat_json_init_object (node);
10249   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
10250   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
10251   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
10252   vat_json_object_add_uint (node, "path_count", count);
10253   fp = mp->mr_route.mr_paths;
10254   for (i = 0; i < count; i++)
10255     {
10256       vl_api_mpls_fib_path_json_print (node, fp);
10257       fp++;
10258     }
10259 }
10260
10261 static int
10262 api_mpls_route_dump (vat_main_t * vam)
10263 {
10264   unformat_input_t *input = vam->input;
10265   vl_api_mpls_route_dump_t *mp;
10266   vl_api_control_ping_t *mp_ping;
10267   u32 table_id;
10268   int ret;
10269
10270   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10271     {
10272       if (unformat (input, "table_id %d", &table_id))
10273         ;
10274       else
10275         break;
10276     }
10277   if (table_id == ~0)
10278     {
10279       errmsg ("missing table id");
10280       return -99;
10281     }
10282
10283   M (MPLS_ROUTE_DUMP, mp);
10284
10285   mp->table.mt_table_id = ntohl (table_id);
10286   S (mp);
10287
10288   /* Use a control ping for synchronization */
10289   MPING (CONTROL_PING, mp_ping);
10290   S (mp_ping);
10291
10292   W (ret);
10293   return ret;
10294 }
10295
10296 #define vl_api_ip_table_details_t_endian vl_noop_handler
10297 #define vl_api_ip_table_details_t_print vl_noop_handler
10298
10299 static void
10300 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
10301 {
10302   vat_main_t *vam = &vat_main;
10303
10304   print (vam->ofp,
10305          "%s; table-id %d, prefix %U/%d",
10306          mp->table.name, ntohl (mp->table.table_id));
10307 }
10308
10309
10310 static void vl_api_ip_table_details_t_handler_json
10311   (vl_api_ip_table_details_t * mp)
10312 {
10313   vat_main_t *vam = &vat_main;
10314   vat_json_node_t *node = NULL;
10315
10316   if (VAT_JSON_ARRAY != vam->json_tree.type)
10317     {
10318       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10319       vat_json_init_array (&vam->json_tree);
10320     }
10321   node = vat_json_array_add (&vam->json_tree);
10322
10323   vat_json_init_object (node);
10324   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
10325 }
10326
10327 static int
10328 api_ip_table_dump (vat_main_t * vam)
10329 {
10330   vl_api_ip_table_dump_t *mp;
10331   vl_api_control_ping_t *mp_ping;
10332   int ret;
10333
10334   M (IP_TABLE_DUMP, mp);
10335   S (mp);
10336
10337   /* Use a control ping for synchronization */
10338   MPING (CONTROL_PING, mp_ping);
10339   S (mp_ping);
10340
10341   W (ret);
10342   return ret;
10343 }
10344
10345 static int
10346 api_ip_mtable_dump (vat_main_t * vam)
10347 {
10348   vl_api_ip_mtable_dump_t *mp;
10349   vl_api_control_ping_t *mp_ping;
10350   int ret;
10351
10352   M (IP_MTABLE_DUMP, mp);
10353   S (mp);
10354
10355   /* Use a control ping for synchronization */
10356   MPING (CONTROL_PING, mp_ping);
10357   S (mp_ping);
10358
10359   W (ret);
10360   return ret;
10361 }
10362
10363 static int
10364 api_ip_mroute_dump (vat_main_t * vam)
10365 {
10366   unformat_input_t *input = vam->input;
10367   vl_api_control_ping_t *mp_ping;
10368   vl_api_ip_mroute_dump_t *mp;
10369   int ret, is_ip6;
10370   u32 table_id;
10371
10372   is_ip6 = 0;
10373   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10374     {
10375       if (unformat (input, "table_id %d", &table_id))
10376         ;
10377       else if (unformat (input, "ip6"))
10378         is_ip6 = 1;
10379       else if (unformat (input, "ip4"))
10380         is_ip6 = 0;
10381       else
10382         break;
10383     }
10384   if (table_id == ~0)
10385     {
10386       errmsg ("missing table id");
10387       return -99;
10388     }
10389
10390   M (IP_MROUTE_DUMP, mp);
10391   mp->table.table_id = table_id;
10392   mp->table.is_ip6 = is_ip6;
10393   S (mp);
10394
10395   /* Use a control ping for synchronization */
10396   MPING (CONTROL_PING, mp_ping);
10397   S (mp_ping);
10398
10399   W (ret);
10400   return ret;
10401 }
10402
10403 #define vl_api_ip_route_details_t_endian vl_noop_handler
10404 #define vl_api_ip_route_details_t_print vl_noop_handler
10405
10406 static void
10407 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
10408 {
10409   vat_main_t *vam = &vat_main;
10410   u8 count = mp->route.n_paths;
10411   vl_api_fib_path_t *fp;
10412   int i;
10413
10414   print (vam->ofp,
10415          "table-id %d, prefix %U/%d",
10416          ntohl (mp->route.table_id),
10417          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
10418   for (i = 0; i < count; i++)
10419     {
10420       fp = &mp->route.paths[i];
10421
10422       vl_api_fib_path_print (vam, fp);
10423       fp++;
10424     }
10425 }
10426
10427 static void vl_api_ip_route_details_t_handler_json
10428   (vl_api_ip_route_details_t * mp)
10429 {
10430   vat_main_t *vam = &vat_main;
10431   u8 count = mp->route.n_paths;
10432   vat_json_node_t *node = NULL;
10433   struct in_addr ip4;
10434   struct in6_addr ip6;
10435   vl_api_fib_path_t *fp;
10436   int i;
10437
10438   if (VAT_JSON_ARRAY != vam->json_tree.type)
10439     {
10440       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10441       vat_json_init_array (&vam->json_tree);
10442     }
10443   node = vat_json_array_add (&vam->json_tree);
10444
10445   vat_json_init_object (node);
10446   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
10447   if (ADDRESS_IP6 == mp->route.prefix.address.af)
10448     {
10449       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
10450       vat_json_object_add_ip6 (node, "prefix", ip6);
10451     }
10452   else
10453     {
10454       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
10455       vat_json_object_add_ip4 (node, "prefix", ip4);
10456     }
10457   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
10458   vat_json_object_add_uint (node, "path_count", count);
10459   for (i = 0; i < count; i++)
10460     {
10461       fp = &mp->route.paths[i];
10462       vl_api_mpls_fib_path_json_print (node, fp);
10463     }
10464 }
10465
10466 static int
10467 api_ip_route_dump (vat_main_t * vam)
10468 {
10469   unformat_input_t *input = vam->input;
10470   vl_api_ip_route_dump_t *mp;
10471   vl_api_control_ping_t *mp_ping;
10472   u32 table_id;
10473   u8 is_ip6;
10474   int ret;
10475
10476   is_ip6 = 0;
10477   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10478     {
10479       if (unformat (input, "table_id %d", &table_id))
10480         ;
10481       else if (unformat (input, "ip6"))
10482         is_ip6 = 1;
10483       else if (unformat (input, "ip4"))
10484         is_ip6 = 0;
10485       else
10486         break;
10487     }
10488   if (table_id == ~0)
10489     {
10490       errmsg ("missing table id");
10491       return -99;
10492     }
10493
10494   M (IP_ROUTE_DUMP, mp);
10495
10496   mp->table.table_id = table_id;
10497   mp->table.is_ip6 = is_ip6;
10498
10499   S (mp);
10500
10501   /* Use a control ping for synchronization */
10502   MPING (CONTROL_PING, mp_ping);
10503   S (mp_ping);
10504
10505   W (ret);
10506   return ret;
10507 }
10508
10509 static void
10510 vl_api_ipfix_exporter_details_t_handler (vl_api_ipfix_exporter_details_t * mp)
10511 {
10512   vat_main_t *vam = &vat_main;
10513
10514   print (vam->ofp, "collector_address %U, collector_port %d, "
10515          "src_address %U, vrf_id %d, path_mtu %u, "
10516          "template_interval %u, udp_checksum %d",
10517          format_ip4_address, mp->collector_address,
10518          ntohs (mp->collector_port),
10519          format_ip4_address, mp->src_address,
10520          ntohl (mp->vrf_id), ntohl (mp->path_mtu),
10521          ntohl (mp->template_interval), mp->udp_checksum);
10522
10523   vam->retval = 0;
10524   vam->result_ready = 1;
10525 }
10526
10527 static void
10528   vl_api_ipfix_exporter_details_t_handler_json
10529   (vl_api_ipfix_exporter_details_t * mp)
10530 {
10531   vat_main_t *vam = &vat_main;
10532   vat_json_node_t node;
10533   struct in_addr collector_address;
10534   struct in_addr src_address;
10535
10536   vat_json_init_object (&node);
10537   clib_memcpy (&collector_address, &mp->collector_address,
10538                sizeof (collector_address));
10539   vat_json_object_add_ip4 (&node, "collector_address", collector_address);
10540   vat_json_object_add_uint (&node, "collector_port",
10541                             ntohs (mp->collector_port));
10542   clib_memcpy (&src_address, &mp->src_address, sizeof (src_address));
10543   vat_json_object_add_ip4 (&node, "src_address", src_address);
10544   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
10545   vat_json_object_add_uint (&node, "path_mtu", ntohl (mp->path_mtu));
10546   vat_json_object_add_uint (&node, "template_interval",
10547                             ntohl (mp->template_interval));
10548   vat_json_object_add_int (&node, "udp_checksum", mp->udp_checksum);
10549
10550   vat_json_print (vam->ofp, &node);
10551   vat_json_free (&node);
10552   vam->retval = 0;
10553   vam->result_ready = 1;
10554 }
10555
10556 int
10557 api_ipfix_exporter_dump (vat_main_t * vam)
10558 {
10559   vl_api_ipfix_exporter_dump_t *mp;
10560   int ret;
10561
10562   /* Construct the API message */
10563   M (IPFIX_EXPORTER_DUMP, mp);
10564   mp->context = 0;
10565
10566   S (mp);
10567   W (ret);
10568   return ret;
10569 }
10570
10571 static int
10572 api_ipfix_classify_stream_dump (vat_main_t * vam)
10573 {
10574   vl_api_ipfix_classify_stream_dump_t *mp;
10575   int ret;
10576
10577   /* Construct the API message */
10578   M (IPFIX_CLASSIFY_STREAM_DUMP, mp);
10579   mp->context = 0;
10580
10581   S (mp);
10582   W (ret);
10583   return ret;
10584   /* NOTREACHED */
10585   return 0;
10586 }
10587
10588 static void
10589   vl_api_ipfix_classify_stream_details_t_handler
10590   (vl_api_ipfix_classify_stream_details_t * mp)
10591 {
10592   vat_main_t *vam = &vat_main;
10593   print (vam->ofp, "domain_id %d, src_port %d",
10594          ntohl (mp->domain_id), ntohs (mp->src_port));
10595   vam->retval = 0;
10596   vam->result_ready = 1;
10597 }
10598
10599 static void
10600   vl_api_ipfix_classify_stream_details_t_handler_json
10601   (vl_api_ipfix_classify_stream_details_t * mp)
10602 {
10603   vat_main_t *vam = &vat_main;
10604   vat_json_node_t node;
10605
10606   vat_json_init_object (&node);
10607   vat_json_object_add_uint (&node, "domain_id", ntohl (mp->domain_id));
10608   vat_json_object_add_uint (&node, "src_port", ntohs (mp->src_port));
10609
10610   vat_json_print (vam->ofp, &node);
10611   vat_json_free (&node);
10612   vam->retval = 0;
10613   vam->result_ready = 1;
10614 }
10615
10616 static int
10617 api_ipfix_classify_table_dump (vat_main_t * vam)
10618 {
10619   vl_api_ipfix_classify_table_dump_t *mp;
10620   vl_api_control_ping_t *mp_ping;
10621   int ret;
10622
10623   if (!vam->json_output)
10624     {
10625       print (vam->ofp, "%15s%15s%20s", "table_id", "ip_version",
10626              "transport_protocol");
10627     }
10628
10629   /* Construct the API message */
10630   M (IPFIX_CLASSIFY_TABLE_DUMP, mp);
10631
10632   /* send it... */
10633   S (mp);
10634
10635   /* Use a control ping for synchronization */
10636   MPING (CONTROL_PING, mp_ping);
10637   S (mp_ping);
10638
10639   W (ret);
10640   return ret;
10641 }
10642
10643 static void
10644   vl_api_ipfix_classify_table_details_t_handler
10645   (vl_api_ipfix_classify_table_details_t * mp)
10646 {
10647   vat_main_t *vam = &vat_main;
10648   print (vam->ofp, "%15d%15d%20d", ntohl (mp->table_id), mp->ip_version,
10649          mp->transport_protocol);
10650 }
10651
10652 static void
10653   vl_api_ipfix_classify_table_details_t_handler_json
10654   (vl_api_ipfix_classify_table_details_t * mp)
10655 {
10656   vat_json_node_t *node = NULL;
10657   vat_main_t *vam = &vat_main;
10658
10659   if (VAT_JSON_ARRAY != vam->json_tree.type)
10660     {
10661       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10662       vat_json_init_array (&vam->json_tree);
10663     }
10664
10665   node = vat_json_array_add (&vam->json_tree);
10666   vat_json_init_object (node);
10667
10668   vat_json_object_add_uint (node, "table_id", ntohl (mp->table_id));
10669   vat_json_object_add_uint (node, "ip_version", mp->ip_version);
10670   vat_json_object_add_uint (node, "transport_protocol",
10671                             mp->transport_protocol);
10672 }
10673
10674 static int
10675 api_sw_interface_span_enable_disable (vat_main_t * vam)
10676 {
10677   unformat_input_t *i = vam->input;
10678   vl_api_sw_interface_span_enable_disable_t *mp;
10679   u32 src_sw_if_index = ~0;
10680   u32 dst_sw_if_index = ~0;
10681   u8 state = 3;
10682   int ret;
10683   u8 is_l2 = 0;
10684
10685   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10686     {
10687       if (unformat
10688           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
10689         ;
10690       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
10691         ;
10692       else
10693         if (unformat
10694             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
10695         ;
10696       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
10697         ;
10698       else if (unformat (i, "disable"))
10699         state = 0;
10700       else if (unformat (i, "rx"))
10701         state = 1;
10702       else if (unformat (i, "tx"))
10703         state = 2;
10704       else if (unformat (i, "both"))
10705         state = 3;
10706       else if (unformat (i, "l2"))
10707         is_l2 = 1;
10708       else
10709         break;
10710     }
10711
10712   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
10713
10714   mp->sw_if_index_from = htonl (src_sw_if_index);
10715   mp->sw_if_index_to = htonl (dst_sw_if_index);
10716   mp->state = state;
10717   mp->is_l2 = is_l2;
10718
10719   S (mp);
10720   W (ret);
10721   return ret;
10722 }
10723
10724 static void
10725 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
10726                                             * mp)
10727 {
10728   vat_main_t *vam = &vat_main;
10729   u8 *sw_if_from_name = 0;
10730   u8 *sw_if_to_name = 0;
10731   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
10732   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
10733   char *states[] = { "none", "rx", "tx", "both" };
10734   hash_pair_t *p;
10735
10736   /* *INDENT-OFF* */
10737   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
10738   ({
10739     if ((u32) p->value[0] == sw_if_index_from)
10740       {
10741         sw_if_from_name = (u8 *)(p->key);
10742         if (sw_if_to_name)
10743           break;
10744       }
10745     if ((u32) p->value[0] == sw_if_index_to)
10746       {
10747         sw_if_to_name = (u8 *)(p->key);
10748         if (sw_if_from_name)
10749           break;
10750       }
10751   }));
10752   /* *INDENT-ON* */
10753   print (vam->ofp, "%20s => %20s (%s) %s",
10754          sw_if_from_name, sw_if_to_name, states[mp->state],
10755          mp->is_l2 ? "l2" : "device");
10756 }
10757
10758 static void
10759   vl_api_sw_interface_span_details_t_handler_json
10760   (vl_api_sw_interface_span_details_t * mp)
10761 {
10762   vat_main_t *vam = &vat_main;
10763   vat_json_node_t *node = NULL;
10764   u8 *sw_if_from_name = 0;
10765   u8 *sw_if_to_name = 0;
10766   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
10767   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
10768   hash_pair_t *p;
10769
10770   /* *INDENT-OFF* */
10771   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
10772   ({
10773     if ((u32) p->value[0] == sw_if_index_from)
10774       {
10775         sw_if_from_name = (u8 *)(p->key);
10776         if (sw_if_to_name)
10777           break;
10778       }
10779     if ((u32) p->value[0] == sw_if_index_to)
10780       {
10781         sw_if_to_name = (u8 *)(p->key);
10782         if (sw_if_from_name)
10783           break;
10784       }
10785   }));
10786   /* *INDENT-ON* */
10787
10788   if (VAT_JSON_ARRAY != vam->json_tree.type)
10789     {
10790       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10791       vat_json_init_array (&vam->json_tree);
10792     }
10793   node = vat_json_array_add (&vam->json_tree);
10794
10795   vat_json_init_object (node);
10796   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
10797   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
10798   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
10799   if (0 != sw_if_to_name)
10800     {
10801       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
10802     }
10803   vat_json_object_add_uint (node, "state", mp->state);
10804   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
10805 }
10806
10807 static int
10808 api_sw_interface_span_dump (vat_main_t * vam)
10809 {
10810   unformat_input_t *input = vam->input;
10811   vl_api_sw_interface_span_dump_t *mp;
10812   vl_api_control_ping_t *mp_ping;
10813   u8 is_l2 = 0;
10814   int ret;
10815
10816   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10817     {
10818       if (unformat (input, "l2"))
10819         is_l2 = 1;
10820       else
10821         break;
10822     }
10823
10824   M (SW_INTERFACE_SPAN_DUMP, mp);
10825   mp->is_l2 = is_l2;
10826   S (mp);
10827
10828   /* Use a control ping for synchronization */
10829   MPING (CONTROL_PING, mp_ping);
10830   S (mp_ping);
10831
10832   W (ret);
10833   return ret;
10834 }
10835
10836 int
10837 api_pg_create_interface (vat_main_t * vam)
10838 {
10839   unformat_input_t *input = vam->input;
10840   vl_api_pg_create_interface_t *mp;
10841
10842   u32 if_id = ~0, gso_size = 0;
10843   u8 gso_enabled = 0;
10844   int ret;
10845   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10846     {
10847       if (unformat (input, "if_id %d", &if_id))
10848         ;
10849       else if (unformat (input, "gso-enabled"))
10850         {
10851           gso_enabled = 1;
10852           if (unformat (input, "gso-size %u", &gso_size))
10853             ;
10854           else
10855             {
10856               errmsg ("missing gso-size");
10857               return -99;
10858             }
10859         }
10860       else
10861         break;
10862     }
10863   if (if_id == ~0)
10864     {
10865       errmsg ("missing pg interface index");
10866       return -99;
10867     }
10868
10869   /* Construct the API message */
10870   M (PG_CREATE_INTERFACE, mp);
10871   mp->context = 0;
10872   mp->interface_id = ntohl (if_id);
10873   mp->gso_enabled = gso_enabled;
10874
10875   S (mp);
10876   W (ret);
10877   return ret;
10878 }
10879
10880 int
10881 api_pg_capture (vat_main_t * vam)
10882 {
10883   unformat_input_t *input = vam->input;
10884   vl_api_pg_capture_t *mp;
10885
10886   u32 if_id = ~0;
10887   u8 enable = 1;
10888   u32 count = 1;
10889   u8 pcap_file_set = 0;
10890   u8 *pcap_file = 0;
10891   int ret;
10892   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10893     {
10894       if (unformat (input, "if_id %d", &if_id))
10895         ;
10896       else if (unformat (input, "pcap %s", &pcap_file))
10897         pcap_file_set = 1;
10898       else if (unformat (input, "count %d", &count))
10899         ;
10900       else if (unformat (input, "disable"))
10901         enable = 0;
10902       else
10903         break;
10904     }
10905   if (if_id == ~0)
10906     {
10907       errmsg ("missing pg interface index");
10908       return -99;
10909     }
10910   if (pcap_file_set > 0)
10911     {
10912       if (vec_len (pcap_file) > 255)
10913         {
10914           errmsg ("pcap file name is too long");
10915           return -99;
10916         }
10917     }
10918
10919   /* Construct the API message */
10920   M (PG_CAPTURE, mp);
10921   mp->context = 0;
10922   mp->interface_id = ntohl (if_id);
10923   mp->is_enabled = enable;
10924   mp->count = ntohl (count);
10925   if (pcap_file_set != 0)
10926     {
10927       vl_api_vec_to_api_string (pcap_file, &mp->pcap_file_name);
10928     }
10929   vec_free (pcap_file);
10930
10931   S (mp);
10932   W (ret);
10933   return ret;
10934 }
10935
10936 int
10937 api_pg_enable_disable (vat_main_t * vam)
10938 {
10939   unformat_input_t *input = vam->input;
10940   vl_api_pg_enable_disable_t *mp;
10941
10942   u8 enable = 1;
10943   u8 stream_name_set = 0;
10944   u8 *stream_name = 0;
10945   int ret;
10946   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10947     {
10948       if (unformat (input, "stream %s", &stream_name))
10949         stream_name_set = 1;
10950       else if (unformat (input, "disable"))
10951         enable = 0;
10952       else
10953         break;
10954     }
10955
10956   if (stream_name_set > 0)
10957     {
10958       if (vec_len (stream_name) > 255)
10959         {
10960           errmsg ("stream name too long");
10961           return -99;
10962         }
10963     }
10964
10965   /* Construct the API message */
10966   M (PG_ENABLE_DISABLE, mp);
10967   mp->context = 0;
10968   mp->is_enabled = enable;
10969   if (stream_name_set != 0)
10970     {
10971       vl_api_vec_to_api_string (stream_name, &mp->stream_name);
10972     }
10973   vec_free (stream_name);
10974
10975   S (mp);
10976   W (ret);
10977   return ret;
10978 }
10979
10980 int
10981 api_pg_interface_enable_disable_coalesce (vat_main_t * vam)
10982 {
10983   unformat_input_t *input = vam->input;
10984   vl_api_pg_interface_enable_disable_coalesce_t *mp;
10985
10986   u32 sw_if_index = ~0;
10987   u8 enable = 1;
10988   int ret;
10989   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10990     {
10991       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10992         ;
10993       else if (unformat (input, "sw_if_index %d", &sw_if_index))
10994         ;
10995       else if (unformat (input, "disable"))
10996         enable = 0;
10997       else
10998         break;
10999     }
11000
11001   if (sw_if_index == ~0)
11002     {
11003       errmsg ("Interface required but not specified");
11004       return -99;
11005     }
11006
11007   /* Construct the API message */
11008   M (PG_INTERFACE_ENABLE_DISABLE_COALESCE, mp);
11009   mp->context = 0;
11010   mp->coalesce_enabled = enable;
11011   mp->sw_if_index = htonl (sw_if_index);
11012
11013   S (mp);
11014   W (ret);
11015   return ret;
11016 }
11017
11018 int
11019 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
11020 {
11021   unformat_input_t *input = vam->input;
11022   vl_api_ip_source_and_port_range_check_add_del_t *mp;
11023
11024   u16 *low_ports = 0;
11025   u16 *high_ports = 0;
11026   u16 this_low;
11027   u16 this_hi;
11028   vl_api_prefix_t prefix;
11029   u32 tmp, tmp2;
11030   u8 prefix_set = 0;
11031   u32 vrf_id = ~0;
11032   u8 is_add = 1;
11033   int ret;
11034
11035   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11036     {
11037       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
11038         prefix_set = 1;
11039       else if (unformat (input, "vrf %d", &vrf_id))
11040         ;
11041       else if (unformat (input, "del"))
11042         is_add = 0;
11043       else if (unformat (input, "port %d", &tmp))
11044         {
11045           if (tmp == 0 || tmp > 65535)
11046             {
11047               errmsg ("port %d out of range", tmp);
11048               return -99;
11049             }
11050           this_low = tmp;
11051           this_hi = this_low + 1;
11052           vec_add1 (low_ports, this_low);
11053           vec_add1 (high_ports, this_hi);
11054         }
11055       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
11056         {
11057           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
11058             {
11059               errmsg ("incorrect range parameters");
11060               return -99;
11061             }
11062           this_low = tmp;
11063           /* Note: in debug CLI +1 is added to high before
11064              passing to real fn that does "the work"
11065              (ip_source_and_port_range_check_add_del).
11066              This fn is a wrapper around the binary API fn a
11067              control plane will call, which expects this increment
11068              to have occurred. Hence letting the binary API control
11069              plane fn do the increment for consistency between VAT
11070              and other control planes.
11071            */
11072           this_hi = tmp2;
11073           vec_add1 (low_ports, this_low);
11074           vec_add1 (high_ports, this_hi);
11075         }
11076       else
11077         break;
11078     }
11079
11080   if (prefix_set == 0)
11081     {
11082       errmsg ("<address>/<mask> not specified");
11083       return -99;
11084     }
11085
11086   if (vrf_id == ~0)
11087     {
11088       errmsg ("VRF ID required, not specified");
11089       return -99;
11090     }
11091
11092   if (vrf_id == 0)
11093     {
11094       errmsg
11095         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
11096       return -99;
11097     }
11098
11099   if (vec_len (low_ports) == 0)
11100     {
11101       errmsg ("At least one port or port range required");
11102       return -99;
11103     }
11104
11105   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
11106
11107   mp->is_add = is_add;
11108
11109   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
11110
11111   mp->number_of_ranges = vec_len (low_ports);
11112
11113   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
11114   vec_free (low_ports);
11115
11116   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
11117   vec_free (high_ports);
11118
11119   mp->vrf_id = ntohl (vrf_id);
11120
11121   S (mp);
11122   W (ret);
11123   return ret;
11124 }
11125
11126 int
11127 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
11128 {
11129   unformat_input_t *input = vam->input;
11130   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
11131   u32 sw_if_index = ~0;
11132   int vrf_set = 0;
11133   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
11134   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
11135   u8 is_add = 1;
11136   int ret;
11137
11138   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11139     {
11140       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11141         ;
11142       else if (unformat (input, "sw_if_index %d", &sw_if_index))
11143         ;
11144       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
11145         vrf_set = 1;
11146       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
11147         vrf_set = 1;
11148       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
11149         vrf_set = 1;
11150       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
11151         vrf_set = 1;
11152       else if (unformat (input, "del"))
11153         is_add = 0;
11154       else
11155         break;
11156     }
11157
11158   if (sw_if_index == ~0)
11159     {
11160       errmsg ("Interface required but not specified");
11161       return -99;
11162     }
11163
11164   if (vrf_set == 0)
11165     {
11166       errmsg ("VRF ID required but not specified");
11167       return -99;
11168     }
11169
11170   if (tcp_out_vrf_id == 0
11171       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
11172     {
11173       errmsg
11174         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
11175       return -99;
11176     }
11177
11178   /* Construct the API message */
11179   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
11180
11181   mp->sw_if_index = ntohl (sw_if_index);
11182   mp->is_add = is_add;
11183   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
11184   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
11185   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
11186   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
11187
11188   /* send it... */
11189   S (mp);
11190
11191   /* Wait for a reply... */
11192   W (ret);
11193   return ret;
11194 }
11195
11196 static int
11197 api_set_punt (vat_main_t * vam)
11198 {
11199   unformat_input_t *i = vam->input;
11200   vl_api_address_family_t af;
11201   vl_api_set_punt_t *mp;
11202   u32 protocol = ~0;
11203   u32 port = ~0;
11204   int is_add = 1;
11205   int ret;
11206
11207   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11208     {
11209       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
11210         ;
11211       else if (unformat (i, "protocol %d", &protocol))
11212         ;
11213       else if (unformat (i, "port %d", &port))
11214         ;
11215       else if (unformat (i, "del"))
11216         is_add = 0;
11217       else
11218         {
11219           clib_warning ("parse error '%U'", format_unformat_error, i);
11220           return -99;
11221         }
11222     }
11223
11224   M (SET_PUNT, mp);
11225
11226   mp->is_add = (u8) is_add;
11227   mp->punt.type = PUNT_API_TYPE_L4;
11228   mp->punt.punt.l4.af = af;
11229   mp->punt.punt.l4.protocol = (u8) protocol;
11230   mp->punt.punt.l4.port = htons ((u16) port);
11231
11232   S (mp);
11233   W (ret);
11234   return ret;
11235 }
11236
11237 static int
11238 api_delete_subif (vat_main_t * vam)
11239 {
11240   unformat_input_t *i = vam->input;
11241   vl_api_delete_subif_t *mp;
11242   u32 sw_if_index = ~0;
11243   int ret;
11244
11245   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11246     {
11247       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11248         ;
11249       if (unformat (i, "sw_if_index %d", &sw_if_index))
11250         ;
11251       else
11252         break;
11253     }
11254
11255   if (sw_if_index == ~0)
11256     {
11257       errmsg ("missing sw_if_index");
11258       return -99;
11259     }
11260
11261   /* Construct the API message */
11262   M (DELETE_SUBIF, mp);
11263   mp->sw_if_index = ntohl (sw_if_index);
11264
11265   S (mp);
11266   W (ret);
11267   return ret;
11268 }
11269
11270 #define foreach_pbb_vtr_op      \
11271 _("disable",  L2_VTR_DISABLED)  \
11272 _("pop",  L2_VTR_POP_2)         \
11273 _("push",  L2_VTR_PUSH_2)
11274
11275 static int
11276 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
11277 {
11278   unformat_input_t *i = vam->input;
11279   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
11280   u32 sw_if_index = ~0, vtr_op = ~0;
11281   u16 outer_tag = ~0;
11282   u8 dmac[6], smac[6];
11283   u8 dmac_set = 0, smac_set = 0;
11284   u16 vlanid = 0;
11285   u32 sid = ~0;
11286   u32 tmp;
11287   int ret;
11288
11289   /* Shut up coverity */
11290   clib_memset (dmac, 0, sizeof (dmac));
11291   clib_memset (smac, 0, sizeof (smac));
11292
11293   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11294     {
11295       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11296         ;
11297       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11298         ;
11299       else if (unformat (i, "vtr_op %d", &vtr_op))
11300         ;
11301 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
11302       foreach_pbb_vtr_op
11303 #undef _
11304         else if (unformat (i, "translate_pbb_stag"))
11305         {
11306           if (unformat (i, "%d", &tmp))
11307             {
11308               vtr_op = L2_VTR_TRANSLATE_2_1;
11309               outer_tag = tmp;
11310             }
11311           else
11312             {
11313               errmsg
11314                 ("translate_pbb_stag operation requires outer tag definition");
11315               return -99;
11316             }
11317         }
11318       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
11319         dmac_set++;
11320       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
11321         smac_set++;
11322       else if (unformat (i, "sid %d", &sid))
11323         ;
11324       else if (unformat (i, "vlanid %d", &tmp))
11325         vlanid = tmp;
11326       else
11327         {
11328           clib_warning ("parse error '%U'", format_unformat_error, i);
11329           return -99;
11330         }
11331     }
11332
11333   if ((sw_if_index == ~0) || (vtr_op == ~0))
11334     {
11335       errmsg ("missing sw_if_index or vtr operation");
11336       return -99;
11337     }
11338   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
11339       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
11340     {
11341       errmsg
11342         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
11343       return -99;
11344     }
11345
11346   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
11347   mp->sw_if_index = ntohl (sw_if_index);
11348   mp->vtr_op = ntohl (vtr_op);
11349   mp->outer_tag = ntohs (outer_tag);
11350   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
11351   clib_memcpy (mp->b_smac, smac, sizeof (smac));
11352   mp->b_vlanid = ntohs (vlanid);
11353   mp->i_sid = ntohl (sid);
11354
11355   S (mp);
11356   W (ret);
11357   return ret;
11358 }
11359
11360 static int
11361 api_feature_enable_disable (vat_main_t * vam)
11362 {
11363   unformat_input_t *i = vam->input;
11364   vl_api_feature_enable_disable_t *mp;
11365   u8 *arc_name = 0;
11366   u8 *feature_name = 0;
11367   u32 sw_if_index = ~0;
11368   u8 enable = 1;
11369   int ret;
11370
11371   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11372     {
11373       if (unformat (i, "arc_name %s", &arc_name))
11374         ;
11375       else if (unformat (i, "feature_name %s", &feature_name))
11376         ;
11377       else
11378         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11379         ;
11380       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11381         ;
11382       else if (unformat (i, "disable"))
11383         enable = 0;
11384       else
11385         break;
11386     }
11387
11388   if (arc_name == 0)
11389     {
11390       errmsg ("missing arc name");
11391       return -99;
11392     }
11393   if (vec_len (arc_name) > 63)
11394     {
11395       errmsg ("arc name too long");
11396     }
11397
11398   if (feature_name == 0)
11399     {
11400       errmsg ("missing feature name");
11401       return -99;
11402     }
11403   if (vec_len (feature_name) > 63)
11404     {
11405       errmsg ("feature name too long");
11406     }
11407
11408   if (sw_if_index == ~0)
11409     {
11410       errmsg ("missing interface name or sw_if_index");
11411       return -99;
11412     }
11413
11414   /* Construct the API message */
11415   M (FEATURE_ENABLE_DISABLE, mp);
11416   mp->sw_if_index = ntohl (sw_if_index);
11417   mp->enable = enable;
11418   clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name));
11419   clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name));
11420   vec_free (arc_name);
11421   vec_free (feature_name);
11422
11423   S (mp);
11424   W (ret);
11425   return ret;
11426 }
11427
11428 static int
11429 api_feature_gso_enable_disable (vat_main_t * vam)
11430 {
11431   unformat_input_t *i = vam->input;
11432   vl_api_feature_gso_enable_disable_t *mp;
11433   u32 sw_if_index = ~0;
11434   u8 enable = 1;
11435   int ret;
11436
11437   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11438     {
11439       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11440         ;
11441       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11442         ;
11443       else if (unformat (i, "enable"))
11444         enable = 1;
11445       else if (unformat (i, "disable"))
11446         enable = 0;
11447       else
11448         break;
11449     }
11450
11451   if (sw_if_index == ~0)
11452     {
11453       errmsg ("missing interface name or sw_if_index");
11454       return -99;
11455     }
11456
11457   /* Construct the API message */
11458   M (FEATURE_GSO_ENABLE_DISABLE, mp);
11459   mp->sw_if_index = ntohl (sw_if_index);
11460   mp->enable_disable = enable;
11461
11462   S (mp);
11463   W (ret);
11464   return ret;
11465 }
11466
11467 static int
11468 api_sw_interface_tag_add_del (vat_main_t * vam)
11469 {
11470   unformat_input_t *i = vam->input;
11471   vl_api_sw_interface_tag_add_del_t *mp;
11472   u32 sw_if_index = ~0;
11473   u8 *tag = 0;
11474   u8 enable = 1;
11475   int ret;
11476
11477   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11478     {
11479       if (unformat (i, "tag %s", &tag))
11480         ;
11481       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11482         ;
11483       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11484         ;
11485       else if (unformat (i, "del"))
11486         enable = 0;
11487       else
11488         break;
11489     }
11490
11491   if (sw_if_index == ~0)
11492     {
11493       errmsg ("missing interface name or sw_if_index");
11494       return -99;
11495     }
11496
11497   if (enable && (tag == 0))
11498     {
11499       errmsg ("no tag specified");
11500       return -99;
11501     }
11502
11503   /* Construct the API message */
11504   M (SW_INTERFACE_TAG_ADD_DEL, mp);
11505   mp->sw_if_index = ntohl (sw_if_index);
11506   mp->is_add = enable;
11507   if (enable)
11508     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
11509   vec_free (tag);
11510
11511   S (mp);
11512   W (ret);
11513   return ret;
11514 }
11515
11516 static int
11517 api_sw_interface_add_del_mac_address (vat_main_t * vam)
11518 {
11519   unformat_input_t *i = vam->input;
11520   vl_api_mac_address_t mac = { 0 };
11521   vl_api_sw_interface_add_del_mac_address_t *mp;
11522   u32 sw_if_index = ~0;
11523   u8 is_add = 1;
11524   u8 mac_set = 0;
11525   int ret;
11526
11527   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11528     {
11529       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11530         ;
11531       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11532         ;
11533       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
11534         mac_set++;
11535       else if (unformat (i, "del"))
11536         is_add = 0;
11537       else
11538         break;
11539     }
11540
11541   if (sw_if_index == ~0)
11542     {
11543       errmsg ("missing interface name or sw_if_index");
11544       return -99;
11545     }
11546
11547   if (!mac_set)
11548     {
11549       errmsg ("missing MAC address");
11550       return -99;
11551     }
11552
11553   /* Construct the API message */
11554   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
11555   mp->sw_if_index = ntohl (sw_if_index);
11556   mp->is_add = is_add;
11557   clib_memcpy (&mp->addr, &mac, sizeof (mac));
11558
11559   S (mp);
11560   W (ret);
11561   return ret;
11562 }
11563
11564 static void vl_api_l2_xconnect_details_t_handler
11565   (vl_api_l2_xconnect_details_t * mp)
11566 {
11567   vat_main_t *vam = &vat_main;
11568
11569   print (vam->ofp, "%15d%15d",
11570          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
11571 }
11572
11573 static void vl_api_l2_xconnect_details_t_handler_json
11574   (vl_api_l2_xconnect_details_t * mp)
11575 {
11576   vat_main_t *vam = &vat_main;
11577   vat_json_node_t *node = NULL;
11578
11579   if (VAT_JSON_ARRAY != vam->json_tree.type)
11580     {
11581       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11582       vat_json_init_array (&vam->json_tree);
11583     }
11584   node = vat_json_array_add (&vam->json_tree);
11585
11586   vat_json_init_object (node);
11587   vat_json_object_add_uint (node, "rx_sw_if_index",
11588                             ntohl (mp->rx_sw_if_index));
11589   vat_json_object_add_uint (node, "tx_sw_if_index",
11590                             ntohl (mp->tx_sw_if_index));
11591 }
11592
11593 static int
11594 api_l2_xconnect_dump (vat_main_t * vam)
11595 {
11596   vl_api_l2_xconnect_dump_t *mp;
11597   vl_api_control_ping_t *mp_ping;
11598   int ret;
11599
11600   if (!vam->json_output)
11601     {
11602       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
11603     }
11604
11605   M (L2_XCONNECT_DUMP, mp);
11606
11607   S (mp);
11608
11609   /* Use a control ping for synchronization */
11610   MPING (CONTROL_PING, mp_ping);
11611   S (mp_ping);
11612
11613   W (ret);
11614   return ret;
11615 }
11616
11617 static int
11618 api_hw_interface_set_mtu (vat_main_t * vam)
11619 {
11620   unformat_input_t *i = vam->input;
11621   vl_api_hw_interface_set_mtu_t *mp;
11622   u32 sw_if_index = ~0;
11623   u32 mtu = 0;
11624   int ret;
11625
11626   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11627     {
11628       if (unformat (i, "mtu %d", &mtu))
11629         ;
11630       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11631         ;
11632       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11633         ;
11634       else
11635         break;
11636     }
11637
11638   if (sw_if_index == ~0)
11639     {
11640       errmsg ("missing interface name or sw_if_index");
11641       return -99;
11642     }
11643
11644   if (mtu == 0)
11645     {
11646       errmsg ("no mtu specified");
11647       return -99;
11648     }
11649
11650   /* Construct the API message */
11651   M (HW_INTERFACE_SET_MTU, mp);
11652   mp->sw_if_index = ntohl (sw_if_index);
11653   mp->mtu = ntohs ((u16) mtu);
11654
11655   S (mp);
11656   W (ret);
11657   return ret;
11658 }
11659
11660 static int
11661 api_p2p_ethernet_add (vat_main_t * vam)
11662 {
11663   unformat_input_t *i = vam->input;
11664   vl_api_p2p_ethernet_add_t *mp;
11665   u32 parent_if_index = ~0;
11666   u32 sub_id = ~0;
11667   u8 remote_mac[6];
11668   u8 mac_set = 0;
11669   int ret;
11670
11671   clib_memset (remote_mac, 0, sizeof (remote_mac));
11672   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11673     {
11674       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
11675         ;
11676       else if (unformat (i, "sw_if_index %d", &parent_if_index))
11677         ;
11678       else
11679         if (unformat
11680             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
11681         mac_set++;
11682       else if (unformat (i, "sub_id %d", &sub_id))
11683         ;
11684       else
11685         {
11686           clib_warning ("parse error '%U'", format_unformat_error, i);
11687           return -99;
11688         }
11689     }
11690
11691   if (parent_if_index == ~0)
11692     {
11693       errmsg ("missing interface name or sw_if_index");
11694       return -99;
11695     }
11696   if (mac_set == 0)
11697     {
11698       errmsg ("missing remote mac address");
11699       return -99;
11700     }
11701   if (sub_id == ~0)
11702     {
11703       errmsg ("missing sub-interface id");
11704       return -99;
11705     }
11706
11707   M (P2P_ETHERNET_ADD, mp);
11708   mp->parent_if_index = ntohl (parent_if_index);
11709   mp->subif_id = ntohl (sub_id);
11710   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
11711
11712   S (mp);
11713   W (ret);
11714   return ret;
11715 }
11716
11717 static int
11718 api_p2p_ethernet_del (vat_main_t * vam)
11719 {
11720   unformat_input_t *i = vam->input;
11721   vl_api_p2p_ethernet_del_t *mp;
11722   u32 parent_if_index = ~0;
11723   u8 remote_mac[6];
11724   u8 mac_set = 0;
11725   int ret;
11726
11727   clib_memset (remote_mac, 0, sizeof (remote_mac));
11728   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11729     {
11730       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
11731         ;
11732       else if (unformat (i, "sw_if_index %d", &parent_if_index))
11733         ;
11734       else
11735         if (unformat
11736             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
11737         mac_set++;
11738       else
11739         {
11740           clib_warning ("parse error '%U'", format_unformat_error, i);
11741           return -99;
11742         }
11743     }
11744
11745   if (parent_if_index == ~0)
11746     {
11747       errmsg ("missing interface name or sw_if_index");
11748       return -99;
11749     }
11750   if (mac_set == 0)
11751     {
11752       errmsg ("missing remote mac address");
11753       return -99;
11754     }
11755
11756   M (P2P_ETHERNET_DEL, mp);
11757   mp->parent_if_index = ntohl (parent_if_index);
11758   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
11759
11760   S (mp);
11761   W (ret);
11762   return ret;
11763 }
11764
11765 static int
11766 api_tcp_configure_src_addresses (vat_main_t * vam)
11767 {
11768   vl_api_tcp_configure_src_addresses_t *mp;
11769   unformat_input_t *i = vam->input;
11770   vl_api_address_t first, last;
11771   u8 range_set = 0;
11772   u32 vrf_id = 0;
11773   int ret;
11774
11775   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11776     {
11777       if (unformat (i, "%U - %U",
11778                     unformat_vl_api_address, &first,
11779                     unformat_vl_api_address, &last))
11780         {
11781           if (range_set)
11782             {
11783               errmsg ("one range per message (range already set)");
11784               return -99;
11785             }
11786           range_set = 1;
11787         }
11788       else if (unformat (i, "vrf %d", &vrf_id))
11789         ;
11790       else
11791         break;
11792     }
11793
11794   if (range_set == 0)
11795     {
11796       errmsg ("address range not set");
11797       return -99;
11798     }
11799
11800   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
11801
11802   mp->vrf_id = ntohl (vrf_id);
11803   clib_memcpy (&mp->first_address, &first, sizeof (first));
11804   clib_memcpy (&mp->last_address, &last, sizeof (last));
11805
11806   S (mp);
11807   W (ret);
11808   return ret;
11809 }
11810
11811 static void vl_api_app_namespace_add_del_reply_t_handler
11812   (vl_api_app_namespace_add_del_reply_t * mp)
11813 {
11814   vat_main_t *vam = &vat_main;
11815   i32 retval = ntohl (mp->retval);
11816   if (vam->async_mode)
11817     {
11818       vam->async_errors += (retval < 0);
11819     }
11820   else
11821     {
11822       vam->retval = retval;
11823       if (retval == 0)
11824         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
11825       vam->result_ready = 1;
11826     }
11827 }
11828
11829 static void vl_api_app_namespace_add_del_reply_t_handler_json
11830   (vl_api_app_namespace_add_del_reply_t * mp)
11831 {
11832   vat_main_t *vam = &vat_main;
11833   vat_json_node_t node;
11834
11835   vat_json_init_object (&node);
11836   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
11837   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
11838
11839   vat_json_print (vam->ofp, &node);
11840   vat_json_free (&node);
11841
11842   vam->retval = ntohl (mp->retval);
11843   vam->result_ready = 1;
11844 }
11845
11846 static int
11847 api_app_namespace_add_del (vat_main_t * vam)
11848 {
11849   vl_api_app_namespace_add_del_t *mp;
11850   unformat_input_t *i = vam->input;
11851   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
11852   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
11853   u64 secret;
11854   int ret;
11855
11856   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11857     {
11858       if (unformat (i, "id %_%v%_", &ns_id))
11859         ;
11860       else if (unformat (i, "secret %lu", &secret))
11861         secret_set = 1;
11862       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11863         sw_if_index_set = 1;
11864       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
11865         ;
11866       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
11867         ;
11868       else
11869         break;
11870     }
11871   if (!ns_id || !secret_set || !sw_if_index_set)
11872     {
11873       errmsg ("namespace id, secret and sw_if_index must be set");
11874       return -99;
11875     }
11876   if (vec_len (ns_id) > 64)
11877     {
11878       errmsg ("namespace id too long");
11879       return -99;
11880     }
11881   M (APP_NAMESPACE_ADD_DEL, mp);
11882
11883   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
11884   mp->secret = clib_host_to_net_u64 (secret);
11885   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
11886   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
11887   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
11888   vec_free (ns_id);
11889   S (mp);
11890   W (ret);
11891   return ret;
11892 }
11893
11894 static int
11895 api_sock_init_shm (vat_main_t * vam)
11896 {
11897 #if VPP_API_TEST_BUILTIN == 0
11898   unformat_input_t *i = vam->input;
11899   vl_api_shm_elem_config_t *config = 0;
11900   u64 size = 64 << 20;
11901   int rv;
11902
11903   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11904     {
11905       if (unformat (i, "size %U", unformat_memory_size, &size))
11906         ;
11907       else
11908         break;
11909     }
11910
11911   /*
11912    * Canned custom ring allocator config.
11913    * Should probably parse all of this
11914    */
11915   vec_validate (config, 6);
11916   config[0].type = VL_API_VLIB_RING;
11917   config[0].size = 256;
11918   config[0].count = 32;
11919
11920   config[1].type = VL_API_VLIB_RING;
11921   config[1].size = 1024;
11922   config[1].count = 16;
11923
11924   config[2].type = VL_API_VLIB_RING;
11925   config[2].size = 4096;
11926   config[2].count = 2;
11927
11928   config[3].type = VL_API_CLIENT_RING;
11929   config[3].size = 256;
11930   config[3].count = 32;
11931
11932   config[4].type = VL_API_CLIENT_RING;
11933   config[4].size = 1024;
11934   config[4].count = 16;
11935
11936   config[5].type = VL_API_CLIENT_RING;
11937   config[5].size = 4096;
11938   config[5].count = 2;
11939
11940   config[6].type = VL_API_QUEUE;
11941   config[6].count = 128;
11942   config[6].size = sizeof (uword);
11943
11944   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
11945   if (!rv)
11946     vam->client_index_invalid = 1;
11947   return rv;
11948 #else
11949   return -99;
11950 #endif
11951 }
11952
11953 static void
11954 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
11955 {
11956   vat_main_t *vam = &vat_main;
11957   fib_prefix_t lcl, rmt;
11958
11959   ip_prefix_decode (&mp->lcl, &lcl);
11960   ip_prefix_decode (&mp->rmt, &rmt);
11961
11962   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
11963     {
11964       print (vam->ofp,
11965              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
11966              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
11967              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
11968              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
11969              &rmt.fp_addr.ip4, rmt.fp_len,
11970              clib_net_to_host_u16 (mp->rmt_port),
11971              clib_net_to_host_u32 (mp->action_index), mp->tag);
11972     }
11973   else
11974     {
11975       print (vam->ofp,
11976              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
11977              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
11978              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
11979              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
11980              &rmt.fp_addr.ip6, rmt.fp_len,
11981              clib_net_to_host_u16 (mp->rmt_port),
11982              clib_net_to_host_u32 (mp->action_index), mp->tag);
11983     }
11984 }
11985
11986 static void
11987 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
11988                                              mp)
11989 {
11990   vat_main_t *vam = &vat_main;
11991   vat_json_node_t *node = NULL;
11992   struct in6_addr ip6;
11993   struct in_addr ip4;
11994
11995   fib_prefix_t lcl, rmt;
11996
11997   ip_prefix_decode (&mp->lcl, &lcl);
11998   ip_prefix_decode (&mp->rmt, &rmt);
11999
12000   if (VAT_JSON_ARRAY != vam->json_tree.type)
12001     {
12002       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
12003       vat_json_init_array (&vam->json_tree);
12004     }
12005   node = vat_json_array_add (&vam->json_tree);
12006   vat_json_init_object (node);
12007
12008   vat_json_object_add_uint (node, "appns_index",
12009                             clib_net_to_host_u32 (mp->appns_index));
12010   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
12011   vat_json_object_add_uint (node, "scope", mp->scope);
12012   vat_json_object_add_uint (node, "action_index",
12013                             clib_net_to_host_u32 (mp->action_index));
12014   vat_json_object_add_uint (node, "lcl_port",
12015                             clib_net_to_host_u16 (mp->lcl_port));
12016   vat_json_object_add_uint (node, "rmt_port",
12017                             clib_net_to_host_u16 (mp->rmt_port));
12018   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
12019   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
12020   vat_json_object_add_string_copy (node, "tag", mp->tag);
12021   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
12022     {
12023       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
12024       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
12025       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
12026       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
12027     }
12028   else
12029     {
12030       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
12031       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
12032       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
12033       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
12034     }
12035 }
12036
12037 static int
12038 api_session_rule_add_del (vat_main_t * vam)
12039 {
12040   vl_api_session_rule_add_del_t *mp;
12041   unformat_input_t *i = vam->input;
12042   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
12043   u32 appns_index = 0, scope = 0;
12044   ip4_address_t lcl_ip4, rmt_ip4;
12045   ip6_address_t lcl_ip6, rmt_ip6;
12046   u8 is_ip4 = 1, conn_set = 0;
12047   u8 is_add = 1, *tag = 0;
12048   int ret;
12049   fib_prefix_t lcl, rmt;
12050
12051   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12052     {
12053       if (unformat (i, "del"))
12054         is_add = 0;
12055       else if (unformat (i, "add"))
12056         ;
12057       else if (unformat (i, "proto tcp"))
12058         proto = 0;
12059       else if (unformat (i, "proto udp"))
12060         proto = 1;
12061       else if (unformat (i, "appns %d", &appns_index))
12062         ;
12063       else if (unformat (i, "scope %d", &scope))
12064         ;
12065       else if (unformat (i, "tag %_%v%_", &tag))
12066         ;
12067       else
12068         if (unformat
12069             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
12070              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
12071              &rmt_port))
12072         {
12073           is_ip4 = 1;
12074           conn_set = 1;
12075         }
12076       else
12077         if (unformat
12078             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
12079              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
12080              &rmt_port))
12081         {
12082           is_ip4 = 0;
12083           conn_set = 1;
12084         }
12085       else if (unformat (i, "action %d", &action))
12086         ;
12087       else
12088         break;
12089     }
12090   if (proto == ~0 || !conn_set || action == ~0)
12091     {
12092       errmsg ("transport proto, connection and action must be set");
12093       return -99;
12094     }
12095
12096   if (scope > 3)
12097     {
12098       errmsg ("scope should be 0-3");
12099       return -99;
12100     }
12101
12102   M (SESSION_RULE_ADD_DEL, mp);
12103
12104   clib_memset (&lcl, 0, sizeof (lcl));
12105   clib_memset (&rmt, 0, sizeof (rmt));
12106   if (is_ip4)
12107     {
12108       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
12109       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
12110       lcl.fp_len = lcl_plen;
12111       rmt.fp_len = rmt_plen;
12112     }
12113   else
12114     {
12115       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
12116       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
12117       lcl.fp_len = lcl_plen;
12118       rmt.fp_len = rmt_plen;
12119     }
12120
12121
12122   ip_prefix_encode (&lcl, &mp->lcl);
12123   ip_prefix_encode (&rmt, &mp->rmt);
12124   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
12125   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
12126   mp->transport_proto =
12127     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
12128   mp->action_index = clib_host_to_net_u32 (action);
12129   mp->appns_index = clib_host_to_net_u32 (appns_index);
12130   mp->scope = scope;
12131   mp->is_add = is_add;
12132   if (tag)
12133     {
12134       clib_memcpy (mp->tag, tag, vec_len (tag));
12135       vec_free (tag);
12136     }
12137
12138   S (mp);
12139   W (ret);
12140   return ret;
12141 }
12142
12143 static int
12144 api_session_rules_dump (vat_main_t * vam)
12145 {
12146   vl_api_session_rules_dump_t *mp;
12147   vl_api_control_ping_t *mp_ping;
12148   int ret;
12149
12150   if (!vam->json_output)
12151     {
12152       print (vam->ofp, "%=20s", "Session Rules");
12153     }
12154
12155   M (SESSION_RULES_DUMP, mp);
12156   /* send it... */
12157   S (mp);
12158
12159   /* Use a control ping for synchronization */
12160   MPING (CONTROL_PING, mp_ping);
12161   S (mp_ping);
12162
12163   /* Wait for a reply... */
12164   W (ret);
12165   return ret;
12166 }
12167
12168 static int
12169 api_ip_container_proxy_add_del (vat_main_t * vam)
12170 {
12171   vl_api_ip_container_proxy_add_del_t *mp;
12172   unformat_input_t *i = vam->input;
12173   u32 sw_if_index = ~0;
12174   vl_api_prefix_t pfx = { };
12175   u8 is_add = 1;
12176   int ret;
12177
12178   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12179     {
12180       if (unformat (i, "del"))
12181         is_add = 0;
12182       else if (unformat (i, "add"))
12183         ;
12184       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
12185         ;
12186       else if (unformat (i, "sw_if_index %u", &sw_if_index))
12187         ;
12188       else
12189         break;
12190     }
12191   if (sw_if_index == ~0 || pfx.len == 0)
12192     {
12193       errmsg ("address and sw_if_index must be set");
12194       return -99;
12195     }
12196
12197   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
12198
12199   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
12200   mp->is_add = is_add;
12201   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
12202
12203   S (mp);
12204   W (ret);
12205   return ret;
12206 }
12207
12208 static int
12209 api_qos_record_enable_disable (vat_main_t * vam)
12210 {
12211   unformat_input_t *i = vam->input;
12212   vl_api_qos_record_enable_disable_t *mp;
12213   u32 sw_if_index, qs = 0xff;
12214   u8 sw_if_index_set = 0;
12215   u8 enable = 1;
12216   int ret;
12217
12218   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
12219     {
12220       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
12221         sw_if_index_set = 1;
12222       else if (unformat (i, "sw_if_index %d", &sw_if_index))
12223         sw_if_index_set = 1;
12224       else if (unformat (i, "%U", unformat_qos_source, &qs))
12225         ;
12226       else if (unformat (i, "disable"))
12227         enable = 0;
12228       else
12229         {
12230           clib_warning ("parse error '%U'", format_unformat_error, i);
12231           return -99;
12232         }
12233     }
12234
12235   if (sw_if_index_set == 0)
12236     {
12237       errmsg ("missing interface name or sw_if_index");
12238       return -99;
12239     }
12240   if (qs == 0xff)
12241     {
12242       errmsg ("input location must be specified");
12243       return -99;
12244     }
12245
12246   M (QOS_RECORD_ENABLE_DISABLE, mp);
12247
12248   mp->record.sw_if_index = ntohl (sw_if_index);
12249   mp->record.input_source = qs;
12250   mp->enable = enable;
12251
12252   S (mp);
12253   W (ret);
12254   return ret;
12255 }
12256
12257
12258 static int
12259 q_or_quit (vat_main_t * vam)
12260 {
12261 #if VPP_API_TEST_BUILTIN == 0
12262   longjmp (vam->jump_buf, 1);
12263 #endif
12264   return 0;                     /* not so much */
12265 }
12266
12267 static int
12268 q (vat_main_t * vam)
12269 {
12270   return q_or_quit (vam);
12271 }
12272
12273 static int
12274 quit (vat_main_t * vam)
12275 {
12276   return q_or_quit (vam);
12277 }
12278
12279 static int
12280 comment (vat_main_t * vam)
12281 {
12282   return 0;
12283 }
12284
12285 static int
12286 elog_save (vat_main_t * vam)
12287 {
12288 #if VPP_API_TEST_BUILTIN == 0
12289   elog_main_t *em = &vam->elog_main;
12290   unformat_input_t *i = vam->input;
12291   char *file, *chroot_file;
12292   clib_error_t *error;
12293
12294   if (!unformat (i, "%s", &file))
12295     {
12296       errmsg ("expected file name, got `%U'", format_unformat_error, i);
12297       return 0;
12298     }
12299
12300   /* It's fairly hard to get "../oopsie" through unformat; just in case */
12301   if (strstr (file, "..") || index (file, '/'))
12302     {
12303       errmsg ("illegal characters in filename '%s'", file);
12304       return 0;
12305     }
12306
12307   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
12308
12309   vec_free (file);
12310
12311   errmsg ("Saving %wd of %wd events to %s",
12312           elog_n_events_in_buffer (em),
12313           elog_buffer_capacity (em), chroot_file);
12314
12315   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
12316   vec_free (chroot_file);
12317
12318   if (error)
12319     clib_error_report (error);
12320 #else
12321   errmsg ("Use the vpp event loger...");
12322 #endif
12323
12324   return 0;
12325 }
12326
12327 static int
12328 elog_setup (vat_main_t * vam)
12329 {
12330 #if VPP_API_TEST_BUILTIN == 0
12331   elog_main_t *em = &vam->elog_main;
12332   unformat_input_t *i = vam->input;
12333   u32 nevents = 128 << 10;
12334
12335   (void) unformat (i, "nevents %d", &nevents);
12336
12337   elog_init (em, nevents);
12338   vl_api_set_elog_main (em);
12339   vl_api_set_elog_trace_api_messages (1);
12340   errmsg ("Event logger initialized with %u events", nevents);
12341 #else
12342   errmsg ("Use the vpp event loger...");
12343 #endif
12344   return 0;
12345 }
12346
12347 static int
12348 elog_enable (vat_main_t * vam)
12349 {
12350 #if VPP_API_TEST_BUILTIN == 0
12351   elog_main_t *em = &vam->elog_main;
12352
12353   elog_enable_disable (em, 1 /* enable */ );
12354   vl_api_set_elog_trace_api_messages (1);
12355   errmsg ("Event logger enabled...");
12356 #else
12357   errmsg ("Use the vpp event loger...");
12358 #endif
12359   return 0;
12360 }
12361
12362 static int
12363 elog_disable (vat_main_t * vam)
12364 {
12365 #if VPP_API_TEST_BUILTIN == 0
12366   elog_main_t *em = &vam->elog_main;
12367
12368   elog_enable_disable (em, 0 /* enable */ );
12369   vl_api_set_elog_trace_api_messages (1);
12370   errmsg ("Event logger disabled...");
12371 #else
12372   errmsg ("Use the vpp event loger...");
12373 #endif
12374   return 0;
12375 }
12376
12377 static int
12378 statseg (vat_main_t * vam)
12379 {
12380   ssvm_private_t *ssvmp = &vam->stat_segment;
12381   ssvm_shared_header_t *shared_header = ssvmp->sh;
12382   vlib_counter_t **counters;
12383   u64 thread0_index1_packets;
12384   u64 thread0_index1_bytes;
12385   f64 vector_rate, input_rate;
12386   uword *p;
12387
12388   uword *counter_vector_by_name;
12389   if (vam->stat_segment_lockp == 0)
12390     {
12391       errmsg ("Stat segment not mapped...");
12392       return -99;
12393     }
12394
12395   /* look up "/if/rx for sw_if_index 1 as a test */
12396
12397   clib_spinlock_lock (vam->stat_segment_lockp);
12398
12399   counter_vector_by_name = (uword *) shared_header->opaque[1];
12400
12401   p = hash_get_mem (counter_vector_by_name, "/if/rx");
12402   if (p == 0)
12403     {
12404       clib_spinlock_unlock (vam->stat_segment_lockp);
12405       errmsg ("/if/tx not found?");
12406       return -99;
12407     }
12408
12409   /* Fish per-thread vector of combined counters from shared memory */
12410   counters = (vlib_counter_t **) p[0];
12411
12412   if (vec_len (counters[0]) < 2)
12413     {
12414       clib_spinlock_unlock (vam->stat_segment_lockp);
12415       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
12416       return -99;
12417     }
12418
12419   /* Read thread 0 sw_if_index 1 counter */
12420   thread0_index1_packets = counters[0][1].packets;
12421   thread0_index1_bytes = counters[0][1].bytes;
12422
12423   p = hash_get_mem (counter_vector_by_name, "vector_rate");
12424   if (p == 0)
12425     {
12426       clib_spinlock_unlock (vam->stat_segment_lockp);
12427       errmsg ("vector_rate not found?");
12428       return -99;
12429     }
12430
12431   vector_rate = *(f64 *) (p[0]);
12432   p = hash_get_mem (counter_vector_by_name, "input_rate");
12433   if (p == 0)
12434     {
12435       clib_spinlock_unlock (vam->stat_segment_lockp);
12436       errmsg ("input_rate not found?");
12437       return -99;
12438     }
12439   input_rate = *(f64 *) (p[0]);
12440
12441   clib_spinlock_unlock (vam->stat_segment_lockp);
12442
12443   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
12444          vector_rate, input_rate);
12445   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
12446          thread0_index1_packets, thread0_index1_bytes);
12447
12448   return 0;
12449 }
12450
12451 static int
12452 cmd_cmp (void *a1, void *a2)
12453 {
12454   u8 **c1 = a1;
12455   u8 **c2 = a2;
12456
12457   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
12458 }
12459
12460 static int
12461 help (vat_main_t * vam)
12462 {
12463   u8 **cmds = 0;
12464   u8 *name = 0;
12465   hash_pair_t *p;
12466   unformat_input_t *i = vam->input;
12467   int j;
12468
12469   if (unformat (i, "%s", &name))
12470     {
12471       uword *hs;
12472
12473       vec_add1 (name, 0);
12474
12475       hs = hash_get_mem (vam->help_by_name, name);
12476       if (hs)
12477         print (vam->ofp, "usage: %s %s", name, hs[0]);
12478       else
12479         print (vam->ofp, "No such msg / command '%s'", name);
12480       vec_free (name);
12481       return 0;
12482     }
12483
12484   print (vam->ofp, "Help is available for the following:");
12485
12486     /* *INDENT-OFF* */
12487     hash_foreach_pair (p, vam->function_by_name,
12488     ({
12489       vec_add1 (cmds, (u8 *)(p->key));
12490     }));
12491     /* *INDENT-ON* */
12492
12493   vec_sort_with_function (cmds, cmd_cmp);
12494
12495   for (j = 0; j < vec_len (cmds); j++)
12496     print (vam->ofp, "%s", cmds[j]);
12497
12498   vec_free (cmds);
12499   return 0;
12500 }
12501
12502 static int
12503 set (vat_main_t * vam)
12504 {
12505   u8 *name = 0, *value = 0;
12506   unformat_input_t *i = vam->input;
12507
12508   if (unformat (i, "%s", &name))
12509     {
12510       /* The input buffer is a vector, not a string. */
12511       value = vec_dup (i->buffer);
12512       vec_delete (value, i->index, 0);
12513       /* Almost certainly has a trailing newline */
12514       if (value[vec_len (value) - 1] == '\n')
12515         value[vec_len (value) - 1] = 0;
12516       /* Make sure it's a proper string, one way or the other */
12517       vec_add1 (value, 0);
12518       (void) clib_macro_set_value (&vam->macro_main,
12519                                    (char *) name, (char *) value);
12520     }
12521   else
12522     errmsg ("usage: set <name> <value>");
12523
12524   vec_free (name);
12525   vec_free (value);
12526   return 0;
12527 }
12528
12529 static int
12530 unset (vat_main_t * vam)
12531 {
12532   u8 *name = 0;
12533
12534   if (unformat (vam->input, "%s", &name))
12535     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
12536       errmsg ("unset: %s wasn't set", name);
12537   vec_free (name);
12538   return 0;
12539 }
12540
12541 typedef struct
12542 {
12543   u8 *name;
12544   u8 *value;
12545 } macro_sort_t;
12546
12547
12548 static int
12549 macro_sort_cmp (void *a1, void *a2)
12550 {
12551   macro_sort_t *s1 = a1;
12552   macro_sort_t *s2 = a2;
12553
12554   return strcmp ((char *) (s1->name), (char *) (s2->name));
12555 }
12556
12557 static int
12558 dump_macro_table (vat_main_t * vam)
12559 {
12560   macro_sort_t *sort_me = 0, *sm;
12561   int i;
12562   hash_pair_t *p;
12563
12564     /* *INDENT-OFF* */
12565     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
12566     ({
12567       vec_add2 (sort_me, sm, 1);
12568       sm->name = (u8 *)(p->key);
12569       sm->value = (u8 *) (p->value[0]);
12570     }));
12571     /* *INDENT-ON* */
12572
12573   vec_sort_with_function (sort_me, macro_sort_cmp);
12574
12575   if (vec_len (sort_me))
12576     print (vam->ofp, "%-15s%s", "Name", "Value");
12577   else
12578     print (vam->ofp, "The macro table is empty...");
12579
12580   for (i = 0; i < vec_len (sort_me); i++)
12581     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
12582   return 0;
12583 }
12584
12585 static int
12586 dump_node_table (vat_main_t * vam)
12587 {
12588   int i, j;
12589   vlib_node_t *node, *next_node;
12590
12591   if (vec_len (vam->graph_nodes) == 0)
12592     {
12593       print (vam->ofp, "Node table empty, issue get_node_graph...");
12594       return 0;
12595     }
12596
12597   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
12598     {
12599       node = vam->graph_nodes[0][i];
12600       print (vam->ofp, "[%d] %s", i, node->name);
12601       for (j = 0; j < vec_len (node->next_nodes); j++)
12602         {
12603           if (node->next_nodes[j] != ~0)
12604             {
12605               next_node = vam->graph_nodes[0][node->next_nodes[j]];
12606               print (vam->ofp, "  [%d] %s", j, next_node->name);
12607             }
12608         }
12609     }
12610   return 0;
12611 }
12612
12613 static int
12614 value_sort_cmp (void *a1, void *a2)
12615 {
12616   name_sort_t *n1 = a1;
12617   name_sort_t *n2 = a2;
12618
12619   if (n1->value < n2->value)
12620     return -1;
12621   if (n1->value > n2->value)
12622     return 1;
12623   return 0;
12624 }
12625
12626
12627 static int
12628 dump_msg_api_table (vat_main_t * vam)
12629 {
12630   api_main_t *am = vlibapi_get_main ();
12631   name_sort_t *nses = 0, *ns;
12632   hash_pair_t *hp;
12633   int i;
12634
12635   /* *INDENT-OFF* */
12636   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
12637   ({
12638     vec_add2 (nses, ns, 1);
12639     ns->name = (u8 *)(hp->key);
12640     ns->value = (u32) hp->value[0];
12641   }));
12642   /* *INDENT-ON* */
12643
12644   vec_sort_with_function (nses, value_sort_cmp);
12645
12646   for (i = 0; i < vec_len (nses); i++)
12647     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
12648   vec_free (nses);
12649   return 0;
12650 }
12651
12652 static int
12653 get_msg_id (vat_main_t * vam)
12654 {
12655   u8 *name_and_crc;
12656   u32 message_index;
12657
12658   if (unformat (vam->input, "%s", &name_and_crc))
12659     {
12660       message_index = vl_msg_api_get_msg_index (name_and_crc);
12661       if (message_index == ~0)
12662         {
12663           print (vam->ofp, " '%s' not found", name_and_crc);
12664           return 0;
12665         }
12666       print (vam->ofp, " '%s' has message index %d",
12667              name_and_crc, message_index);
12668       return 0;
12669     }
12670   errmsg ("name_and_crc required...");
12671   return 0;
12672 }
12673
12674 static int
12675 search_node_table (vat_main_t * vam)
12676 {
12677   unformat_input_t *line_input = vam->input;
12678   u8 *node_to_find;
12679   int j;
12680   vlib_node_t *node, *next_node;
12681   uword *p;
12682
12683   if (vam->graph_node_index_by_name == 0)
12684     {
12685       print (vam->ofp, "Node table empty, issue get_node_graph...");
12686       return 0;
12687     }
12688
12689   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
12690     {
12691       if (unformat (line_input, "%s", &node_to_find))
12692         {
12693           vec_add1 (node_to_find, 0);
12694           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
12695           if (p == 0)
12696             {
12697               print (vam->ofp, "%s not found...", node_to_find);
12698               goto out;
12699             }
12700           node = vam->graph_nodes[0][p[0]];
12701           print (vam->ofp, "[%d] %s", p[0], node->name);
12702           for (j = 0; j < vec_len (node->next_nodes); j++)
12703             {
12704               if (node->next_nodes[j] != ~0)
12705                 {
12706                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
12707                   print (vam->ofp, "  [%d] %s", j, next_node->name);
12708                 }
12709             }
12710         }
12711
12712       else
12713         {
12714           clib_warning ("parse error '%U'", format_unformat_error,
12715                         line_input);
12716           return -99;
12717         }
12718
12719     out:
12720       vec_free (node_to_find);
12721
12722     }
12723
12724   return 0;
12725 }
12726
12727
12728 static int
12729 script (vat_main_t * vam)
12730 {
12731 #if (VPP_API_TEST_BUILTIN==0)
12732   u8 *s = 0;
12733   char *save_current_file;
12734   unformat_input_t save_input;
12735   jmp_buf save_jump_buf;
12736   u32 save_line_number;
12737
12738   FILE *new_fp, *save_ifp;
12739
12740   if (unformat (vam->input, "%s", &s))
12741     {
12742       new_fp = fopen ((char *) s, "r");
12743       if (new_fp == 0)
12744         {
12745           errmsg ("Couldn't open script file %s", s);
12746           vec_free (s);
12747           return -99;
12748         }
12749     }
12750   else
12751     {
12752       errmsg ("Missing script name");
12753       return -99;
12754     }
12755
12756   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
12757   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
12758   save_ifp = vam->ifp;
12759   save_line_number = vam->input_line_number;
12760   save_current_file = (char *) vam->current_file;
12761
12762   vam->input_line_number = 0;
12763   vam->ifp = new_fp;
12764   vam->current_file = s;
12765   do_one_file (vam);
12766
12767   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
12768   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
12769   vam->ifp = save_ifp;
12770   vam->input_line_number = save_line_number;
12771   vam->current_file = (u8 *) save_current_file;
12772   vec_free (s);
12773
12774   return 0;
12775 #else
12776   clib_warning ("use the exec command...");
12777   return -99;
12778 #endif
12779 }
12780
12781 static int
12782 echo (vat_main_t * vam)
12783 {
12784   print (vam->ofp, "%v", vam->input->buffer);
12785   return 0;
12786 }
12787
12788 /* List of API message constructors, CLI names map to api_xxx */
12789 #define foreach_vpe_api_msg                                             \
12790 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
12791 _(sw_interface_dump,"")                                                 \
12792 _(sw_interface_set_flags,                                               \
12793   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
12794 _(sw_interface_add_del_address,                                         \
12795   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
12796 _(sw_interface_set_rx_mode,                                             \
12797   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
12798 _(sw_interface_set_rx_placement,                                        \
12799   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
12800 _(sw_interface_rx_placement_dump,                                       \
12801   "[<intfc> | sw_if_index <id>]")                                         \
12802 _(sw_interface_set_table,                                               \
12803   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
12804 _(sw_interface_set_mpls_enable,                                         \
12805   "<intfc> | sw_if_index [disable | dis]")                              \
12806 _(sw_interface_set_vpath,                                               \
12807   "<intfc> | sw_if_index <id> enable | disable")                        \
12808 _(sw_interface_set_l2_xconnect,                                         \
12809   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
12810   "enable | disable")                                                   \
12811 _(sw_interface_set_l2_bridge,                                           \
12812   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
12813   "[shg <split-horizon-group>] [bvi]\n"                                 \
12814   "enable | disable")                                                   \
12815 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
12816 _(bridge_domain_add_del,                                                \
12817   "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") \
12818 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
12819 _(l2fib_add_del,                                                        \
12820   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
12821 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
12822 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
12823 _(l2_flags,                                                             \
12824   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
12825 _(bridge_flags,                                                         \
12826   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
12827 _(tap_create_v2,                                                        \
12828   "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]") \
12829 _(tap_delete_v2,                                                        \
12830   "<vpp-if-name> | sw_if_index <id>")                                   \
12831 _(sw_interface_tap_v2_dump, "")                                         \
12832 _(virtio_pci_create_v2,                                                    \
12833   "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]") \
12834 _(virtio_pci_delete,                                                    \
12835   "<vpp-if-name> | sw_if_index <id>")                                   \
12836 _(sw_interface_virtio_pci_dump, "")                                     \
12837 _(bond_create,                                                          \
12838   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
12839   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
12840   "[id <if-id>]")                                                       \
12841 _(bond_create2,                                                         \
12842   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
12843   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
12844   "[id <if-id>] [gso]")                                                 \
12845 _(bond_delete,                                                          \
12846   "<vpp-if-name> | sw_if_index <id>")                                   \
12847 _(bond_add_member,                                                      \
12848   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
12849 _(bond_detach_member,                                                   \
12850   "sw_if_index <n>")                                                    \
12851  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
12852  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
12853  _(sw_member_interface_dump,                                            \
12854   "<vpp-if-name> | sw_if_index <id>")                                   \
12855 _(ip_table_add_del,                                                     \
12856   "table <n> [ipv6] [add | del]\n")                                     \
12857 _(ip_route_add_del,                                                     \
12858   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
12859   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
12860   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
12861   "[multipath] [count <n>] [del]")                                      \
12862 _(ip_mroute_add_del,                                                    \
12863   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
12864   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
12865 _(mpls_table_add_del,                                                   \
12866   "table <n> [add | del]\n")                                            \
12867 _(mpls_route_add_del,                                                   \
12868   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
12869   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
12870   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
12871   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
12872   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
12873   "[count <n>] [del]")                                                  \
12874 _(mpls_ip_bind_unbind,                                                  \
12875   "<label> <addr/len>")                                                 \
12876 _(mpls_tunnel_add_del,                                                  \
12877   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
12878   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
12879   "[l2-only]  [out-label <n>]")                                         \
12880 _(sr_mpls_policy_add,                                                   \
12881   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
12882 _(sr_mpls_policy_del,                                                   \
12883   "bsid <id>")                                                          \
12884 _(sw_interface_set_unnumbered,                                          \
12885   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
12886 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
12887 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
12888   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
12889   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
12890   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
12891 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
12892 _(ip_table_flush, "table <n> [ipv6]")                                   \
12893 _(ip_table_replace_end, "table <n> [ipv6]")                             \
12894 _(set_ip_flow_hash,                                                     \
12895   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
12896 _(sw_interface_ip6_enable_disable,                                      \
12897   "<intfc> | sw_if_index <id> enable | disable")                        \
12898 _(l2_patch_add_del,                                                     \
12899   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
12900   "enable | disable")                                                   \
12901 _(sr_localsid_add_del,                                                  \
12902   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
12903   "fib-table <num> (end.psp) sw_if_index <num>")                        \
12904 _(get_node_index, "node <node-name")                                    \
12905 _(add_node_next, "node <node-name> next <next-node-name>")              \
12906 _(l2_fib_clear_table, "")                                               \
12907 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
12908 _(l2_interface_vlan_tag_rewrite,                                        \
12909   "<intfc> | sw_if_index <nn> \n"                                       \
12910   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
12911   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
12912 _(create_vhost_user_if,                                                 \
12913         "socket <filename> [server] [renumber <dev_instance>] "         \
12914         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
12915         "[mac <mac_address>] [packed]")                                 \
12916 _(modify_vhost_user_if,                                                 \
12917         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
12918         "[server] [renumber <dev_instance>] [gso] [packed]")            \
12919 _(create_vhost_user_if_v2,                                              \
12920         "socket <filename> [server] [renumber <dev_instance>] "         \
12921         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
12922         "[mac <mac_address>] [packed] [event-idx]")                     \
12923 _(modify_vhost_user_if_v2,                                              \
12924         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
12925         "[server] [renumber <dev_instance>] [gso] [packed] [event-idx]")\
12926 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
12927 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
12928 _(show_version, "")                                                     \
12929 _(show_threads, "")                                                     \
12930 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
12931 _(interface_name_renumber,                                              \
12932   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
12933 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
12934 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
12935 _(ip_dump, "ipv4 | ipv6")                                               \
12936 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
12937 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
12938   "  spid_id <n> ")                                                     \
12939 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
12940   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
12941   "  integ_alg <alg> integ_key <hex>")                                  \
12942 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
12943   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
12944   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
12945   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
12946 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
12947 _(delete_loopback,"sw_if_index <nn>")                                   \
12948 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
12949 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
12950 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
12951 _(want_interface_events,  "enable|disable")                             \
12952 _(get_first_msg_id, "client <name>")                                    \
12953 _(get_node_graph, " ")                                                  \
12954 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
12955 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
12956 _(ioam_disable, "")                                                     \
12957 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
12958 _(af_packet_delete, "name <host interface name>")                       \
12959 _(af_packet_dump, "")                                                   \
12960 _(policer_add_del, "name <policer name> <params> [del]")                \
12961 _(policer_dump, "[name <policer name>]")                                \
12962 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
12963 _(mpls_table_dump, "")                                                  \
12964 _(mpls_route_dump, "table-id <ID>")                                     \
12965 _(set_ipfix_exporter, "collector_address <ip4> [collector_port <nn>] "  \
12966     "src_address <ip4> [vrf_id <nn>] [path_mtu <nn>] "                  \
12967     "[template_interval <nn>] [udp_checksum]")                          \
12968 _(ipfix_exporter_dump, "")                                              \
12969 _(set_ipfix_classify_stream, "[domain <domain-id>] [src_port <src-port>]") \
12970 _(ipfix_classify_stream_dump, "")                                       \
12971 _(ipfix_classify_table_add_del, "table <table-index> ip4|ip6 [tcp|udp]") \
12972 _(ipfix_classify_table_dump, "")                                        \
12973 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
12974 _(sw_interface_span_dump, "[l2]")                                           \
12975 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
12976 _(pg_create_interface, "if_id <nn> [gso-enabled gso-size <size>]")      \
12977 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
12978 _(pg_enable_disable, "[stream <id>] disable")                           \
12979 _(pg_interface_enable_disable_coalesce, "<intf> | sw_if_index <nn> enable | disable")  \
12980 _(ip_source_and_port_range_check_add_del,                               \
12981   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
12982 _(ip_source_and_port_range_check_interface_add_del,                     \
12983   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
12984   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
12985 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
12986 _(l2_interface_pbb_tag_rewrite,                                         \
12987   "<intfc> | sw_if_index <nn> \n"                                       \
12988   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
12989   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
12990 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
12991 _(ip_table_dump, "")                                                    \
12992 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
12993 _(ip_mtable_dump, "")                                                   \
12994 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
12995 _(feature_enable_disable, "arc_name <arc_name> "                        \
12996   "feature_name <feature_name> <intfc> | sw_if_index <nn> [disable]")   \
12997 _(feature_gso_enable_disable, "<intfc> | sw_if_index <nn> "             \
12998   "[enable | disable] ")                                                \
12999 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
13000 "[disable]")                                                            \
13001 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
13002   "mac <mac-address> [del]")                                            \
13003 _(l2_xconnect_dump, "")                                                 \
13004 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
13005 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
13006 _(p2p_ethernet_add, "<intfc> | sw_if_index <nn> remote_mac <mac-address> sub_id <id>") \
13007 _(p2p_ethernet_del, "<intfc> | sw_if_index <nn> remote_mac <mac-address>") \
13008 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
13009 _(sock_init_shm, "size <nnn>")                                          \
13010 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
13011 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
13012   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
13013 _(session_rules_dump, "")                                               \
13014 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
13015 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
13016
13017 /* List of command functions, CLI names map directly to functions */
13018 #define foreach_cli_function                                    \
13019 _(comment, "usage: comment <ignore-rest-of-line>")              \
13020 _(dump_interface_table, "usage: dump_interface_table")          \
13021 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
13022 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
13023 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
13024 _(dump_macro_table, "usage: dump_macro_table ")                 \
13025 _(dump_node_table, "usage: dump_node_table")                    \
13026 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
13027 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
13028 _(elog_disable, "usage: elog_disable")                          \
13029 _(elog_enable, "usage: elog_enable")                            \
13030 _(elog_save, "usage: elog_save <filename>")                     \
13031 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
13032 _(echo, "usage: echo <message>")                                \
13033 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
13034 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
13035 _(help, "usage: help")                                          \
13036 _(q, "usage: quit")                                             \
13037 _(quit, "usage: quit")                                          \
13038 _(search_node_table, "usage: search_node_table <name>...")      \
13039 _(set, "usage: set <variable-name> <value>")                    \
13040 _(script, "usage: script <file-name>")                          \
13041 _(statseg, "usage: statseg")                                    \
13042 _(unset, "usage: unset <variable-name>")
13043
13044 #define _(N,n)                                  \
13045     static void vl_api_##n##_t_handler_uni      \
13046     (vl_api_##n##_t * mp)                       \
13047     {                                           \
13048         vat_main_t * vam = &vat_main;           \
13049         if (vam->json_output) {                 \
13050             vl_api_##n##_t_handler_json(mp);    \
13051         } else {                                \
13052             vl_api_##n##_t_handler(mp);         \
13053         }                                       \
13054     }
13055 foreach_vpe_api_reply_msg;
13056 #if VPP_API_TEST_BUILTIN == 0
13057 foreach_standalone_reply_msg;
13058 #endif
13059 #undef _
13060
13061 void
13062 vat_api_hookup (vat_main_t * vam)
13063 {
13064 #define _(N,n)                                                  \
13065     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
13066                            vl_api_##n##_t_handler_uni,          \
13067                            vl_noop_handler,                     \
13068                            vl_api_##n##_t_endian,               \
13069                            vl_api_##n##_t_print,                \
13070                            sizeof(vl_api_##n##_t), 1);
13071   foreach_vpe_api_reply_msg;
13072 #if VPP_API_TEST_BUILTIN == 0
13073   foreach_standalone_reply_msg;
13074 #endif
13075 #undef _
13076
13077 #if (VPP_API_TEST_BUILTIN==0)
13078   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
13079
13080   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
13081
13082   vam->function_by_name = hash_create_string (0, sizeof (uword));
13083
13084   vam->help_by_name = hash_create_string (0, sizeof (uword));
13085 #endif
13086
13087   /* API messages we can send */
13088 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
13089   foreach_vpe_api_msg;
13090 #undef _
13091
13092   /* Help strings */
13093 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
13094   foreach_vpe_api_msg;
13095 #undef _
13096
13097   /* CLI functions */
13098 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
13099   foreach_cli_function;
13100 #undef _
13101
13102   /* Help strings */
13103 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
13104   foreach_cli_function;
13105 #undef _
13106 }
13107
13108 #if VPP_API_TEST_BUILTIN
13109 static clib_error_t *
13110 vat_api_hookup_shim (vlib_main_t * vm)
13111 {
13112   vat_api_hookup (&vat_main);
13113   return 0;
13114 }
13115
13116 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
13117 #endif
13118
13119 /*
13120  * fd.io coding-style-patch-verification: ON
13121  *
13122  * Local Variables:
13123  * eval: (c-set-style "gnu")
13124  * End:
13125  */