feature: 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 /*
2762  * Generate boilerplate reply handlers, which
2763  * dig the return value out of the xxx_reply_t API message,
2764  * stick it into vam->retval, and set vam->result_ready
2765  *
2766  * Could also do this by pointing N message decode slots at
2767  * a single function, but that could break in subtle ways.
2768  */
2769
2770 #define foreach_standard_reply_retval_handler           \
2771 _(sw_interface_set_flags_reply)                         \
2772 _(sw_interface_add_del_address_reply)                   \
2773 _(sw_interface_set_rx_mode_reply)                       \
2774 _(sw_interface_set_rx_placement_reply)                  \
2775 _(sw_interface_set_table_reply)                         \
2776 _(sw_interface_set_mpls_enable_reply)                   \
2777 _(sw_interface_set_vpath_reply)                         \
2778 _(sw_interface_set_l2_bridge_reply)                     \
2779 _(sw_interface_set_bond_weight_reply)                   \
2780 _(bridge_domain_add_del_reply)                          \
2781 _(sw_interface_set_l2_xconnect_reply)                   \
2782 _(l2fib_add_del_reply)                                  \
2783 _(l2fib_flush_int_reply)                                \
2784 _(l2fib_flush_bd_reply)                                 \
2785 _(ip_route_add_del_reply)                               \
2786 _(ip_table_add_del_reply)                               \
2787 _(ip_table_replace_begin_reply)                         \
2788 _(ip_table_flush_reply)                                 \
2789 _(ip_table_replace_end_reply)                           \
2790 _(ip_mroute_add_del_reply)                              \
2791 _(mpls_route_add_del_reply)                             \
2792 _(mpls_table_add_del_reply)                             \
2793 _(mpls_ip_bind_unbind_reply)                            \
2794 _(sw_interface_set_unnumbered_reply)                    \
2795 _(set_ip_flow_hash_reply)                               \
2796 _(sw_interface_ip6_enable_disable_reply)                \
2797 _(l2_patch_add_del_reply)                               \
2798 _(sr_mpls_policy_add_reply)                             \
2799 _(sr_mpls_policy_mod_reply)                             \
2800 _(sr_mpls_policy_del_reply)                             \
2801 _(sr_policy_add_reply)                                  \
2802 _(sr_policy_mod_reply)                                  \
2803 _(sr_policy_del_reply)                                  \
2804 _(sr_localsid_add_del_reply)                            \
2805 _(sr_steering_add_del_reply)                            \
2806 _(l2_fib_clear_table_reply)                             \
2807 _(l2_interface_efp_filter_reply)                        \
2808 _(l2_interface_vlan_tag_rewrite_reply)                  \
2809 _(modify_vhost_user_if_reply)                           \
2810 _(modify_vhost_user_if_v2_reply)                        \
2811 _(delete_vhost_user_if_reply)                           \
2812 _(want_l2_macs_events_reply)                            \
2813 _(ipsec_spd_add_del_reply)                              \
2814 _(ipsec_interface_add_del_spd_reply)                    \
2815 _(ipsec_spd_entry_add_del_reply)                        \
2816 _(ipsec_sad_entry_add_del_reply)                        \
2817 _(delete_loopback_reply)                                \
2818 _(bd_ip_mac_add_del_reply)                              \
2819 _(bd_ip_mac_flush_reply)                                \
2820 _(want_interface_events_reply)                          \
2821 _(sw_interface_clear_stats_reply)                       \
2822 _(ioam_enable_reply)                                    \
2823 _(ioam_disable_reply)                                   \
2824 _(af_packet_delete_reply)                               \
2825 _(sw_interface_span_enable_disable_reply)               \
2826 _(ip_source_and_port_range_check_add_del_reply)         \
2827 _(ip_source_and_port_range_check_interface_add_del_reply)\
2828 _(delete_subif_reply)                                   \
2829 _(l2_interface_pbb_tag_rewrite_reply)                   \
2830 _(set_punt_reply)                                       \
2831 _(sw_interface_tag_add_del_reply)                       \
2832 _(sw_interface_add_del_mac_address_reply)               \
2833 _(hw_interface_set_mtu_reply)                           \
2834 _(p2p_ethernet_add_reply)                               \
2835 _(p2p_ethernet_del_reply)                               \
2836 _(tcp_configure_src_addresses_reply)                    \
2837 _(session_rule_add_del_reply)                           \
2838 _(ip_container_proxy_add_del_reply)                     \
2839 _(qos_record_enable_disable_reply)                      \
2840
2841 #define _(n)                                    \
2842     static void vl_api_##n##_t_handler          \
2843     (vl_api_##n##_t * mp)                       \
2844     {                                           \
2845         vat_main_t * vam = &vat_main;           \
2846         i32 retval = ntohl(mp->retval);         \
2847         if (vam->async_mode) {                  \
2848             vam->async_errors += (retval < 0);  \
2849         } else {                                \
2850             vam->retval = retval;               \
2851             vam->result_ready = 1;              \
2852         }                                       \
2853     }
2854 foreach_standard_reply_retval_handler;
2855 #undef _
2856
2857 #define _(n)                                    \
2858     static void vl_api_##n##_t_handler_json     \
2859     (vl_api_##n##_t * mp)                       \
2860     {                                           \
2861         vat_main_t * vam = &vat_main;           \
2862         vat_json_node_t node;                   \
2863         vat_json_init_object(&node);            \
2864         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
2865         vat_json_print(vam->ofp, &node);        \
2866         vam->retval = ntohl(mp->retval);        \
2867         vam->result_ready = 1;                  \
2868     }
2869 foreach_standard_reply_retval_handler;
2870 #undef _
2871
2872 /*
2873  * Table of message reply handlers, must include boilerplate handlers
2874  * we just generated
2875  */
2876
2877 #define foreach_vpe_api_reply_msg                                       \
2878 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
2879 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
2880 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
2881 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
2882 _(CONTROL_PING_REPLY, control_ping_reply)                               \
2883 _(CLI_REPLY, cli_reply)                                                 \
2884 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
2885 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
2886   sw_interface_add_del_address_reply)                                   \
2887 _(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply)       \
2888 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
2889 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
2890 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
2891 _(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \
2892 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
2893 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
2894   sw_interface_set_l2_xconnect_reply)                                   \
2895 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
2896   sw_interface_set_l2_bridge_reply)                                     \
2897 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
2898 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
2899 _(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply)     \
2900 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
2901 _(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply)                         \
2902 _(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply)                           \
2903 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
2904 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
2905 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                             \
2906 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                             \
2907 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
2908 _(VIRTIO_PCI_CREATE_REPLY, virtio_pci_create_reply)                     \
2909 _(VIRTIO_PCI_CREATE_V2_REPLY, virtio_pci_create_v2_reply)               \
2910 _(VIRTIO_PCI_DELETE_REPLY, virtio_pci_delete_reply)                     \
2911 _(SW_INTERFACE_VIRTIO_PCI_DETAILS, sw_interface_virtio_pci_details)     \
2912 _(BOND_CREATE_REPLY, bond_create_reply)                                 \
2913 _(BOND_CREATE2_REPLY, bond_create2_reply)                               \
2914 _(BOND_DELETE_REPLY, bond_delete_reply)                                 \
2915 _(BOND_ADD_MEMBER_REPLY, bond_add_member_reply)                         \
2916 _(BOND_DETACH_MEMBER_REPLY, bond_detach_member_reply)                   \
2917 _(SW_INTERFACE_SET_BOND_WEIGHT_REPLY, sw_interface_set_bond_weight_reply) \
2918 _(SW_BOND_INTERFACE_DETAILS, sw_bond_interface_details)                 \
2919 _(SW_MEMBER_INTERFACE_DETAILS, sw_member_interface_details)               \
2920 _(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply)                       \
2921 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                       \
2922 _(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply)           \
2923 _(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply)                           \
2924 _(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply)               \
2925 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                     \
2926 _(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply)                   \
2927 _(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply)                   \
2928 _(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply)                 \
2929 _(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply)                 \
2930 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
2931   sw_interface_set_unnumbered_reply)                                    \
2932 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
2933 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
2934 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
2935 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
2936   sw_interface_ip6_enable_disable_reply)                                \
2937 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
2938 _(SR_MPLS_POLICY_ADD_REPLY, sr_mpls_policy_add_reply)                   \
2939 _(SR_MPLS_POLICY_MOD_REPLY, sr_mpls_policy_mod_reply)                   \
2940 _(SR_MPLS_POLICY_DEL_REPLY, sr_mpls_policy_del_reply)                   \
2941 _(SR_POLICY_ADD_REPLY, sr_policy_add_reply)                             \
2942 _(SR_POLICY_MOD_REPLY, sr_policy_mod_reply)                             \
2943 _(SR_POLICY_DEL_REPLY, sr_policy_del_reply)                             \
2944 _(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply)                 \
2945 _(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply)                 \
2946 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
2947 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
2948 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
2949 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
2950 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
2951 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
2952 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
2953 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
2954 _(CREATE_VHOST_USER_IF_V2_REPLY, create_vhost_user_if_v2_reply)         \
2955 _(MODIFY_VHOST_USER_IF_V2_REPLY, modify_vhost_user_if_v2_reply)         \
2956 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
2957 _(SHOW_VERSION_REPLY, show_version_reply)                               \
2958 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
2959 _(L2_FIB_TABLE_DETAILS, l2_fib_table_details)                           \
2960 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
2961 _(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply)                 \
2962 _(L2_MACS_EVENT, l2_macs_event)                                         \
2963 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
2964 _(IP_DETAILS, ip_details)                                               \
2965 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
2966 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
2967 _(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
2968 _(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
2969 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
2970 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
2971 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
2972 _(BD_IP_MAC_FLUSH_REPLY, bd_ip_mac_flush_reply)                         \
2973 _(BD_IP_MAC_DETAILS, bd_ip_mac_details)                                 \
2974 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
2975 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
2976 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
2977 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
2978 _(IOAM_ENABLE_REPLY, ioam_enable_reply)                   \
2979 _(IOAM_DISABLE_REPLY, ioam_disable_reply)                     \
2980 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
2981 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
2982 _(AF_PACKET_DETAILS, af_packet_details)                                 \
2983 _(POLICER_ADD_DEL_REPLY, policer_add_del_reply)                         \
2984 _(POLICER_DETAILS, policer_details)                                     \
2985 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
2986 _(MPLS_TABLE_DETAILS, mpls_table_details)                               \
2987 _(MPLS_ROUTE_DETAILS, mpls_route_details)                               \
2988 _(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \
2989 _(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details)                 \
2990 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
2991 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
2992  ip_source_and_port_range_check_add_del_reply)                          \
2993 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
2994  ip_source_and_port_range_check_interface_add_del_reply)                \
2995 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
2996 _(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \
2997 _(SET_PUNT_REPLY, set_punt_reply)                                       \
2998 _(IP_TABLE_DETAILS, ip_table_details)                                   \
2999 _(IP_ROUTE_DETAILS, ip_route_details)                                   \
3000 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
3001 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
3002 _(L2_XCONNECT_DETAILS, l2_xconnect_details)                             \
3003 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
3004 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
3005 _(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply)                       \
3006 _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply)                       \
3007 _(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
3008 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
3009 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
3010 _(SESSION_RULES_DETAILS, session_rules_details)                         \
3011 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)   \
3012 _(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply)             \
3013
3014 #define foreach_standalone_reply_msg                                    \
3015 _(SW_INTERFACE_EVENT, sw_interface_event)
3016
3017 typedef struct
3018 {
3019   u8 *name;
3020   u32 value;
3021 } name_sort_t;
3022
3023 #define STR_VTR_OP_CASE(op)     \
3024     case L2_VTR_ ## op:         \
3025         return "" # op;
3026
3027 static const char *
3028 str_vtr_op (u32 vtr_op)
3029 {
3030   switch (vtr_op)
3031     {
3032       STR_VTR_OP_CASE (DISABLED);
3033       STR_VTR_OP_CASE (PUSH_1);
3034       STR_VTR_OP_CASE (PUSH_2);
3035       STR_VTR_OP_CASE (POP_1);
3036       STR_VTR_OP_CASE (POP_2);
3037       STR_VTR_OP_CASE (TRANSLATE_1_1);
3038       STR_VTR_OP_CASE (TRANSLATE_1_2);
3039       STR_VTR_OP_CASE (TRANSLATE_2_1);
3040       STR_VTR_OP_CASE (TRANSLATE_2_2);
3041     }
3042
3043   return "UNKNOWN";
3044 }
3045
3046 static int
3047 dump_sub_interface_table (vat_main_t * vam)
3048 {
3049   const sw_interface_subif_t *sub = NULL;
3050
3051   if (vam->json_output)
3052     {
3053       clib_warning
3054         ("JSON output supported only for VPE API calls and dump_stats_table");
3055       return -99;
3056     }
3057
3058   print (vam->ofp,
3059          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
3060          "Interface", "sw_if_index",
3061          "sub id", "dot1ad", "tags", "outer id",
3062          "inner id", "exact", "default", "outer any", "inner any");
3063
3064   vec_foreach (sub, vam->sw_if_subif_table)
3065   {
3066     print (vam->ofp,
3067            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
3068            sub->interface_name,
3069            sub->sw_if_index,
3070            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
3071            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
3072            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
3073            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
3074     if (sub->vtr_op != L2_VTR_DISABLED)
3075       {
3076         print (vam->ofp,
3077                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
3078                "tag1: %d tag2: %d ]",
3079                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
3080                sub->vtr_tag1, sub->vtr_tag2);
3081       }
3082   }
3083
3084   return 0;
3085 }
3086
3087 static int
3088 name_sort_cmp (void *a1, void *a2)
3089 {
3090   name_sort_t *n1 = a1;
3091   name_sort_t *n2 = a2;
3092
3093   return strcmp ((char *) n1->name, (char *) n2->name);
3094 }
3095
3096 static int
3097 dump_interface_table (vat_main_t * vam)
3098 {
3099   hash_pair_t *p;
3100   name_sort_t *nses = 0, *ns;
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   /* *INDENT-OFF* */
3110   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3111   ({
3112     vec_add2 (nses, ns, 1);
3113     ns->name = (u8 *)(p->key);
3114     ns->value = (u32) p->value[0];
3115   }));
3116   /* *INDENT-ON* */
3117
3118   vec_sort_with_function (nses, name_sort_cmp);
3119
3120   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
3121   vec_foreach (ns, nses)
3122   {
3123     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
3124   }
3125   vec_free (nses);
3126   return 0;
3127 }
3128
3129 static int
3130 dump_ip_table (vat_main_t * vam, int is_ipv6)
3131 {
3132   const ip_details_t *det = NULL;
3133   const ip_address_details_t *address = NULL;
3134   u32 i = ~0;
3135
3136   print (vam->ofp, "%-12s", "sw_if_index");
3137
3138   vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
3139   {
3140     i++;
3141     if (!det->present)
3142       {
3143         continue;
3144       }
3145     print (vam->ofp, "%-12d", i);
3146     print (vam->ofp, "            %-30s%-13s", "Address", "Prefix length");
3147     if (!det->addr)
3148       {
3149         continue;
3150       }
3151     vec_foreach (address, det->addr)
3152     {
3153       print (vam->ofp,
3154              "            %-30U%-13d",
3155              is_ipv6 ? format_ip6_address : format_ip4_address,
3156              address->ip, address->prefix_length);
3157     }
3158   }
3159
3160   return 0;
3161 }
3162
3163 static int
3164 dump_ipv4_table (vat_main_t * vam)
3165 {
3166   if (vam->json_output)
3167     {
3168       clib_warning
3169         ("JSON output supported only for VPE API calls and dump_stats_table");
3170       return -99;
3171     }
3172
3173   return dump_ip_table (vam, 0);
3174 }
3175
3176 static int
3177 dump_ipv6_table (vat_main_t * vam)
3178 {
3179   if (vam->json_output)
3180     {
3181       clib_warning
3182         ("JSON output supported only for VPE API calls and dump_stats_table");
3183       return -99;
3184     }
3185
3186   return dump_ip_table (vam, 1);
3187 }
3188
3189 /*
3190  * Pass CLI buffers directly in the CLI_INBAND API message,
3191  * instead of an additional shared memory area.
3192  */
3193 static int
3194 exec_inband (vat_main_t * vam)
3195 {
3196   vl_api_cli_inband_t *mp;
3197   unformat_input_t *i = vam->input;
3198   int ret;
3199
3200   if (vec_len (i->buffer) == 0)
3201     return -1;
3202
3203   if (vam->exec_mode == 0 && unformat (i, "mode"))
3204     {
3205       vam->exec_mode = 1;
3206       return 0;
3207     }
3208   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
3209     {
3210       vam->exec_mode = 0;
3211       return 0;
3212     }
3213
3214   /*
3215    * In order for the CLI command to work, it
3216    * must be a vector ending in \n, not a C-string ending
3217    * in \n\0.
3218    */
3219   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
3220   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
3221
3222   S (mp);
3223   W (ret);
3224   /* json responses may or may not include a useful reply... */
3225   if (vec_len (vam->cmd_reply))
3226     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
3227   return ret;
3228 }
3229
3230 int
3231 exec (vat_main_t * vam)
3232 {
3233   return exec_inband (vam);
3234 }
3235
3236 static int
3237 api_create_loopback (vat_main_t * vam)
3238 {
3239   unformat_input_t *i = vam->input;
3240   vl_api_create_loopback_t *mp;
3241   vl_api_create_loopback_instance_t *mp_lbi;
3242   u8 mac_address[6];
3243   u8 mac_set = 0;
3244   u8 is_specified = 0;
3245   u32 user_instance = 0;
3246   int ret;
3247
3248   clib_memset (mac_address, 0, sizeof (mac_address));
3249
3250   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3251     {
3252       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
3253         mac_set = 1;
3254       if (unformat (i, "instance %d", &user_instance))
3255         is_specified = 1;
3256       else
3257         break;
3258     }
3259
3260   if (is_specified)
3261     {
3262       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
3263       mp_lbi->is_specified = is_specified;
3264       if (is_specified)
3265         mp_lbi->user_instance = htonl (user_instance);
3266       if (mac_set)
3267         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
3268       S (mp_lbi);
3269     }
3270   else
3271     {
3272       /* Construct the API message */
3273       M (CREATE_LOOPBACK, mp);
3274       if (mac_set)
3275         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
3276       S (mp);
3277     }
3278
3279   W (ret);
3280   return ret;
3281 }
3282
3283 static int
3284 api_delete_loopback (vat_main_t * vam)
3285 {
3286   unformat_input_t *i = vam->input;
3287   vl_api_delete_loopback_t *mp;
3288   u32 sw_if_index = ~0;
3289   int ret;
3290
3291   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3292     {
3293       if (unformat (i, "sw_if_index %d", &sw_if_index))
3294         ;
3295       else
3296         break;
3297     }
3298
3299   if (sw_if_index == ~0)
3300     {
3301       errmsg ("missing sw_if_index");
3302       return -99;
3303     }
3304
3305   /* Construct the API message */
3306   M (DELETE_LOOPBACK, mp);
3307   mp->sw_if_index = ntohl (sw_if_index);
3308
3309   S (mp);
3310   W (ret);
3311   return ret;
3312 }
3313
3314 static int
3315 api_want_interface_events (vat_main_t * vam)
3316 {
3317   unformat_input_t *i = vam->input;
3318   vl_api_want_interface_events_t *mp;
3319   int enable = -1;
3320   int ret;
3321
3322   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3323     {
3324       if (unformat (i, "enable"))
3325         enable = 1;
3326       else if (unformat (i, "disable"))
3327         enable = 0;
3328       else
3329         break;
3330     }
3331
3332   if (enable == -1)
3333     {
3334       errmsg ("missing enable|disable");
3335       return -99;
3336     }
3337
3338   M (WANT_INTERFACE_EVENTS, mp);
3339   mp->enable_disable = enable;
3340
3341   vam->interface_event_display = enable;
3342
3343   S (mp);
3344   W (ret);
3345   return ret;
3346 }
3347
3348
3349 /* Note: non-static, called once to set up the initial intfc table */
3350 int
3351 api_sw_interface_dump (vat_main_t * vam)
3352 {
3353   vl_api_sw_interface_dump_t *mp;
3354   vl_api_control_ping_t *mp_ping;
3355   hash_pair_t *p;
3356   name_sort_t *nses = 0, *ns;
3357   sw_interface_subif_t *sub = NULL;
3358   int ret;
3359
3360   /* Toss the old name table */
3361   /* *INDENT-OFF* */
3362   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3363   ({
3364     vec_add2 (nses, ns, 1);
3365     ns->name = (u8 *)(p->key);
3366     ns->value = (u32) p->value[0];
3367   }));
3368   /* *INDENT-ON* */
3369
3370   hash_free (vam->sw_if_index_by_interface_name);
3371
3372   vec_foreach (ns, nses) vec_free (ns->name);
3373
3374   vec_free (nses);
3375
3376   vec_foreach (sub, vam->sw_if_subif_table)
3377   {
3378     vec_free (sub->interface_name);
3379   }
3380   vec_free (vam->sw_if_subif_table);
3381
3382   /* recreate the interface name hash table */
3383   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3384
3385   /*
3386    * Ask for all interface names. Otherwise, the epic catalog of
3387    * name filters becomes ridiculously long, and vat ends up needing
3388    * to be taught about new interface types.
3389    */
3390   M (SW_INTERFACE_DUMP, mp);
3391   S (mp);
3392
3393   /* Use a control ping for synchronization */
3394   MPING (CONTROL_PING, mp_ping);
3395   S (mp_ping);
3396
3397   W (ret);
3398   return ret;
3399 }
3400
3401 static int
3402 api_sw_interface_set_flags (vat_main_t * vam)
3403 {
3404   unformat_input_t *i = vam->input;
3405   vl_api_sw_interface_set_flags_t *mp;
3406   u32 sw_if_index;
3407   u8 sw_if_index_set = 0;
3408   u8 admin_up = 0;
3409   int ret;
3410
3411   /* Parse args required to build the message */
3412   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3413     {
3414       if (unformat (i, "admin-up"))
3415         admin_up = 1;
3416       else if (unformat (i, "admin-down"))
3417         admin_up = 0;
3418       else
3419         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3420         sw_if_index_set = 1;
3421       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3422         sw_if_index_set = 1;
3423       else
3424         break;
3425     }
3426
3427   if (sw_if_index_set == 0)
3428     {
3429       errmsg ("missing interface name or sw_if_index");
3430       return -99;
3431     }
3432
3433   /* Construct the API message */
3434   M (SW_INTERFACE_SET_FLAGS, mp);
3435   mp->sw_if_index = ntohl (sw_if_index);
3436   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
3437
3438   /* send it... */
3439   S (mp);
3440
3441   /* Wait for a reply, return the good/bad news... */
3442   W (ret);
3443   return ret;
3444 }
3445
3446 static int
3447 api_sw_interface_set_rx_mode (vat_main_t * vam)
3448 {
3449   unformat_input_t *i = vam->input;
3450   vl_api_sw_interface_set_rx_mode_t *mp;
3451   u32 sw_if_index;
3452   u8 sw_if_index_set = 0;
3453   int ret;
3454   u8 queue_id_valid = 0;
3455   u32 queue_id;
3456   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
3457
3458   /* Parse args required to build the message */
3459   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3460     {
3461       if (unformat (i, "queue %d", &queue_id))
3462         queue_id_valid = 1;
3463       else if (unformat (i, "polling"))
3464         mode = VNET_HW_IF_RX_MODE_POLLING;
3465       else if (unformat (i, "interrupt"))
3466         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
3467       else if (unformat (i, "adaptive"))
3468         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
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   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
3484     {
3485       errmsg ("missing rx-mode");
3486       return -99;
3487     }
3488
3489   /* Construct the API message */
3490   M (SW_INTERFACE_SET_RX_MODE, mp);
3491   mp->sw_if_index = ntohl (sw_if_index);
3492   mp->mode = (vl_api_rx_mode_t) mode;
3493   mp->queue_id_valid = queue_id_valid;
3494   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
3495
3496   /* send it... */
3497   S (mp);
3498
3499   /* Wait for a reply, return the good/bad news... */
3500   W (ret);
3501   return ret;
3502 }
3503
3504 static int
3505 api_sw_interface_set_rx_placement (vat_main_t * vam)
3506 {
3507   unformat_input_t *i = vam->input;
3508   vl_api_sw_interface_set_rx_placement_t *mp;
3509   u32 sw_if_index;
3510   u8 sw_if_index_set = 0;
3511   int ret;
3512   u8 is_main = 0;
3513   u32 queue_id, thread_index;
3514
3515   /* Parse args required to build the message */
3516   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3517     {
3518       if (unformat (i, "queue %d", &queue_id))
3519         ;
3520       else if (unformat (i, "main"))
3521         is_main = 1;
3522       else if (unformat (i, "worker %d", &thread_index))
3523         ;
3524       else
3525         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3526         sw_if_index_set = 1;
3527       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3528         sw_if_index_set = 1;
3529       else
3530         break;
3531     }
3532
3533   if (sw_if_index_set == 0)
3534     {
3535       errmsg ("missing interface name or sw_if_index");
3536       return -99;
3537     }
3538
3539   if (is_main)
3540     thread_index = 0;
3541   /* Construct the API message */
3542   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
3543   mp->sw_if_index = ntohl (sw_if_index);
3544   mp->worker_id = ntohl (thread_index);
3545   mp->queue_id = ntohl (queue_id);
3546   mp->is_main = is_main;
3547
3548   /* send it... */
3549   S (mp);
3550   /* Wait for a reply, return the good/bad news... */
3551   W (ret);
3552   return ret;
3553 }
3554
3555 static void vl_api_sw_interface_rx_placement_details_t_handler
3556   (vl_api_sw_interface_rx_placement_details_t * mp)
3557 {
3558   vat_main_t *vam = &vat_main;
3559   u32 worker_id = ntohl (mp->worker_id);
3560
3561   print (vam->ofp,
3562          "\n%-11d %-11s %-6d %-5d %-9s",
3563          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
3564          worker_id, ntohl (mp->queue_id),
3565          (mp->mode ==
3566           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
3567 }
3568
3569 static void vl_api_sw_interface_rx_placement_details_t_handler_json
3570   (vl_api_sw_interface_rx_placement_details_t * mp)
3571 {
3572   vat_main_t *vam = &vat_main;
3573   vat_json_node_t *node = NULL;
3574
3575   if (VAT_JSON_ARRAY != vam->json_tree.type)
3576     {
3577       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
3578       vat_json_init_array (&vam->json_tree);
3579     }
3580   node = vat_json_array_add (&vam->json_tree);
3581
3582   vat_json_init_object (node);
3583   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
3584   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
3585   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
3586   vat_json_object_add_uint (node, "mode", mp->mode);
3587 }
3588
3589 static int
3590 api_sw_interface_rx_placement_dump (vat_main_t * vam)
3591 {
3592   unformat_input_t *i = vam->input;
3593   vl_api_sw_interface_rx_placement_dump_t *mp;
3594   vl_api_control_ping_t *mp_ping;
3595   int ret;
3596   u32 sw_if_index;
3597   u8 sw_if_index_set = 0;
3598
3599   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3600     {
3601       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3602         sw_if_index_set++;
3603       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3604         sw_if_index_set++;
3605       else
3606         break;
3607     }
3608
3609   print (vam->ofp,
3610          "\n%-11s %-11s %-6s %-5s %-4s",
3611          "sw_if_index", "main/worker", "thread", "queue", "mode");
3612
3613   /* Dump Interface rx placement */
3614   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
3615
3616   if (sw_if_index_set)
3617     mp->sw_if_index = htonl (sw_if_index);
3618   else
3619     mp->sw_if_index = ~0;
3620
3621   S (mp);
3622
3623   /* Use a control ping for synchronization */
3624   MPING (CONTROL_PING, mp_ping);
3625   S (mp_ping);
3626
3627   W (ret);
3628   return ret;
3629 }
3630
3631 static int
3632 api_sw_interface_clear_stats (vat_main_t * vam)
3633 {
3634   unformat_input_t *i = vam->input;
3635   vl_api_sw_interface_clear_stats_t *mp;
3636   u32 sw_if_index;
3637   u8 sw_if_index_set = 0;
3638   int ret;
3639
3640   /* Parse args required to build the message */
3641   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3642     {
3643       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3644         sw_if_index_set = 1;
3645       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3646         sw_if_index_set = 1;
3647       else
3648         break;
3649     }
3650
3651   /* Construct the API message */
3652   M (SW_INTERFACE_CLEAR_STATS, mp);
3653
3654   if (sw_if_index_set == 1)
3655     mp->sw_if_index = ntohl (sw_if_index);
3656   else
3657     mp->sw_if_index = ~0;
3658
3659   /* send it... */
3660   S (mp);
3661
3662   /* Wait for a reply, return the good/bad news... */
3663   W (ret);
3664   return ret;
3665 }
3666
3667 static int
3668 api_sw_interface_add_del_address (vat_main_t * vam)
3669 {
3670   unformat_input_t *i = vam->input;
3671   vl_api_sw_interface_add_del_address_t *mp;
3672   u32 sw_if_index;
3673   u8 sw_if_index_set = 0;
3674   u8 is_add = 1, del_all = 0;
3675   u32 address_length = 0;
3676   u8 v4_address_set = 0;
3677   u8 v6_address_set = 0;
3678   ip4_address_t v4address;
3679   ip6_address_t v6address;
3680   int ret;
3681
3682   /* Parse args required to build the message */
3683   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3684     {
3685       if (unformat (i, "del-all"))
3686         del_all = 1;
3687       else if (unformat (i, "del"))
3688         is_add = 0;
3689       else
3690         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3691         sw_if_index_set = 1;
3692       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3693         sw_if_index_set = 1;
3694       else if (unformat (i, "%U/%d",
3695                          unformat_ip4_address, &v4address, &address_length))
3696         v4_address_set = 1;
3697       else if (unformat (i, "%U/%d",
3698                          unformat_ip6_address, &v6address, &address_length))
3699         v6_address_set = 1;
3700       else
3701         break;
3702     }
3703
3704   if (sw_if_index_set == 0)
3705     {
3706       errmsg ("missing interface name or sw_if_index");
3707       return -99;
3708     }
3709   if (v4_address_set && v6_address_set)
3710     {
3711       errmsg ("both v4 and v6 addresses set");
3712       return -99;
3713     }
3714   if (!v4_address_set && !v6_address_set && !del_all)
3715     {
3716       errmsg ("no addresses set");
3717       return -99;
3718     }
3719
3720   /* Construct the API message */
3721   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
3722
3723   mp->sw_if_index = ntohl (sw_if_index);
3724   mp->is_add = is_add;
3725   mp->del_all = del_all;
3726   if (v6_address_set)
3727     {
3728       mp->prefix.address.af = ADDRESS_IP6;
3729       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
3730     }
3731   else
3732     {
3733       mp->prefix.address.af = ADDRESS_IP4;
3734       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
3735     }
3736   mp->prefix.len = address_length;
3737
3738   /* send it... */
3739   S (mp);
3740
3741   /* Wait for a reply, return good/bad news  */
3742   W (ret);
3743   return ret;
3744 }
3745
3746 static int
3747 api_sw_interface_set_mpls_enable (vat_main_t * vam)
3748 {
3749   unformat_input_t *i = vam->input;
3750   vl_api_sw_interface_set_mpls_enable_t *mp;
3751   u32 sw_if_index;
3752   u8 sw_if_index_set = 0;
3753   u8 enable = 1;
3754   int ret;
3755
3756   /* Parse args required to build the message */
3757   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3758     {
3759       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3760         sw_if_index_set = 1;
3761       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3762         sw_if_index_set = 1;
3763       else if (unformat (i, "disable"))
3764         enable = 0;
3765       else if (unformat (i, "dis"))
3766         enable = 0;
3767       else
3768         break;
3769     }
3770
3771   if (sw_if_index_set == 0)
3772     {
3773       errmsg ("missing interface name or sw_if_index");
3774       return -99;
3775     }
3776
3777   /* Construct the API message */
3778   M (SW_INTERFACE_SET_MPLS_ENABLE, mp);
3779
3780   mp->sw_if_index = ntohl (sw_if_index);
3781   mp->enable = enable;
3782
3783   /* send it... */
3784   S (mp);
3785
3786   /* Wait for a reply... */
3787   W (ret);
3788   return ret;
3789 }
3790
3791 static int
3792 api_sw_interface_set_table (vat_main_t * vam)
3793 {
3794   unformat_input_t *i = vam->input;
3795   vl_api_sw_interface_set_table_t *mp;
3796   u32 sw_if_index, vrf_id = 0;
3797   u8 sw_if_index_set = 0;
3798   u8 is_ipv6 = 0;
3799   int ret;
3800
3801   /* Parse args required to build the message */
3802   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3803     {
3804       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3805         sw_if_index_set = 1;
3806       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3807         sw_if_index_set = 1;
3808       else if (unformat (i, "vrf %d", &vrf_id))
3809         ;
3810       else if (unformat (i, "ipv6"))
3811         is_ipv6 = 1;
3812       else
3813         break;
3814     }
3815
3816   if (sw_if_index_set == 0)
3817     {
3818       errmsg ("missing interface name or sw_if_index");
3819       return -99;
3820     }
3821
3822   /* Construct the API message */
3823   M (SW_INTERFACE_SET_TABLE, mp);
3824
3825   mp->sw_if_index = ntohl (sw_if_index);
3826   mp->is_ipv6 = is_ipv6;
3827   mp->vrf_id = ntohl (vrf_id);
3828
3829   /* send it... */
3830   S (mp);
3831
3832   /* Wait for a reply... */
3833   W (ret);
3834   return ret;
3835 }
3836
3837 static void vl_api_sw_interface_get_table_reply_t_handler
3838   (vl_api_sw_interface_get_table_reply_t * mp)
3839 {
3840   vat_main_t *vam = &vat_main;
3841
3842   print (vam->ofp, "%d", ntohl (mp->vrf_id));
3843
3844   vam->retval = ntohl (mp->retval);
3845   vam->result_ready = 1;
3846
3847 }
3848
3849 static void vl_api_sw_interface_get_table_reply_t_handler_json
3850   (vl_api_sw_interface_get_table_reply_t * mp)
3851 {
3852   vat_main_t *vam = &vat_main;
3853   vat_json_node_t node;
3854
3855   vat_json_init_object (&node);
3856   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
3857   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
3858
3859   vat_json_print (vam->ofp, &node);
3860   vat_json_free (&node);
3861
3862   vam->retval = ntohl (mp->retval);
3863   vam->result_ready = 1;
3864 }
3865
3866 static int
3867 api_sw_interface_get_table (vat_main_t * vam)
3868 {
3869   unformat_input_t *i = vam->input;
3870   vl_api_sw_interface_get_table_t *mp;
3871   u32 sw_if_index;
3872   u8 sw_if_index_set = 0;
3873   u8 is_ipv6 = 0;
3874   int ret;
3875
3876   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3877     {
3878       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3879         sw_if_index_set = 1;
3880       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3881         sw_if_index_set = 1;
3882       else if (unformat (i, "ipv6"))
3883         is_ipv6 = 1;
3884       else
3885         break;
3886     }
3887
3888   if (sw_if_index_set == 0)
3889     {
3890       errmsg ("missing interface name or sw_if_index");
3891       return -99;
3892     }
3893
3894   M (SW_INTERFACE_GET_TABLE, mp);
3895   mp->sw_if_index = htonl (sw_if_index);
3896   mp->is_ipv6 = is_ipv6;
3897
3898   S (mp);
3899   W (ret);
3900   return ret;
3901 }
3902
3903 static int
3904 api_sw_interface_set_vpath (vat_main_t * vam)
3905 {
3906   unformat_input_t *i = vam->input;
3907   vl_api_sw_interface_set_vpath_t *mp;
3908   u32 sw_if_index = 0;
3909   u8 sw_if_index_set = 0;
3910   u8 is_enable = 0;
3911   int ret;
3912
3913   /* Parse args required to build the message */
3914   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3915     {
3916       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3917         sw_if_index_set = 1;
3918       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3919         sw_if_index_set = 1;
3920       else if (unformat (i, "enable"))
3921         is_enable = 1;
3922       else if (unformat (i, "disable"))
3923         is_enable = 0;
3924       else
3925         break;
3926     }
3927
3928   if (sw_if_index_set == 0)
3929     {
3930       errmsg ("missing interface name or sw_if_index");
3931       return -99;
3932     }
3933
3934   /* Construct the API message */
3935   M (SW_INTERFACE_SET_VPATH, mp);
3936
3937   mp->sw_if_index = ntohl (sw_if_index);
3938   mp->enable = is_enable;
3939
3940   /* send it... */
3941   S (mp);
3942
3943   /* Wait for a reply... */
3944   W (ret);
3945   return ret;
3946 }
3947
3948 static int
3949 api_sw_interface_set_l2_xconnect (vat_main_t * vam)
3950 {
3951   unformat_input_t *i = vam->input;
3952   vl_api_sw_interface_set_l2_xconnect_t *mp;
3953   u32 rx_sw_if_index;
3954   u8 rx_sw_if_index_set = 0;
3955   u32 tx_sw_if_index;
3956   u8 tx_sw_if_index_set = 0;
3957   u8 enable = 1;
3958   int ret;
3959
3960   /* Parse args required to build the message */
3961   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3962     {
3963       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
3964         rx_sw_if_index_set = 1;
3965       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
3966         tx_sw_if_index_set = 1;
3967       else if (unformat (i, "rx"))
3968         {
3969           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3970             {
3971               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3972                             &rx_sw_if_index))
3973                 rx_sw_if_index_set = 1;
3974             }
3975           else
3976             break;
3977         }
3978       else if (unformat (i, "tx"))
3979         {
3980           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3981             {
3982               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
3983                             &tx_sw_if_index))
3984                 tx_sw_if_index_set = 1;
3985             }
3986           else
3987             break;
3988         }
3989       else if (unformat (i, "enable"))
3990         enable = 1;
3991       else if (unformat (i, "disable"))
3992         enable = 0;
3993       else
3994         break;
3995     }
3996
3997   if (rx_sw_if_index_set == 0)
3998     {
3999       errmsg ("missing rx interface name or rx_sw_if_index");
4000       return -99;
4001     }
4002
4003   if (enable && (tx_sw_if_index_set == 0))
4004     {
4005       errmsg ("missing tx interface name or tx_sw_if_index");
4006       return -99;
4007     }
4008
4009   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
4010
4011   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4012   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
4013   mp->enable = enable;
4014
4015   S (mp);
4016   W (ret);
4017   return ret;
4018 }
4019
4020 static int
4021 api_sw_interface_set_l2_bridge (vat_main_t * vam)
4022 {
4023   unformat_input_t *i = vam->input;
4024   vl_api_sw_interface_set_l2_bridge_t *mp;
4025   vl_api_l2_port_type_t port_type;
4026   u32 rx_sw_if_index;
4027   u8 rx_sw_if_index_set = 0;
4028   u32 bd_id;
4029   u8 bd_id_set = 0;
4030   u32 shg = 0;
4031   u8 enable = 1;
4032   int ret;
4033
4034   port_type = L2_API_PORT_TYPE_NORMAL;
4035
4036   /* Parse args required to build the message */
4037   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4038     {
4039       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
4040         rx_sw_if_index_set = 1;
4041       else if (unformat (i, "bd_id %d", &bd_id))
4042         bd_id_set = 1;
4043       else
4044         if (unformat
4045             (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index))
4046         rx_sw_if_index_set = 1;
4047       else if (unformat (i, "shg %d", &shg))
4048         ;
4049       else if (unformat (i, "bvi"))
4050         port_type = L2_API_PORT_TYPE_BVI;
4051       else if (unformat (i, "uu-fwd"))
4052         port_type = L2_API_PORT_TYPE_UU_FWD;
4053       else if (unformat (i, "enable"))
4054         enable = 1;
4055       else if (unformat (i, "disable"))
4056         enable = 0;
4057       else
4058         break;
4059     }
4060
4061   if (rx_sw_if_index_set == 0)
4062     {
4063       errmsg ("missing rx interface name or sw_if_index");
4064       return -99;
4065     }
4066
4067   if (enable && (bd_id_set == 0))
4068     {
4069       errmsg ("missing bridge domain");
4070       return -99;
4071     }
4072
4073   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
4074
4075   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
4076   mp->bd_id = ntohl (bd_id);
4077   mp->shg = (u8) shg;
4078   mp->port_type = ntohl (port_type);
4079   mp->enable = enable;
4080
4081   S (mp);
4082   W (ret);
4083   return ret;
4084 }
4085
4086 static int
4087 api_bridge_domain_dump (vat_main_t * vam)
4088 {
4089   unformat_input_t *i = vam->input;
4090   vl_api_bridge_domain_dump_t *mp;
4091   vl_api_control_ping_t *mp_ping;
4092   u32 bd_id = ~0;
4093   int ret;
4094
4095   /* Parse args required to build the message */
4096   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4097     {
4098       if (unformat (i, "bd_id %d", &bd_id))
4099         ;
4100       else
4101         break;
4102     }
4103
4104   M (BRIDGE_DOMAIN_DUMP, mp);
4105   mp->bd_id = ntohl (bd_id);
4106   S (mp);
4107
4108   /* Use a control ping for synchronization */
4109   MPING (CONTROL_PING, mp_ping);
4110   S (mp_ping);
4111
4112   W (ret);
4113   return ret;
4114 }
4115
4116 static int
4117 api_bridge_domain_add_del (vat_main_t * vam)
4118 {
4119   unformat_input_t *i = vam->input;
4120   vl_api_bridge_domain_add_del_t *mp;
4121   u32 bd_id = ~0;
4122   u8 is_add = 1;
4123   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
4124   u8 *bd_tag = NULL;
4125   u32 mac_age = 0;
4126   int ret;
4127
4128   /* Parse args required to build the message */
4129   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4130     {
4131       if (unformat (i, "bd_id %d", &bd_id))
4132         ;
4133       else if (unformat (i, "flood %d", &flood))
4134         ;
4135       else if (unformat (i, "uu-flood %d", &uu_flood))
4136         ;
4137       else if (unformat (i, "forward %d", &forward))
4138         ;
4139       else if (unformat (i, "learn %d", &learn))
4140         ;
4141       else if (unformat (i, "arp-term %d", &arp_term))
4142         ;
4143       else if (unformat (i, "mac-age %d", &mac_age))
4144         ;
4145       else if (unformat (i, "bd-tag %s", &bd_tag))
4146         ;
4147       else if (unformat (i, "del"))
4148         {
4149           is_add = 0;
4150           flood = uu_flood = forward = learn = 0;
4151         }
4152       else
4153         break;
4154     }
4155
4156   if (bd_id == ~0)
4157     {
4158       errmsg ("missing bridge domain");
4159       ret = -99;
4160       goto done;
4161     }
4162
4163   if (mac_age > 255)
4164     {
4165       errmsg ("mac age must be less than 256 ");
4166       ret = -99;
4167       goto done;
4168     }
4169
4170   if ((bd_tag) && (vec_len (bd_tag) > 63))
4171     {
4172       errmsg ("bd-tag cannot be longer than 63");
4173       ret = -99;
4174       goto done;
4175     }
4176
4177   M (BRIDGE_DOMAIN_ADD_DEL, mp);
4178
4179   mp->bd_id = ntohl (bd_id);
4180   mp->flood = flood;
4181   mp->uu_flood = uu_flood;
4182   mp->forward = forward;
4183   mp->learn = learn;
4184   mp->arp_term = arp_term;
4185   mp->is_add = is_add;
4186   mp->mac_age = (u8) mac_age;
4187   if (bd_tag)
4188     {
4189       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
4190       mp->bd_tag[vec_len (bd_tag)] = 0;
4191     }
4192   S (mp);
4193   W (ret);
4194
4195 done:
4196   vec_free (bd_tag);
4197   return ret;
4198 }
4199
4200 static int
4201 api_l2fib_flush_bd (vat_main_t * vam)
4202 {
4203   unformat_input_t *i = vam->input;
4204   vl_api_l2fib_flush_bd_t *mp;
4205   u32 bd_id = ~0;
4206   int ret;
4207
4208   /* Parse args required to build the message */
4209   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4210     {
4211       if (unformat (i, "bd_id %d", &bd_id));
4212       else
4213         break;
4214     }
4215
4216   if (bd_id == ~0)
4217     {
4218       errmsg ("missing bridge domain");
4219       return -99;
4220     }
4221
4222   M (L2FIB_FLUSH_BD, mp);
4223
4224   mp->bd_id = htonl (bd_id);
4225
4226   S (mp);
4227   W (ret);
4228   return ret;
4229 }
4230
4231 static int
4232 api_l2fib_flush_int (vat_main_t * vam)
4233 {
4234   unformat_input_t *i = vam->input;
4235   vl_api_l2fib_flush_int_t *mp;
4236   u32 sw_if_index = ~0;
4237   int ret;
4238
4239   /* Parse args required to build the message */
4240   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4241     {
4242       if (unformat (i, "sw_if_index %d", &sw_if_index));
4243       else
4244         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index));
4245       else
4246         break;
4247     }
4248
4249   if (sw_if_index == ~0)
4250     {
4251       errmsg ("missing interface name or sw_if_index");
4252       return -99;
4253     }
4254
4255   M (L2FIB_FLUSH_INT, mp);
4256
4257   mp->sw_if_index = ntohl (sw_if_index);
4258
4259   S (mp);
4260   W (ret);
4261   return ret;
4262 }
4263
4264 static int
4265 api_l2fib_add_del (vat_main_t * vam)
4266 {
4267   unformat_input_t *i = vam->input;
4268   vl_api_l2fib_add_del_t *mp;
4269   f64 timeout;
4270   u8 mac[6] = { 0 };
4271   u8 mac_set = 0;
4272   u32 bd_id;
4273   u8 bd_id_set = 0;
4274   u32 sw_if_index = 0;
4275   u8 sw_if_index_set = 0;
4276   u8 is_add = 1;
4277   u8 static_mac = 0;
4278   u8 filter_mac = 0;
4279   u8 bvi_mac = 0;
4280   int count = 1;
4281   f64 before = 0;
4282   int j;
4283
4284   /* Parse args required to build the message */
4285   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4286     {
4287       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
4288         mac_set = 1;
4289       else if (unformat (i, "bd_id %d", &bd_id))
4290         bd_id_set = 1;
4291       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4292         sw_if_index_set = 1;
4293       else if (unformat (i, "sw_if"))
4294         {
4295           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4296             {
4297               if (unformat
4298                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4299                 sw_if_index_set = 1;
4300             }
4301           else
4302             break;
4303         }
4304       else if (unformat (i, "static"))
4305         static_mac = 1;
4306       else if (unformat (i, "filter"))
4307         {
4308           filter_mac = 1;
4309           static_mac = 1;
4310         }
4311       else if (unformat (i, "bvi"))
4312         {
4313           bvi_mac = 1;
4314           static_mac = 1;
4315         }
4316       else if (unformat (i, "del"))
4317         is_add = 0;
4318       else if (unformat (i, "count %d", &count))
4319         ;
4320       else
4321         break;
4322     }
4323
4324   if (mac_set == 0)
4325     {
4326       errmsg ("missing mac address");
4327       return -99;
4328     }
4329
4330   if (bd_id_set == 0)
4331     {
4332       errmsg ("missing bridge domain");
4333       return -99;
4334     }
4335
4336   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
4337     {
4338       errmsg ("missing interface name or sw_if_index");
4339       return -99;
4340     }
4341
4342   if (count > 1)
4343     {
4344       /* Turn on async mode */
4345       vam->async_mode = 1;
4346       vam->async_errors = 0;
4347       before = vat_time_now (vam);
4348     }
4349
4350   for (j = 0; j < count; j++)
4351     {
4352       M (L2FIB_ADD_DEL, mp);
4353
4354       clib_memcpy (mp->mac, mac, 6);
4355       mp->bd_id = ntohl (bd_id);
4356       mp->is_add = is_add;
4357       mp->sw_if_index = ntohl (sw_if_index);
4358
4359       if (is_add)
4360         {
4361           mp->static_mac = static_mac;
4362           mp->filter_mac = filter_mac;
4363           mp->bvi_mac = bvi_mac;
4364         }
4365       increment_mac_address (mac);
4366       /* send it... */
4367       S (mp);
4368     }
4369
4370   if (count > 1)
4371     {
4372       vl_api_control_ping_t *mp_ping;
4373       f64 after;
4374
4375       /* Shut off async mode */
4376       vam->async_mode = 0;
4377
4378       MPING (CONTROL_PING, mp_ping);
4379       S (mp_ping);
4380
4381       timeout = vat_time_now (vam) + 1.0;
4382       while (vat_time_now (vam) < timeout)
4383         if (vam->result_ready == 1)
4384           goto out;
4385       vam->retval = -99;
4386
4387     out:
4388       if (vam->retval == -99)
4389         errmsg ("timeout");
4390
4391       if (vam->async_errors > 0)
4392         {
4393           errmsg ("%d asynchronous errors", vam->async_errors);
4394           vam->retval = -98;
4395         }
4396       vam->async_errors = 0;
4397       after = vat_time_now (vam);
4398
4399       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
4400              count, after - before, count / (after - before));
4401     }
4402   else
4403     {
4404       int ret;
4405
4406       /* Wait for a reply... */
4407       W (ret);
4408       return ret;
4409     }
4410   /* Return the good/bad news */
4411   return (vam->retval);
4412 }
4413
4414 static int
4415 api_bridge_domain_set_mac_age (vat_main_t * vam)
4416 {
4417   unformat_input_t *i = vam->input;
4418   vl_api_bridge_domain_set_mac_age_t *mp;
4419   u32 bd_id = ~0;
4420   u32 mac_age = 0;
4421   int ret;
4422
4423   /* Parse args required to build the message */
4424   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4425     {
4426       if (unformat (i, "bd_id %d", &bd_id));
4427       else if (unformat (i, "mac-age %d", &mac_age));
4428       else
4429         break;
4430     }
4431
4432   if (bd_id == ~0)
4433     {
4434       errmsg ("missing bridge domain");
4435       return -99;
4436     }
4437
4438   if (mac_age > 255)
4439     {
4440       errmsg ("mac age must be less than 256 ");
4441       return -99;
4442     }
4443
4444   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
4445
4446   mp->bd_id = htonl (bd_id);
4447   mp->mac_age = (u8) mac_age;
4448
4449   S (mp);
4450   W (ret);
4451   return ret;
4452 }
4453
4454 static int
4455 api_l2_flags (vat_main_t * vam)
4456 {
4457   unformat_input_t *i = vam->input;
4458   vl_api_l2_flags_t *mp;
4459   u32 sw_if_index;
4460   u32 flags = 0;
4461   u8 sw_if_index_set = 0;
4462   u8 is_set = 0;
4463   int ret;
4464
4465   /* Parse args required to build the message */
4466   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4467     {
4468       if (unformat (i, "sw_if_index %d", &sw_if_index))
4469         sw_if_index_set = 1;
4470       else if (unformat (i, "sw_if"))
4471         {
4472           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4473             {
4474               if (unformat
4475                   (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4476                 sw_if_index_set = 1;
4477             }
4478           else
4479             break;
4480         }
4481       else if (unformat (i, "learn"))
4482         flags |= L2_LEARN;
4483       else if (unformat (i, "forward"))
4484         flags |= L2_FWD;
4485       else if (unformat (i, "flood"))
4486         flags |= L2_FLOOD;
4487       else if (unformat (i, "uu-flood"))
4488         flags |= L2_UU_FLOOD;
4489       else if (unformat (i, "arp-term"))
4490         flags |= L2_ARP_TERM;
4491       else if (unformat (i, "off"))
4492         is_set = 0;
4493       else if (unformat (i, "disable"))
4494         is_set = 0;
4495       else
4496         break;
4497     }
4498
4499   if (sw_if_index_set == 0)
4500     {
4501       errmsg ("missing interface name or sw_if_index");
4502       return -99;
4503     }
4504
4505   M (L2_FLAGS, mp);
4506
4507   mp->sw_if_index = ntohl (sw_if_index);
4508   mp->feature_bitmap = ntohl (flags);
4509   mp->is_set = is_set;
4510
4511   S (mp);
4512   W (ret);
4513   return ret;
4514 }
4515
4516 static int
4517 api_bridge_flags (vat_main_t * vam)
4518 {
4519   unformat_input_t *i = vam->input;
4520   vl_api_bridge_flags_t *mp;
4521   u32 bd_id;
4522   u8 bd_id_set = 0;
4523   u8 is_set = 1;
4524   bd_flags_t flags = 0;
4525   int ret;
4526
4527   /* Parse args required to build the message */
4528   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4529     {
4530       if (unformat (i, "bd_id %d", &bd_id))
4531         bd_id_set = 1;
4532       else if (unformat (i, "learn"))
4533         flags |= BRIDGE_API_FLAG_LEARN;
4534       else if (unformat (i, "forward"))
4535         flags |= BRIDGE_API_FLAG_FWD;
4536       else if (unformat (i, "flood"))
4537         flags |= BRIDGE_API_FLAG_FLOOD;
4538       else if (unformat (i, "uu-flood"))
4539         flags |= BRIDGE_API_FLAG_UU_FLOOD;
4540       else if (unformat (i, "arp-term"))
4541         flags |= BRIDGE_API_FLAG_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 (bd_id_set == 0)
4551     {
4552       errmsg ("missing bridge domain");
4553       return -99;
4554     }
4555
4556   M (BRIDGE_FLAGS, mp);
4557
4558   mp->bd_id = ntohl (bd_id);
4559   mp->flags = 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_bd_ip_mac_add_del (vat_main_t * vam)
4569 {
4570   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
4571   vl_api_mac_address_t mac = { 0 };
4572   unformat_input_t *i = vam->input;
4573   vl_api_bd_ip_mac_add_del_t *mp;
4574   u32 bd_id;
4575   u8 is_add = 1;
4576   u8 bd_id_set = 0;
4577   u8 ip_set = 0;
4578   u8 mac_set = 0;
4579   int ret;
4580
4581
4582   /* Parse args required to build the message */
4583   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4584     {
4585       if (unformat (i, "bd_id %d", &bd_id))
4586         {
4587           bd_id_set++;
4588         }
4589       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
4590         {
4591           ip_set++;
4592         }
4593       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
4594         {
4595           mac_set++;
4596         }
4597       else if (unformat (i, "del"))
4598         is_add = 0;
4599       else
4600         break;
4601     }
4602
4603   if (bd_id_set == 0)
4604     {
4605       errmsg ("missing bridge domain");
4606       return -99;
4607     }
4608   else if (ip_set == 0)
4609     {
4610       errmsg ("missing IP address");
4611       return -99;
4612     }
4613   else if (mac_set == 0)
4614     {
4615       errmsg ("missing MAC address");
4616       return -99;
4617     }
4618
4619   M (BD_IP_MAC_ADD_DEL, mp);
4620
4621   mp->entry.bd_id = ntohl (bd_id);
4622   mp->is_add = is_add;
4623
4624   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
4625   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
4626
4627   S (mp);
4628   W (ret);
4629   return ret;
4630 }
4631
4632 static int
4633 api_bd_ip_mac_flush (vat_main_t * vam)
4634 {
4635   unformat_input_t *i = vam->input;
4636   vl_api_bd_ip_mac_flush_t *mp;
4637   u32 bd_id;
4638   u8 bd_id_set = 0;
4639   int ret;
4640
4641   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4642     {
4643       if (unformat (i, "bd_id %d", &bd_id))
4644         {
4645           bd_id_set++;
4646         }
4647       else
4648         break;
4649     }
4650
4651   if (bd_id_set == 0)
4652     {
4653       errmsg ("missing bridge domain");
4654       return -99;
4655     }
4656
4657   M (BD_IP_MAC_FLUSH, mp);
4658
4659   mp->bd_id = ntohl (bd_id);
4660
4661   S (mp);
4662   W (ret);
4663   return ret;
4664 }
4665
4666 static void vl_api_bd_ip_mac_details_t_handler
4667   (vl_api_bd_ip_mac_details_t * mp)
4668 {
4669   vat_main_t *vam = &vat_main;
4670
4671   print (vam->ofp,
4672          "\n%-5d %U %U",
4673          ntohl (mp->entry.bd_id),
4674          format_vl_api_mac_address, mp->entry.mac,
4675          format_vl_api_address, &mp->entry.ip);
4676 }
4677
4678 static void vl_api_bd_ip_mac_details_t_handler_json
4679   (vl_api_bd_ip_mac_details_t * mp)
4680 {
4681   vat_main_t *vam = &vat_main;
4682   vat_json_node_t *node = NULL;
4683
4684   if (VAT_JSON_ARRAY != vam->json_tree.type)
4685     {
4686       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4687       vat_json_init_array (&vam->json_tree);
4688     }
4689   node = vat_json_array_add (&vam->json_tree);
4690
4691   vat_json_init_object (node);
4692   vat_json_object_add_uint (node, "bd_id", ntohl (mp->entry.bd_id));
4693   vat_json_object_add_string_copy (node, "mac_address",
4694                                    format (0, "%U", format_vl_api_mac_address,
4695                                            &mp->entry.mac));
4696   u8 *ip = 0;
4697
4698   ip = format (0, "%U", format_vl_api_address, &mp->entry.ip);
4699   vat_json_object_add_string_copy (node, "ip_address", ip);
4700   vec_free (ip);
4701 }
4702
4703 static int
4704 api_bd_ip_mac_dump (vat_main_t * vam)
4705 {
4706   unformat_input_t *i = vam->input;
4707   vl_api_bd_ip_mac_dump_t *mp;
4708   vl_api_control_ping_t *mp_ping;
4709   int ret;
4710   u32 bd_id;
4711   u8 bd_id_set = 0;
4712
4713   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4714     {
4715       if (unformat (i, "bd_id %d", &bd_id))
4716         {
4717           bd_id_set++;
4718         }
4719       else
4720         break;
4721     }
4722
4723   print (vam->ofp,
4724          "\n%-5s %-7s %-20s %-30s",
4725          "bd_id", "is_ipv6", "mac_address", "ip_address");
4726
4727   /* Dump Bridge Domain Ip to Mac entries */
4728   M (BD_IP_MAC_DUMP, mp);
4729
4730   if (bd_id_set)
4731     mp->bd_id = htonl (bd_id);
4732   else
4733     mp->bd_id = ~0;
4734
4735   S (mp);
4736
4737   /* Use a control ping for synchronization */
4738   MPING (CONTROL_PING, mp_ping);
4739   S (mp_ping);
4740
4741   W (ret);
4742   return ret;
4743 }
4744
4745 static int
4746 api_tap_create_v2 (vat_main_t * vam)
4747 {
4748   unformat_input_t *i = vam->input;
4749   vl_api_tap_create_v2_t *mp;
4750   u8 mac_address[6];
4751   u8 random_mac = 1;
4752   u32 id = ~0;
4753   u32 num_rx_queues = 0;
4754   u8 *host_if_name = 0;
4755   u8 host_if_name_set = 0;
4756   u8 *host_ns = 0;
4757   u8 host_ns_set = 0;
4758   u8 host_mac_addr[6];
4759   u8 host_mac_addr_set = 0;
4760   u8 *host_bridge = 0;
4761   u8 host_bridge_set = 0;
4762   u8 host_ip4_prefix_set = 0;
4763   u8 host_ip6_prefix_set = 0;
4764   ip4_address_t host_ip4_addr;
4765   ip4_address_t host_ip4_gw;
4766   u8 host_ip4_gw_set = 0;
4767   u32 host_ip4_prefix_len = 0;
4768   ip6_address_t host_ip6_addr;
4769   ip6_address_t host_ip6_gw;
4770   u8 host_ip6_gw_set = 0;
4771   u32 host_ip6_prefix_len = 0;
4772   u32 host_mtu_size = 0;
4773   u8 host_mtu_set = 0;
4774   u32 tap_flags = 0;
4775   int ret;
4776   u32 rx_ring_sz = 0, tx_ring_sz = 0;
4777
4778   clib_memset (mac_address, 0, sizeof (mac_address));
4779
4780   /* Parse args required to build the message */
4781   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4782     {
4783       if (unformat (i, "id %u", &id))
4784         ;
4785       else
4786         if (unformat
4787             (i, "hw-addr %U", unformat_ethernet_address, mac_address))
4788         random_mac = 0;
4789       else if (unformat (i, "host-if-name %s", &host_if_name))
4790         host_if_name_set = 1;
4791       else if (unformat (i, "num-rx-queues %u", &num_rx_queues))
4792         ;
4793       else if (unformat (i, "host-ns %s", &host_ns))
4794         host_ns_set = 1;
4795       else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address,
4796                          host_mac_addr))
4797         host_mac_addr_set = 1;
4798       else if (unformat (i, "host-bridge %s", &host_bridge))
4799         host_bridge_set = 1;
4800       else if (unformat (i, "host-ip4-addr %U/%u", unformat_ip4_address,
4801                          &host_ip4_addr, &host_ip4_prefix_len))
4802         host_ip4_prefix_set = 1;
4803       else if (unformat (i, "host-ip6-addr %U/%u", unformat_ip6_address,
4804                          &host_ip6_addr, &host_ip6_prefix_len))
4805         host_ip6_prefix_set = 1;
4806       else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
4807                          &host_ip4_gw))
4808         host_ip4_gw_set = 1;
4809       else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
4810                          &host_ip6_gw))
4811         host_ip6_gw_set = 1;
4812       else if (unformat (i, "rx-ring-size %u", &rx_ring_sz))
4813         ;
4814       else if (unformat (i, "tx-ring-size %u", &tx_ring_sz))
4815         ;
4816       else if (unformat (i, "host-mtu-size %u", &host_mtu_size))
4817         host_mtu_set = 1;
4818       else if (unformat (i, "no-gso"))
4819         tap_flags &= ~TAP_API_FLAG_GSO;
4820       else if (unformat (i, "gso"))
4821         tap_flags |= TAP_API_FLAG_GSO;
4822       else if (unformat (i, "csum-offload"))
4823         tap_flags |= TAP_API_FLAG_CSUM_OFFLOAD;
4824       else if (unformat (i, "persist"))
4825         tap_flags |= TAP_API_FLAG_PERSIST;
4826       else if (unformat (i, "attach"))
4827         tap_flags |= TAP_API_FLAG_ATTACH;
4828       else if (unformat (i, "tun"))
4829         tap_flags |= TAP_API_FLAG_TUN;
4830       else if (unformat (i, "gro-coalesce"))
4831         tap_flags |= TAP_API_FLAG_GRO_COALESCE;
4832       else if (unformat (i, "packed"))
4833         tap_flags |= TAP_API_FLAG_PACKED;
4834       else if (unformat (i, "in-order"))
4835         tap_flags |= TAP_API_FLAG_IN_ORDER;
4836       else
4837         break;
4838     }
4839
4840   if (vec_len (host_if_name) > 63)
4841     {
4842       errmsg ("tap name too long. ");
4843       return -99;
4844     }
4845   if (vec_len (host_ns) > 63)
4846     {
4847       errmsg ("host name space too long. ");
4848       return -99;
4849     }
4850   if (vec_len (host_bridge) > 63)
4851     {
4852       errmsg ("host bridge name too long. ");
4853       return -99;
4854     }
4855   if (host_ip4_prefix_len > 32)
4856     {
4857       errmsg ("host ip4 prefix length not valid. ");
4858       return -99;
4859     }
4860   if (host_ip6_prefix_len > 128)
4861     {
4862       errmsg ("host ip6 prefix length not valid. ");
4863       return -99;
4864     }
4865   if (!is_pow2 (rx_ring_sz))
4866     {
4867       errmsg ("rx ring size must be power of 2. ");
4868       return -99;
4869     }
4870   if (rx_ring_sz > 32768)
4871     {
4872       errmsg ("rx ring size must be 32768 or lower. ");
4873       return -99;
4874     }
4875   if (!is_pow2 (tx_ring_sz))
4876     {
4877       errmsg ("tx ring size must be power of 2. ");
4878       return -99;
4879     }
4880   if (tx_ring_sz > 32768)
4881     {
4882       errmsg ("tx ring size must be 32768 or lower. ");
4883       return -99;
4884     }
4885   if (host_mtu_set && (host_mtu_size < 64 || host_mtu_size > 65355))
4886     {
4887       errmsg ("host MTU size must be in between 64 and 65355. ");
4888       return -99;
4889     }
4890
4891   /* Construct the API message */
4892   M (TAP_CREATE_V2, mp);
4893
4894   mp->id = ntohl (id);
4895   mp->use_random_mac = random_mac;
4896   mp->num_rx_queues = (u8) num_rx_queues;
4897   mp->tx_ring_sz = ntohs (tx_ring_sz);
4898   mp->rx_ring_sz = ntohs (rx_ring_sz);
4899   mp->host_mtu_set = host_mtu_set;
4900   mp->host_mtu_size = ntohl (host_mtu_size);
4901   mp->host_mac_addr_set = host_mac_addr_set;
4902   mp->host_ip4_prefix_set = host_ip4_prefix_set;
4903   mp->host_ip6_prefix_set = host_ip6_prefix_set;
4904   mp->host_ip4_gw_set = host_ip4_gw_set;
4905   mp->host_ip6_gw_set = host_ip6_gw_set;
4906   mp->tap_flags = ntohl (tap_flags);
4907   mp->host_namespace_set = host_ns_set;
4908   mp->host_if_name_set = host_if_name_set;
4909   mp->host_bridge_set = host_bridge_set;
4910
4911   if (random_mac == 0)
4912     clib_memcpy (mp->mac_address, mac_address, 6);
4913   if (host_mac_addr_set)
4914     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
4915   if (host_if_name_set)
4916     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
4917   if (host_ns_set)
4918     clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns));
4919   if (host_bridge_set)
4920     clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge));
4921   if (host_ip4_prefix_set)
4922     {
4923       clib_memcpy (mp->host_ip4_prefix.address, &host_ip4_addr, 4);
4924       mp->host_ip4_prefix.len = (u8) host_ip4_prefix_len;
4925     }
4926   if (host_ip6_prefix_set)
4927     {
4928       clib_memcpy (mp->host_ip6_prefix.address, &host_ip6_addr, 16);
4929       mp->host_ip6_prefix.len = (u8) host_ip6_prefix_len;
4930     }
4931   if (host_ip4_gw_set)
4932     clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
4933   if (host_ip6_gw_set)
4934     clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
4935
4936   vec_free (host_ns);
4937   vec_free (host_if_name);
4938   vec_free (host_bridge);
4939
4940   /* send it... */
4941   S (mp);
4942
4943   /* Wait for a reply... */
4944   W (ret);
4945   return ret;
4946 }
4947
4948 static int
4949 api_tap_delete_v2 (vat_main_t * vam)
4950 {
4951   unformat_input_t *i = vam->input;
4952   vl_api_tap_delete_v2_t *mp;
4953   u32 sw_if_index = ~0;
4954   u8 sw_if_index_set = 0;
4955   int ret;
4956
4957   /* Parse args required to build the message */
4958   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4959     {
4960       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
4961         sw_if_index_set = 1;
4962       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4963         sw_if_index_set = 1;
4964       else
4965         break;
4966     }
4967
4968   if (sw_if_index_set == 0)
4969     {
4970       errmsg ("missing vpp interface name. ");
4971       return -99;
4972     }
4973
4974   /* Construct the API message */
4975   M (TAP_DELETE_V2, mp);
4976
4977   mp->sw_if_index = ntohl (sw_if_index);
4978
4979   /* send it... */
4980   S (mp);
4981
4982   /* Wait for a reply... */
4983   W (ret);
4984   return ret;
4985 }
4986
4987 uword
4988 unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
4989 {
4990   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
4991   u32 x[4];
4992
4993   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
4994     return 0;
4995
4996   addr->domain = x[0];
4997   addr->bus = x[1];
4998   addr->slot = x[2];
4999   addr->function = x[3];
5000
5001   return 1;
5002 }
5003
5004 static int
5005 api_virtio_pci_create_v2 (vat_main_t * vam)
5006 {
5007   unformat_input_t *i = vam->input;
5008   vl_api_virtio_pci_create_v2_t *mp;
5009   u8 mac_address[6];
5010   u8 random_mac = 1;
5011   u32 pci_addr = 0;
5012   u64 features = (u64) ~ (0ULL);
5013   u32 virtio_flags = 0;
5014   int ret;
5015
5016   clib_memset (mac_address, 0, sizeof (mac_address));
5017
5018   /* Parse args required to build the message */
5019   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5020     {
5021       if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address))
5022         {
5023           random_mac = 0;
5024         }
5025       else if (unformat (i, "pci-addr %U", unformat_vlib_pci_addr, &pci_addr))
5026         ;
5027       else if (unformat (i, "features 0x%llx", &features))
5028         ;
5029       else if (unformat (i, "gso-enabled"))
5030         virtio_flags |= VIRTIO_API_FLAG_GSO;
5031       else if (unformat (i, "csum-offload-enabled"))
5032         virtio_flags |= VIRTIO_API_FLAG_CSUM_OFFLOAD;
5033       else if (unformat (i, "gro-coalesce"))
5034         virtio_flags |= VIRTIO_API_FLAG_GRO_COALESCE;
5035       else if (unformat (i, "packed"))
5036         virtio_flags |= VIRTIO_API_FLAG_PACKED;
5037       else if (unformat (i, "in-order"))
5038         virtio_flags |= VIRTIO_API_FLAG_IN_ORDER;
5039       else if (unformat (i, "buffering"))
5040         virtio_flags |= VIRTIO_API_FLAG_BUFFERING;
5041       else
5042         break;
5043     }
5044
5045   if (pci_addr == 0)
5046     {
5047       errmsg ("pci address must be non zero. ");
5048       return -99;
5049     }
5050
5051   /* Construct the API message */
5052   M (VIRTIO_PCI_CREATE_V2, mp);
5053
5054   mp->use_random_mac = random_mac;
5055
5056   mp->pci_addr.domain = htons (((vlib_pci_addr_t) pci_addr).domain);
5057   mp->pci_addr.bus = ((vlib_pci_addr_t) pci_addr).bus;
5058   mp->pci_addr.slot = ((vlib_pci_addr_t) pci_addr).slot;
5059   mp->pci_addr.function = ((vlib_pci_addr_t) pci_addr).function;
5060
5061   mp->features = clib_host_to_net_u64 (features);
5062   mp->virtio_flags = clib_host_to_net_u32 (virtio_flags);
5063
5064   if (random_mac == 0)
5065     clib_memcpy (mp->mac_address, mac_address, 6);
5066
5067   /* send it... */
5068   S (mp);
5069
5070   /* Wait for a reply... */
5071   W (ret);
5072   return ret;
5073 }
5074
5075 static int
5076 api_virtio_pci_delete (vat_main_t * vam)
5077 {
5078   unformat_input_t *i = vam->input;
5079   vl_api_virtio_pci_delete_t *mp;
5080   u32 sw_if_index = ~0;
5081   u8 sw_if_index_set = 0;
5082   int ret;
5083
5084   /* Parse args required to build the message */
5085   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5086     {
5087       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5088         sw_if_index_set = 1;
5089       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5090         sw_if_index_set = 1;
5091       else
5092         break;
5093     }
5094
5095   if (sw_if_index_set == 0)
5096     {
5097       errmsg ("missing vpp interface name. ");
5098       return -99;
5099     }
5100
5101   /* Construct the API message */
5102   M (VIRTIO_PCI_DELETE, mp);
5103
5104   mp->sw_if_index = htonl (sw_if_index);
5105
5106   /* send it... */
5107   S (mp);
5108
5109   /* Wait for a reply... */
5110   W (ret);
5111   return ret;
5112 }
5113
5114 static int
5115 api_bond_create (vat_main_t * vam)
5116 {
5117   unformat_input_t *i = vam->input;
5118   vl_api_bond_create_t *mp;
5119   u8 mac_address[6];
5120   u8 custom_mac = 0;
5121   int ret;
5122   u8 mode;
5123   u8 lb;
5124   u8 mode_is_set = 0;
5125   u32 id = ~0;
5126   u8 numa_only = 0;
5127
5128   clib_memset (mac_address, 0, sizeof (mac_address));
5129   lb = BOND_LB_L2;
5130
5131   /* Parse args required to build the message */
5132   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5133     {
5134       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5135         mode_is_set = 1;
5136       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5137                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5138         ;
5139       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5140                          mac_address))
5141         custom_mac = 1;
5142       else if (unformat (i, "numa-only"))
5143         numa_only = 1;
5144       else if (unformat (i, "id %u", &id))
5145         ;
5146       else
5147         break;
5148     }
5149
5150   if (mode_is_set == 0)
5151     {
5152       errmsg ("Missing bond mode. ");
5153       return -99;
5154     }
5155
5156   /* Construct the API message */
5157   M (BOND_CREATE, mp);
5158
5159   mp->use_custom_mac = custom_mac;
5160
5161   mp->mode = htonl (mode);
5162   mp->lb = htonl (lb);
5163   mp->id = htonl (id);
5164   mp->numa_only = numa_only;
5165
5166   if (custom_mac)
5167     clib_memcpy (mp->mac_address, mac_address, 6);
5168
5169   /* send it... */
5170   S (mp);
5171
5172   /* Wait for a reply... */
5173   W (ret);
5174   return ret;
5175 }
5176
5177 static int
5178 api_bond_create2 (vat_main_t * vam)
5179 {
5180   unformat_input_t *i = vam->input;
5181   vl_api_bond_create2_t *mp;
5182   u8 mac_address[6];
5183   u8 custom_mac = 0;
5184   int ret;
5185   u8 mode;
5186   u8 lb;
5187   u8 mode_is_set = 0;
5188   u32 id = ~0;
5189   u8 numa_only = 0;
5190   u8 gso = 0;
5191
5192   clib_memset (mac_address, 0, sizeof (mac_address));
5193   lb = BOND_LB_L2;
5194
5195   /* Parse args required to build the message */
5196   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5197     {
5198       if (unformat (i, "mode %U", unformat_bond_mode, &mode))
5199         mode_is_set = 1;
5200       else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
5201                && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
5202         ;
5203       else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
5204                          mac_address))
5205         custom_mac = 1;
5206       else if (unformat (i, "numa-only"))
5207         numa_only = 1;
5208       else if (unformat (i, "gso"))
5209         gso = 1;
5210       else if (unformat (i, "id %u", &id))
5211         ;
5212       else
5213         break;
5214     }
5215
5216   if (mode_is_set == 0)
5217     {
5218       errmsg ("Missing bond mode. ");
5219       return -99;
5220     }
5221
5222   /* Construct the API message */
5223   M (BOND_CREATE2, mp);
5224
5225   mp->use_custom_mac = custom_mac;
5226
5227   mp->mode = htonl (mode);
5228   mp->lb = htonl (lb);
5229   mp->id = htonl (id);
5230   mp->numa_only = numa_only;
5231   mp->enable_gso = gso;
5232
5233   if (custom_mac)
5234     clib_memcpy (mp->mac_address, mac_address, 6);
5235
5236   /* send it... */
5237   S (mp);
5238
5239   /* Wait for a reply... */
5240   W (ret);
5241   return ret;
5242 }
5243
5244 static int
5245 api_bond_delete (vat_main_t * vam)
5246 {
5247   unformat_input_t *i = vam->input;
5248   vl_api_bond_delete_t *mp;
5249   u32 sw_if_index = ~0;
5250   u8 sw_if_index_set = 0;
5251   int ret;
5252
5253   /* Parse args required to build the message */
5254   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5255     {
5256       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5257         sw_if_index_set = 1;
5258       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5259         sw_if_index_set = 1;
5260       else
5261         break;
5262     }
5263
5264   if (sw_if_index_set == 0)
5265     {
5266       errmsg ("missing vpp interface name. ");
5267       return -99;
5268     }
5269
5270   /* Construct the API message */
5271   M (BOND_DELETE, mp);
5272
5273   mp->sw_if_index = ntohl (sw_if_index);
5274
5275   /* send it... */
5276   S (mp);
5277
5278   /* Wait for a reply... */
5279   W (ret);
5280   return ret;
5281 }
5282
5283 static int
5284 api_bond_add_member (vat_main_t * vam)
5285 {
5286   unformat_input_t *i = vam->input;
5287   vl_api_bond_add_member_t *mp;
5288   u32 bond_sw_if_index;
5289   int ret;
5290   u8 is_passive;
5291   u8 is_long_timeout;
5292   u32 bond_sw_if_index_is_set = 0;
5293   u32 sw_if_index;
5294   u8 sw_if_index_is_set = 0;
5295
5296   /* Parse args required to build the message */
5297   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5298     {
5299       if (unformat (i, "sw_if_index %d", &sw_if_index))
5300         sw_if_index_is_set = 1;
5301       else if (unformat (i, "bond %u", &bond_sw_if_index))
5302         bond_sw_if_index_is_set = 1;
5303       else if (unformat (i, "passive %d", &is_passive))
5304         ;
5305       else if (unformat (i, "long-timeout %d", &is_long_timeout))
5306         ;
5307       else
5308         break;
5309     }
5310
5311   if (bond_sw_if_index_is_set == 0)
5312     {
5313       errmsg ("Missing bond sw_if_index. ");
5314       return -99;
5315     }
5316   if (sw_if_index_is_set == 0)
5317     {
5318       errmsg ("Missing member sw_if_index. ");
5319       return -99;
5320     }
5321
5322   /* Construct the API message */
5323   M (BOND_ADD_MEMBER, mp);
5324
5325   mp->bond_sw_if_index = ntohl (bond_sw_if_index);
5326   mp->sw_if_index = ntohl (sw_if_index);
5327   mp->is_long_timeout = is_long_timeout;
5328   mp->is_passive = is_passive;
5329
5330   /* send it... */
5331   S (mp);
5332
5333   /* Wait for a reply... */
5334   W (ret);
5335   return ret;
5336 }
5337
5338 static int
5339 api_bond_detach_member (vat_main_t * vam)
5340 {
5341   unformat_input_t *i = vam->input;
5342   vl_api_bond_detach_member_t *mp;
5343   u32 sw_if_index = ~0;
5344   u8 sw_if_index_set = 0;
5345   int ret;
5346
5347   /* Parse args required to build the message */
5348   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5349     {
5350       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5351         sw_if_index_set = 1;
5352       else if (unformat (i, "sw_if_index %d", &sw_if_index))
5353         sw_if_index_set = 1;
5354       else
5355         break;
5356     }
5357
5358   if (sw_if_index_set == 0)
5359     {
5360       errmsg ("missing vpp interface name. ");
5361       return -99;
5362     }
5363
5364   /* Construct the API message */
5365   M (BOND_DETACH_MEMBER, mp);
5366
5367   mp->sw_if_index = ntohl (sw_if_index);
5368
5369   /* send it... */
5370   S (mp);
5371
5372   /* Wait for a reply... */
5373   W (ret);
5374   return ret;
5375 }
5376
5377 static int
5378 api_ip_table_add_del (vat_main_t * vam)
5379 {
5380   unformat_input_t *i = vam->input;
5381   vl_api_ip_table_add_del_t *mp;
5382   u32 table_id = ~0;
5383   u8 is_ipv6 = 0;
5384   u8 is_add = 1;
5385   int ret = 0;
5386
5387   /* Parse args required to build the message */
5388   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5389     {
5390       if (unformat (i, "ipv6"))
5391         is_ipv6 = 1;
5392       else if (unformat (i, "del"))
5393         is_add = 0;
5394       else if (unformat (i, "add"))
5395         is_add = 1;
5396       else if (unformat (i, "table %d", &table_id))
5397         ;
5398       else
5399         {
5400           clib_warning ("parse error '%U'", format_unformat_error, i);
5401           return -99;
5402         }
5403     }
5404
5405   if (~0 == table_id)
5406     {
5407       errmsg ("missing table-ID");
5408       return -99;
5409     }
5410
5411   /* Construct the API message */
5412   M (IP_TABLE_ADD_DEL, mp);
5413
5414   mp->table.table_id = ntohl (table_id);
5415   mp->table.is_ip6 = is_ipv6;
5416   mp->is_add = is_add;
5417
5418   /* send it... */
5419   S (mp);
5420
5421   /* Wait for a reply... */
5422   W (ret);
5423
5424   return ret;
5425 }
5426
5427 uword
5428 unformat_fib_path (unformat_input_t * input, va_list * args)
5429 {
5430   vat_main_t *vam = va_arg (*args, vat_main_t *);
5431   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
5432   u32 weight, preference;
5433   mpls_label_t out_label;
5434
5435   clib_memset (path, 0, sizeof (*path));
5436   path->weight = 1;
5437   path->sw_if_index = ~0;
5438   path->rpf_id = ~0;
5439   path->n_labels = 0;
5440
5441   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5442     {
5443       if (unformat (input, "%U %U",
5444                     unformat_vl_api_ip4_address,
5445                     &path->nh.address.ip4,
5446                     api_unformat_sw_if_index, vam, &path->sw_if_index))
5447         {
5448           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5449         }
5450       else if (unformat (input, "%U %U",
5451                          unformat_vl_api_ip6_address,
5452                          &path->nh.address.ip6,
5453                          api_unformat_sw_if_index, vam, &path->sw_if_index))
5454         {
5455           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5456         }
5457       else if (unformat (input, "weight %u", &weight))
5458         {
5459           path->weight = weight;
5460         }
5461       else if (unformat (input, "preference %u", &preference))
5462         {
5463           path->preference = preference;
5464         }
5465       else if (unformat (input, "%U next-hop-table %d",
5466                          unformat_vl_api_ip4_address,
5467                          &path->nh.address.ip4, &path->table_id))
5468         {
5469           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5470         }
5471       else if (unformat (input, "%U next-hop-table %d",
5472                          unformat_vl_api_ip6_address,
5473                          &path->nh.address.ip6, &path->table_id))
5474         {
5475           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5476         }
5477       else if (unformat (input, "%U",
5478                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
5479         {
5480           /*
5481            * the recursive next-hops are by default in the default table
5482            */
5483           path->table_id = 0;
5484           path->sw_if_index = ~0;
5485           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5486         }
5487       else if (unformat (input, "%U",
5488                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
5489         {
5490           /*
5491            * the recursive next-hops are by default in the default table
5492            */
5493           path->table_id = 0;
5494           path->sw_if_index = ~0;
5495           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5496         }
5497       else if (unformat (input, "resolve-via-host"))
5498         {
5499           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
5500         }
5501       else if (unformat (input, "resolve-via-attached"))
5502         {
5503           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
5504         }
5505       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
5506         {
5507           path->type = FIB_API_PATH_TYPE_LOCAL;
5508           path->sw_if_index = ~0;
5509           path->proto = FIB_API_PATH_NH_PROTO_IP4;
5510         }
5511       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
5512         {
5513           path->type = FIB_API_PATH_TYPE_LOCAL;
5514           path->sw_if_index = ~0;
5515           path->proto = FIB_API_PATH_NH_PROTO_IP6;
5516         }
5517       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
5518         ;
5519       else if (unformat (input, "via-label %d", &path->nh.via_label))
5520         {
5521           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
5522           path->sw_if_index = ~0;
5523         }
5524       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
5525         {
5526           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
5527           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
5528         }
5529       else if (unformat (input, "local"))
5530         {
5531           path->type = FIB_API_PATH_TYPE_LOCAL;
5532         }
5533       else if (unformat (input, "out-labels"))
5534         {
5535           while (unformat (input, "%d", &out_label))
5536             {
5537               path->label_stack[path->n_labels].label = out_label;
5538               path->label_stack[path->n_labels].is_uniform = 0;
5539               path->label_stack[path->n_labels].ttl = 64;
5540               path->n_labels++;
5541             }
5542         }
5543       else if (unformat (input, "via"))
5544         {
5545           /* new path, back up and return */
5546           unformat_put_input (input);
5547           unformat_put_input (input);
5548           unformat_put_input (input);
5549           unformat_put_input (input);
5550           break;
5551         }
5552       else
5553         {
5554           return (0);
5555         }
5556     }
5557
5558   path->proto = ntohl (path->proto);
5559   path->type = ntohl (path->type);
5560   path->flags = ntohl (path->flags);
5561   path->table_id = ntohl (path->table_id);
5562   path->sw_if_index = ntohl (path->sw_if_index);
5563
5564   return (1);
5565 }
5566
5567 static int
5568 api_ip_route_add_del (vat_main_t * vam)
5569 {
5570   unformat_input_t *i = vam->input;
5571   vl_api_ip_route_add_del_t *mp;
5572   u32 vrf_id = 0;
5573   u8 is_add = 1;
5574   u8 is_multipath = 0;
5575   u8 prefix_set = 0;
5576   u8 path_count = 0;
5577   vl_api_prefix_t pfx = { };
5578   vl_api_fib_path_t paths[8];
5579   int count = 1;
5580   int j;
5581   f64 before = 0;
5582   u32 random_add_del = 0;
5583   u32 *random_vector = 0;
5584   u32 random_seed = 0xdeaddabe;
5585
5586   /* Parse args required to build the message */
5587   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5588     {
5589       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5590         prefix_set = 1;
5591       else if (unformat (i, "del"))
5592         is_add = 0;
5593       else if (unformat (i, "add"))
5594         is_add = 1;
5595       else if (unformat (i, "vrf %d", &vrf_id))
5596         ;
5597       else if (unformat (i, "count %d", &count))
5598         ;
5599       else if (unformat (i, "random"))
5600         random_add_del = 1;
5601       else if (unformat (i, "multipath"))
5602         is_multipath = 1;
5603       else if (unformat (i, "seed %d", &random_seed))
5604         ;
5605       else
5606         if (unformat
5607             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5608         {
5609           path_count++;
5610           if (8 == path_count)
5611             {
5612               errmsg ("max 8 paths");
5613               return -99;
5614             }
5615         }
5616       else
5617         {
5618           clib_warning ("parse error '%U'", format_unformat_error, i);
5619           return -99;
5620         }
5621     }
5622
5623   if (!path_count)
5624     {
5625       errmsg ("specify a path; via ...");
5626       return -99;
5627     }
5628   if (prefix_set == 0)
5629     {
5630       errmsg ("missing prefix");
5631       return -99;
5632     }
5633
5634   /* Generate a pile of unique, random routes */
5635   if (random_add_del)
5636     {
5637       ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
5638       u32 this_random_address;
5639       uword *random_hash;
5640
5641       random_hash = hash_create (count, sizeof (uword));
5642
5643       hash_set (random_hash, i->as_u32, 1);
5644       for (j = 0; j <= count; j++)
5645         {
5646           do
5647             {
5648               this_random_address = random_u32 (&random_seed);
5649               this_random_address =
5650                 clib_host_to_net_u32 (this_random_address);
5651             }
5652           while (hash_get (random_hash, this_random_address));
5653           vec_add1 (random_vector, this_random_address);
5654           hash_set (random_hash, this_random_address, 1);
5655         }
5656       hash_free (random_hash);
5657       set_ip4_address (&pfx.address, random_vector[0]);
5658     }
5659
5660   if (count > 1)
5661     {
5662       /* Turn on async mode */
5663       vam->async_mode = 1;
5664       vam->async_errors = 0;
5665       before = vat_time_now (vam);
5666     }
5667
5668   for (j = 0; j < count; j++)
5669     {
5670       /* Construct the API message */
5671       M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5672
5673       mp->is_add = is_add;
5674       mp->is_multipath = is_multipath;
5675
5676       clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5677       mp->route.table_id = ntohl (vrf_id);
5678       mp->route.n_paths = path_count;
5679
5680       clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
5681
5682       if (random_add_del)
5683         set_ip4_address (&pfx.address, random_vector[j + 1]);
5684       else
5685         increment_address (&pfx.address);
5686       /* send it... */
5687       S (mp);
5688       /* If we receive SIGTERM, stop now... */
5689       if (vam->do_exit)
5690         break;
5691     }
5692
5693   /* When testing multiple add/del ops, use a control-ping to sync */
5694   if (count > 1)
5695     {
5696       vl_api_control_ping_t *mp_ping;
5697       f64 after;
5698       f64 timeout;
5699
5700       /* Shut off async mode */
5701       vam->async_mode = 0;
5702
5703       MPING (CONTROL_PING, mp_ping);
5704       S (mp_ping);
5705
5706       timeout = vat_time_now (vam) + 1.0;
5707       while (vat_time_now (vam) < timeout)
5708         if (vam->result_ready == 1)
5709           goto out;
5710       vam->retval = -99;
5711
5712     out:
5713       if (vam->retval == -99)
5714         errmsg ("timeout");
5715
5716       if (vam->async_errors > 0)
5717         {
5718           errmsg ("%d asynchronous errors", vam->async_errors);
5719           vam->retval = -98;
5720         }
5721       vam->async_errors = 0;
5722       after = vat_time_now (vam);
5723
5724       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5725       if (j > 0)
5726         count = j;
5727
5728       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5729              count, after - before, count / (after - before));
5730     }
5731   else
5732     {
5733       int ret;
5734
5735       /* Wait for a reply... */
5736       W (ret);
5737       return ret;
5738     }
5739
5740   /* Return the good/bad news */
5741   return (vam->retval);
5742 }
5743
5744 static int
5745 api_ip_mroute_add_del (vat_main_t * vam)
5746 {
5747   unformat_input_t *i = vam->input;
5748   u8 path_set = 0, prefix_set = 0, is_add = 1;
5749   vl_api_ip_mroute_add_del_t *mp;
5750   mfib_entry_flags_t eflags = 0;
5751   vl_api_mfib_path_t path;
5752   vl_api_mprefix_t pfx = { };
5753   u32 vrf_id = 0;
5754   int ret;
5755
5756   /* Parse args required to build the message */
5757   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5758     {
5759       if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
5760         {
5761           prefix_set = 1;
5762           pfx.grp_address_length = htons (pfx.grp_address_length);
5763         }
5764       else if (unformat (i, "del"))
5765         is_add = 0;
5766       else if (unformat (i, "add"))
5767         is_add = 1;
5768       else if (unformat (i, "vrf %d", &vrf_id))
5769         ;
5770       else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
5771         path.itf_flags = htonl (path.itf_flags);
5772       else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
5773         ;
5774       else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
5775         path_set = 1;
5776       else
5777         {
5778           clib_warning ("parse error '%U'", format_unformat_error, i);
5779           return -99;
5780         }
5781     }
5782
5783   if (prefix_set == 0)
5784     {
5785       errmsg ("missing addresses\n");
5786       return -99;
5787     }
5788   if (path_set == 0)
5789     {
5790       errmsg ("missing path\n");
5791       return -99;
5792     }
5793
5794   /* Construct the API message */
5795   M (IP_MROUTE_ADD_DEL, mp);
5796
5797   mp->is_add = is_add;
5798   mp->is_multipath = 1;
5799
5800   clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
5801   mp->route.table_id = htonl (vrf_id);
5802   mp->route.n_paths = 1;
5803   mp->route.entry_flags = htonl (eflags);
5804
5805   clib_memcpy (&mp->route.paths, &path, sizeof (path));
5806
5807   /* send it... */
5808   S (mp);
5809   /* Wait for a reply... */
5810   W (ret);
5811   return ret;
5812 }
5813
5814 static int
5815 api_mpls_table_add_del (vat_main_t * vam)
5816 {
5817   unformat_input_t *i = vam->input;
5818   vl_api_mpls_table_add_del_t *mp;
5819   u32 table_id = ~0;
5820   u8 is_add = 1;
5821   int ret = 0;
5822
5823   /* Parse args required to build the message */
5824   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5825     {
5826       if (unformat (i, "table %d", &table_id))
5827         ;
5828       else if (unformat (i, "del"))
5829         is_add = 0;
5830       else if (unformat (i, "add"))
5831         is_add = 1;
5832       else
5833         {
5834           clib_warning ("parse error '%U'", format_unformat_error, i);
5835           return -99;
5836         }
5837     }
5838
5839   if (~0 == table_id)
5840     {
5841       errmsg ("missing table-ID");
5842       return -99;
5843     }
5844
5845   /* Construct the API message */
5846   M (MPLS_TABLE_ADD_DEL, mp);
5847
5848   mp->mt_table.mt_table_id = ntohl (table_id);
5849   mp->mt_is_add = is_add;
5850
5851   /* send it... */
5852   S (mp);
5853
5854   /* Wait for a reply... */
5855   W (ret);
5856
5857   return ret;
5858 }
5859
5860 static int
5861 api_mpls_route_add_del (vat_main_t * vam)
5862 {
5863   u8 is_add = 1, path_count = 0, is_multipath = 0, is_eos = 0;
5864   mpls_label_t local_label = MPLS_LABEL_INVALID;
5865   unformat_input_t *i = vam->input;
5866   vl_api_mpls_route_add_del_t *mp;
5867   vl_api_fib_path_t paths[8];
5868   int count = 1, j;
5869   f64 before = 0;
5870
5871   /* Parse args required to build the message */
5872   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5873     {
5874       if (unformat (i, "%d", &local_label))
5875         ;
5876       else if (unformat (i, "eos"))
5877         is_eos = 1;
5878       else if (unformat (i, "non-eos"))
5879         is_eos = 0;
5880       else if (unformat (i, "del"))
5881         is_add = 0;
5882       else if (unformat (i, "add"))
5883         is_add = 1;
5884       else if (unformat (i, "multipath"))
5885         is_multipath = 1;
5886       else if (unformat (i, "count %d", &count))
5887         ;
5888       else
5889         if (unformat
5890             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
5891         {
5892           path_count++;
5893           if (8 == path_count)
5894             {
5895               errmsg ("max 8 paths");
5896               return -99;
5897             }
5898         }
5899       else
5900         {
5901           clib_warning ("parse error '%U'", format_unformat_error, i);
5902           return -99;
5903         }
5904     }
5905
5906   if (!path_count)
5907     {
5908       errmsg ("specify a path; via ...");
5909       return -99;
5910     }
5911
5912   if (MPLS_LABEL_INVALID == local_label)
5913     {
5914       errmsg ("missing label");
5915       return -99;
5916     }
5917
5918   if (count > 1)
5919     {
5920       /* Turn on async mode */
5921       vam->async_mode = 1;
5922       vam->async_errors = 0;
5923       before = vat_time_now (vam);
5924     }
5925
5926   for (j = 0; j < count; j++)
5927     {
5928       /* Construct the API message */
5929       M2 (MPLS_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
5930
5931       mp->mr_is_add = is_add;
5932       mp->mr_is_multipath = is_multipath;
5933
5934       mp->mr_route.mr_label = local_label;
5935       mp->mr_route.mr_eos = is_eos;
5936       mp->mr_route.mr_table_id = 0;
5937       mp->mr_route.mr_n_paths = path_count;
5938
5939       clib_memcpy (&mp->mr_route.mr_paths, paths,
5940                    sizeof (paths[0]) * path_count);
5941
5942       local_label++;
5943
5944       /* send it... */
5945       S (mp);
5946       /* If we receive SIGTERM, stop now... */
5947       if (vam->do_exit)
5948         break;
5949     }
5950
5951   /* When testing multiple add/del ops, use a control-ping to sync */
5952   if (count > 1)
5953     {
5954       vl_api_control_ping_t *mp_ping;
5955       f64 after;
5956       f64 timeout;
5957
5958       /* Shut off async mode */
5959       vam->async_mode = 0;
5960
5961       MPING (CONTROL_PING, mp_ping);
5962       S (mp_ping);
5963
5964       timeout = vat_time_now (vam) + 1.0;
5965       while (vat_time_now (vam) < timeout)
5966         if (vam->result_ready == 1)
5967           goto out;
5968       vam->retval = -99;
5969
5970     out:
5971       if (vam->retval == -99)
5972         errmsg ("timeout");
5973
5974       if (vam->async_errors > 0)
5975         {
5976           errmsg ("%d asynchronous errors", vam->async_errors);
5977           vam->retval = -98;
5978         }
5979       vam->async_errors = 0;
5980       after = vat_time_now (vam);
5981
5982       /* slim chance, but we might have eaten SIGTERM on the first iteration */
5983       if (j > 0)
5984         count = j;
5985
5986       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
5987              count, after - before, count / (after - before));
5988     }
5989   else
5990     {
5991       int ret;
5992
5993       /* Wait for a reply... */
5994       W (ret);
5995       return ret;
5996     }
5997
5998   /* Return the good/bad news */
5999   return (vam->retval);
6000   return (0);
6001 }
6002
6003 static int
6004 api_mpls_ip_bind_unbind (vat_main_t * vam)
6005 {
6006   unformat_input_t *i = vam->input;
6007   vl_api_mpls_ip_bind_unbind_t *mp;
6008   u32 ip_table_id = 0;
6009   u8 is_bind = 1;
6010   vl_api_prefix_t pfx;
6011   u8 prefix_set = 0;
6012   mpls_label_t local_label = MPLS_LABEL_INVALID;
6013   int ret;
6014
6015   /* Parse args required to build the message */
6016   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6017     {
6018       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
6019         prefix_set = 1;
6020       else if (unformat (i, "%d", &local_label))
6021         ;
6022       else if (unformat (i, "table-id %d", &ip_table_id))
6023         ;
6024       else if (unformat (i, "unbind"))
6025         is_bind = 0;
6026       else if (unformat (i, "bind"))
6027         is_bind = 1;
6028       else
6029         {
6030           clib_warning ("parse error '%U'", format_unformat_error, i);
6031           return -99;
6032         }
6033     }
6034
6035   if (!prefix_set)
6036     {
6037       errmsg ("IP prefix not set");
6038       return -99;
6039     }
6040
6041   if (MPLS_LABEL_INVALID == local_label)
6042     {
6043       errmsg ("missing label");
6044       return -99;
6045     }
6046
6047   /* Construct the API message */
6048   M (MPLS_IP_BIND_UNBIND, mp);
6049
6050   mp->mb_is_bind = is_bind;
6051   mp->mb_ip_table_id = ntohl (ip_table_id);
6052   mp->mb_mpls_table_id = 0;
6053   mp->mb_label = ntohl (local_label);
6054   clib_memcpy (&mp->mb_prefix, &pfx, sizeof (pfx));
6055
6056   /* send it... */
6057   S (mp);
6058
6059   /* Wait for a reply... */
6060   W (ret);
6061   return ret;
6062   return (0);
6063 }
6064
6065 static int
6066 api_sr_mpls_policy_add (vat_main_t * vam)
6067 {
6068   unformat_input_t *i = vam->input;
6069   vl_api_sr_mpls_policy_add_t *mp;
6070   u32 bsid = 0;
6071   u32 weight = 1;
6072   u8 type = 0;
6073   u8 n_segments = 0;
6074   u32 sid;
6075   u32 *segments = NULL;
6076   int ret;
6077
6078   /* Parse args required to build the message */
6079   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6080     {
6081       if (unformat (i, "bsid %d", &bsid))
6082         ;
6083       else if (unformat (i, "weight %d", &weight))
6084         ;
6085       else if (unformat (i, "spray"))
6086         type = 1;
6087       else if (unformat (i, "next %d", &sid))
6088         {
6089           n_segments += 1;
6090           vec_add1 (segments, htonl (sid));
6091         }
6092       else
6093         {
6094           clib_warning ("parse error '%U'", format_unformat_error, i);
6095           return -99;
6096         }
6097     }
6098
6099   if (bsid == 0)
6100     {
6101       errmsg ("bsid not set");
6102       return -99;
6103     }
6104
6105   if (n_segments == 0)
6106     {
6107       errmsg ("no sid in segment stack");
6108       return -99;
6109     }
6110
6111   /* Construct the API message */
6112   M2 (SR_MPLS_POLICY_ADD, mp, sizeof (u32) * n_segments);
6113
6114   mp->bsid = htonl (bsid);
6115   mp->weight = htonl (weight);
6116   mp->is_spray = type;
6117   mp->n_segments = n_segments;
6118   memcpy (mp->segments, segments, sizeof (u32) * n_segments);
6119   vec_free (segments);
6120
6121   /* send it... */
6122   S (mp);
6123
6124   /* Wait for a reply... */
6125   W (ret);
6126   return ret;
6127 }
6128
6129 static int
6130 api_sr_mpls_policy_del (vat_main_t * vam)
6131 {
6132   unformat_input_t *i = vam->input;
6133   vl_api_sr_mpls_policy_del_t *mp;
6134   u32 bsid = 0;
6135   int ret;
6136
6137   /* Parse args required to build the message */
6138   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6139     {
6140       if (unformat (i, "bsid %d", &bsid))
6141         ;
6142       else
6143         {
6144           clib_warning ("parse error '%U'", format_unformat_error, i);
6145           return -99;
6146         }
6147     }
6148
6149   if (bsid == 0)
6150     {
6151       errmsg ("bsid not set");
6152       return -99;
6153     }
6154
6155   /* Construct the API message */
6156   M (SR_MPLS_POLICY_DEL, mp);
6157
6158   mp->bsid = htonl (bsid);
6159
6160   /* send it... */
6161   S (mp);
6162
6163   /* Wait for a reply... */
6164   W (ret);
6165   return ret;
6166 }
6167
6168 static int
6169 api_mpls_tunnel_add_del (vat_main_t * vam)
6170 {
6171   unformat_input_t *i = vam->input;
6172   vl_api_mpls_tunnel_add_del_t *mp;
6173
6174   vl_api_fib_path_t paths[8];
6175   u32 sw_if_index = ~0;
6176   u8 path_count = 0;
6177   u8 l2_only = 0;
6178   u8 is_add = 1;
6179   int ret;
6180
6181   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6182     {
6183       if (unformat (i, "add"))
6184         is_add = 1;
6185       else
6186         if (unformat
6187             (i, "del %U", api_unformat_sw_if_index, vam, &sw_if_index))
6188         is_add = 0;
6189       else if (unformat (i, "del sw_if_index %d", &sw_if_index))
6190         is_add = 0;
6191       else if (unformat (i, "l2-only"))
6192         l2_only = 1;
6193       else
6194         if (unformat
6195             (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
6196         {
6197           path_count++;
6198           if (8 == path_count)
6199             {
6200               errmsg ("max 8 paths");
6201               return -99;
6202             }
6203         }
6204       else
6205         {
6206           clib_warning ("parse error '%U'", format_unformat_error, i);
6207           return -99;
6208         }
6209     }
6210
6211   M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
6212
6213   mp->mt_is_add = is_add;
6214   mp->mt_tunnel.mt_sw_if_index = ntohl (sw_if_index);
6215   mp->mt_tunnel.mt_l2_only = l2_only;
6216   mp->mt_tunnel.mt_is_multicast = 0;
6217   mp->mt_tunnel.mt_n_paths = path_count;
6218
6219   clib_memcpy (&mp->mt_tunnel.mt_paths, &paths,
6220                sizeof (paths[0]) * path_count);
6221
6222   S (mp);
6223   W (ret);
6224   return ret;
6225 }
6226
6227 static int
6228 api_sw_interface_set_unnumbered (vat_main_t * vam)
6229 {
6230   unformat_input_t *i = vam->input;
6231   vl_api_sw_interface_set_unnumbered_t *mp;
6232   u32 sw_if_index;
6233   u32 unnum_sw_index = ~0;
6234   u8 is_add = 1;
6235   u8 sw_if_index_set = 0;
6236   int ret;
6237
6238   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6239     {
6240       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6241         sw_if_index_set = 1;
6242       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6243         sw_if_index_set = 1;
6244       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
6245         ;
6246       else if (unformat (i, "del"))
6247         is_add = 0;
6248       else
6249         {
6250           clib_warning ("parse error '%U'", format_unformat_error, i);
6251           return -99;
6252         }
6253     }
6254
6255   if (sw_if_index_set == 0)
6256     {
6257       errmsg ("missing interface name or sw_if_index");
6258       return -99;
6259     }
6260
6261   M (SW_INTERFACE_SET_UNNUMBERED, mp);
6262
6263   mp->sw_if_index = ntohl (sw_if_index);
6264   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
6265   mp->is_add = is_add;
6266
6267   S (mp);
6268   W (ret);
6269   return ret;
6270 }
6271
6272
6273 static int
6274 api_create_vlan_subif (vat_main_t * vam)
6275 {
6276   unformat_input_t *i = vam->input;
6277   vl_api_create_vlan_subif_t *mp;
6278   u32 sw_if_index;
6279   u8 sw_if_index_set = 0;
6280   u32 vlan_id;
6281   u8 vlan_id_set = 0;
6282   int ret;
6283
6284   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6285     {
6286       if (unformat (i, "sw_if_index %d", &sw_if_index))
6287         sw_if_index_set = 1;
6288       else
6289         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6290         sw_if_index_set = 1;
6291       else if (unformat (i, "vlan %d", &vlan_id))
6292         vlan_id_set = 1;
6293       else
6294         {
6295           clib_warning ("parse error '%U'", format_unformat_error, i);
6296           return -99;
6297         }
6298     }
6299
6300   if (sw_if_index_set == 0)
6301     {
6302       errmsg ("missing interface name or sw_if_index");
6303       return -99;
6304     }
6305
6306   if (vlan_id_set == 0)
6307     {
6308       errmsg ("missing vlan_id");
6309       return -99;
6310     }
6311   M (CREATE_VLAN_SUBIF, mp);
6312
6313   mp->sw_if_index = ntohl (sw_if_index);
6314   mp->vlan_id = ntohl (vlan_id);
6315
6316   S (mp);
6317   W (ret);
6318   return ret;
6319 }
6320
6321 #define foreach_create_subif_bit                \
6322 _(no_tags)                                      \
6323 _(one_tag)                                      \
6324 _(two_tags)                                     \
6325 _(dot1ad)                                       \
6326 _(exact_match)                                  \
6327 _(default_sub)                                  \
6328 _(outer_vlan_id_any)                            \
6329 _(inner_vlan_id_any)
6330
6331 #define foreach_create_subif_flag               \
6332 _(0, "no_tags")                                 \
6333 _(1, "one_tag")                                 \
6334 _(2, "two_tags")                                \
6335 _(3, "dot1ad")                                  \
6336 _(4, "exact_match")                             \
6337 _(5, "default_sub")                             \
6338 _(6, "outer_vlan_id_any")                       \
6339 _(7, "inner_vlan_id_any")
6340
6341 static int
6342 api_create_subif (vat_main_t * vam)
6343 {
6344   unformat_input_t *i = vam->input;
6345   vl_api_create_subif_t *mp;
6346   u32 sw_if_index;
6347   u8 sw_if_index_set = 0;
6348   u32 sub_id;
6349   u8 sub_id_set = 0;
6350   u32 __attribute__ ((unused)) no_tags = 0;
6351   u32 __attribute__ ((unused)) one_tag = 0;
6352   u32 __attribute__ ((unused)) two_tags = 0;
6353   u32 __attribute__ ((unused)) dot1ad = 0;
6354   u32 __attribute__ ((unused)) exact_match = 0;
6355   u32 __attribute__ ((unused)) default_sub = 0;
6356   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
6357   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
6358   u32 tmp;
6359   u16 outer_vlan_id = 0;
6360   u16 inner_vlan_id = 0;
6361   int ret;
6362
6363   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6364     {
6365       if (unformat (i, "sw_if_index %d", &sw_if_index))
6366         sw_if_index_set = 1;
6367       else
6368         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6369         sw_if_index_set = 1;
6370       else if (unformat (i, "sub_id %d", &sub_id))
6371         sub_id_set = 1;
6372       else if (unformat (i, "outer_vlan_id %d", &tmp))
6373         outer_vlan_id = tmp;
6374       else if (unformat (i, "inner_vlan_id %d", &tmp))
6375         inner_vlan_id = tmp;
6376
6377 #define _(a) else if (unformat (i, #a)) a = 1 ;
6378       foreach_create_subif_bit
6379 #undef _
6380         else
6381         {
6382           clib_warning ("parse error '%U'", format_unformat_error, i);
6383           return -99;
6384         }
6385     }
6386
6387   if (sw_if_index_set == 0)
6388     {
6389       errmsg ("missing interface name or sw_if_index");
6390       return -99;
6391     }
6392
6393   if (sub_id_set == 0)
6394     {
6395       errmsg ("missing sub_id");
6396       return -99;
6397     }
6398   M (CREATE_SUBIF, mp);
6399
6400   mp->sw_if_index = ntohl (sw_if_index);
6401   mp->sub_id = ntohl (sub_id);
6402
6403 #define _(a,b) mp->sub_if_flags |= (1 << a);
6404   foreach_create_subif_flag;
6405 #undef _
6406
6407   mp->outer_vlan_id = ntohs (outer_vlan_id);
6408   mp->inner_vlan_id = ntohs (inner_vlan_id);
6409
6410   S (mp);
6411   W (ret);
6412   return ret;
6413 }
6414
6415 static int
6416 api_ip_table_replace_begin (vat_main_t * vam)
6417 {
6418   unformat_input_t *i = vam->input;
6419   vl_api_ip_table_replace_begin_t *mp;
6420   u32 table_id = 0;
6421   u8 is_ipv6 = 0;
6422
6423   int ret;
6424   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6425     {
6426       if (unformat (i, "table %d", &table_id))
6427         ;
6428       else if (unformat (i, "ipv6"))
6429         is_ipv6 = 1;
6430       else
6431         {
6432           clib_warning ("parse error '%U'", format_unformat_error, i);
6433           return -99;
6434         }
6435     }
6436
6437   M (IP_TABLE_REPLACE_BEGIN, mp);
6438
6439   mp->table.table_id = ntohl (table_id);
6440   mp->table.is_ip6 = is_ipv6;
6441
6442   S (mp);
6443   W (ret);
6444   return ret;
6445 }
6446
6447 static int
6448 api_ip_table_flush (vat_main_t * vam)
6449 {
6450   unformat_input_t *i = vam->input;
6451   vl_api_ip_table_flush_t *mp;
6452   u32 table_id = 0;
6453   u8 is_ipv6 = 0;
6454
6455   int ret;
6456   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6457     {
6458       if (unformat (i, "table %d", &table_id))
6459         ;
6460       else if (unformat (i, "ipv6"))
6461         is_ipv6 = 1;
6462       else
6463         {
6464           clib_warning ("parse error '%U'", format_unformat_error, i);
6465           return -99;
6466         }
6467     }
6468
6469   M (IP_TABLE_FLUSH, mp);
6470
6471   mp->table.table_id = ntohl (table_id);
6472   mp->table.is_ip6 = is_ipv6;
6473
6474   S (mp);
6475   W (ret);
6476   return ret;
6477 }
6478
6479 static int
6480 api_ip_table_replace_end (vat_main_t * vam)
6481 {
6482   unformat_input_t *i = vam->input;
6483   vl_api_ip_table_replace_end_t *mp;
6484   u32 table_id = 0;
6485   u8 is_ipv6 = 0;
6486
6487   int ret;
6488   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6489     {
6490       if (unformat (i, "table %d", &table_id))
6491         ;
6492       else if (unformat (i, "ipv6"))
6493         is_ipv6 = 1;
6494       else
6495         {
6496           clib_warning ("parse error '%U'", format_unformat_error, i);
6497           return -99;
6498         }
6499     }
6500
6501   M (IP_TABLE_REPLACE_END, mp);
6502
6503   mp->table.table_id = ntohl (table_id);
6504   mp->table.is_ip6 = is_ipv6;
6505
6506   S (mp);
6507   W (ret);
6508   return ret;
6509 }
6510
6511 static int
6512 api_set_ip_flow_hash (vat_main_t * vam)
6513 {
6514   unformat_input_t *i = vam->input;
6515   vl_api_set_ip_flow_hash_t *mp;
6516   u32 vrf_id = 0;
6517   u8 is_ipv6 = 0;
6518   u8 vrf_id_set = 0;
6519   u8 src = 0;
6520   u8 dst = 0;
6521   u8 sport = 0;
6522   u8 dport = 0;
6523   u8 proto = 0;
6524   u8 reverse = 0;
6525   int ret;
6526
6527   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6528     {
6529       if (unformat (i, "vrf %d", &vrf_id))
6530         vrf_id_set = 1;
6531       else if (unformat (i, "ipv6"))
6532         is_ipv6 = 1;
6533       else if (unformat (i, "src"))
6534         src = 1;
6535       else if (unformat (i, "dst"))
6536         dst = 1;
6537       else if (unformat (i, "sport"))
6538         sport = 1;
6539       else if (unformat (i, "dport"))
6540         dport = 1;
6541       else if (unformat (i, "proto"))
6542         proto = 1;
6543       else if (unformat (i, "reverse"))
6544         reverse = 1;
6545
6546       else
6547         {
6548           clib_warning ("parse error '%U'", format_unformat_error, i);
6549           return -99;
6550         }
6551     }
6552
6553   if (vrf_id_set == 0)
6554     {
6555       errmsg ("missing vrf id");
6556       return -99;
6557     }
6558
6559   M (SET_IP_FLOW_HASH, mp);
6560   mp->src = src;
6561   mp->dst = dst;
6562   mp->sport = sport;
6563   mp->dport = dport;
6564   mp->proto = proto;
6565   mp->reverse = reverse;
6566   mp->vrf_id = ntohl (vrf_id);
6567   mp->is_ipv6 = is_ipv6;
6568
6569   S (mp);
6570   W (ret);
6571   return ret;
6572 }
6573
6574 static int
6575 api_sw_interface_ip6_enable_disable (vat_main_t * vam)
6576 {
6577   unformat_input_t *i = vam->input;
6578   vl_api_sw_interface_ip6_enable_disable_t *mp;
6579   u32 sw_if_index;
6580   u8 sw_if_index_set = 0;
6581   u8 enable = 0;
6582   int ret;
6583
6584   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6585     {
6586       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
6587         sw_if_index_set = 1;
6588       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6589         sw_if_index_set = 1;
6590       else if (unformat (i, "enable"))
6591         enable = 1;
6592       else if (unformat (i, "disable"))
6593         enable = 0;
6594       else
6595         {
6596           clib_warning ("parse error '%U'", format_unformat_error, i);
6597           return -99;
6598         }
6599     }
6600
6601   if (sw_if_index_set == 0)
6602     {
6603       errmsg ("missing interface name or sw_if_index");
6604       return -99;
6605     }
6606
6607   M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
6608
6609   mp->sw_if_index = ntohl (sw_if_index);
6610   mp->enable = enable;
6611
6612   S (mp);
6613   W (ret);
6614   return ret;
6615 }
6616
6617
6618 static int
6619 api_l2_patch_add_del (vat_main_t * vam)
6620 {
6621   unformat_input_t *i = vam->input;
6622   vl_api_l2_patch_add_del_t *mp;
6623   u32 rx_sw_if_index;
6624   u8 rx_sw_if_index_set = 0;
6625   u32 tx_sw_if_index;
6626   u8 tx_sw_if_index_set = 0;
6627   u8 is_add = 1;
6628   int ret;
6629
6630   /* Parse args required to build the message */
6631   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6632     {
6633       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
6634         rx_sw_if_index_set = 1;
6635       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
6636         tx_sw_if_index_set = 1;
6637       else if (unformat (i, "rx"))
6638         {
6639           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6640             {
6641               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6642                             &rx_sw_if_index))
6643                 rx_sw_if_index_set = 1;
6644             }
6645           else
6646             break;
6647         }
6648       else if (unformat (i, "tx"))
6649         {
6650           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6651             {
6652               if (unformat (i, "%U", api_unformat_sw_if_index, vam,
6653                             &tx_sw_if_index))
6654                 tx_sw_if_index_set = 1;
6655             }
6656           else
6657             break;
6658         }
6659       else if (unformat (i, "del"))
6660         is_add = 0;
6661       else
6662         break;
6663     }
6664
6665   if (rx_sw_if_index_set == 0)
6666     {
6667       errmsg ("missing rx interface name or rx_sw_if_index");
6668       return -99;
6669     }
6670
6671   if (tx_sw_if_index_set == 0)
6672     {
6673       errmsg ("missing tx interface name or tx_sw_if_index");
6674       return -99;
6675     }
6676
6677   M (L2_PATCH_ADD_DEL, mp);
6678
6679   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
6680   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
6681   mp->is_add = is_add;
6682
6683   S (mp);
6684   W (ret);
6685   return ret;
6686 }
6687
6688 u8 is_del;
6689 u8 localsid_addr[16];
6690 u8 end_psp;
6691 u8 behavior;
6692 u32 sw_if_index;
6693 u32 vlan_index;
6694 u32 fib_table;
6695 u8 nh_addr[16];
6696
6697 static int
6698 api_sr_localsid_add_del (vat_main_t * vam)
6699 {
6700   unformat_input_t *i = vam->input;
6701   vl_api_sr_localsid_add_del_t *mp;
6702
6703   u8 is_del;
6704   ip6_address_t localsid;
6705   u8 end_psp = 0;
6706   u8 behavior = ~0;
6707   u32 sw_if_index;
6708   u32 fib_table = ~(u32) 0;
6709   ip46_address_t nh_addr;
6710   clib_memset (&nh_addr, 0, sizeof (ip46_address_t));
6711
6712   bool nexthop_set = 0;
6713
6714   int ret;
6715
6716   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6717     {
6718       if (unformat (i, "del"))
6719         is_del = 1;
6720       else if (unformat (i, "address %U", unformat_ip6_address, &localsid));
6721       else if (unformat (i, "next-hop %U", unformat_ip46_address, &nh_addr))
6722         nexthop_set = 1;
6723       else if (unformat (i, "behavior %u", &behavior));
6724       else if (unformat (i, "sw_if_index %u", &sw_if_index));
6725       else if (unformat (i, "fib-table %u", &fib_table));
6726       else if (unformat (i, "end.psp %u", &behavior));
6727       else
6728         break;
6729     }
6730
6731   M (SR_LOCALSID_ADD_DEL, mp);
6732
6733   clib_memcpy (mp->localsid, &localsid, sizeof (mp->localsid));
6734
6735   if (nexthop_set)
6736     {
6737       clib_memcpy (&mp->nh_addr.un, &nh_addr, sizeof (mp->nh_addr.un));
6738     }
6739   mp->behavior = behavior;
6740   mp->sw_if_index = ntohl (sw_if_index);
6741   mp->fib_table = ntohl (fib_table);
6742   mp->end_psp = end_psp;
6743   mp->is_del = is_del;
6744
6745   S (mp);
6746   W (ret);
6747   return ret;
6748 }
6749
6750 static int
6751 api_ioam_enable (vat_main_t * vam)
6752 {
6753   unformat_input_t *input = vam->input;
6754   vl_api_ioam_enable_t *mp;
6755   u32 id = 0;
6756   int has_trace_option = 0;
6757   int has_pot_option = 0;
6758   int has_seqno_option = 0;
6759   int has_analyse_option = 0;
6760   int ret;
6761
6762   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6763     {
6764       if (unformat (input, "trace"))
6765         has_trace_option = 1;
6766       else if (unformat (input, "pot"))
6767         has_pot_option = 1;
6768       else if (unformat (input, "seqno"))
6769         has_seqno_option = 1;
6770       else if (unformat (input, "analyse"))
6771         has_analyse_option = 1;
6772       else
6773         break;
6774     }
6775   M (IOAM_ENABLE, mp);
6776   mp->id = htons (id);
6777   mp->seqno = has_seqno_option;
6778   mp->analyse = has_analyse_option;
6779   mp->pot_enable = has_pot_option;
6780   mp->trace_enable = has_trace_option;
6781
6782   S (mp);
6783   W (ret);
6784   return ret;
6785 }
6786
6787
6788 static int
6789 api_ioam_disable (vat_main_t * vam)
6790 {
6791   vl_api_ioam_disable_t *mp;
6792   int ret;
6793
6794   M (IOAM_DISABLE, mp);
6795   S (mp);
6796   W (ret);
6797   return ret;
6798 }
6799
6800 #define foreach_tcp_proto_field                 \
6801 _(src_port)                                     \
6802 _(dst_port)
6803
6804 #define foreach_udp_proto_field                 \
6805 _(src_port)                                     \
6806 _(dst_port)
6807
6808 #define foreach_ip4_proto_field                 \
6809 _(src_address)                                  \
6810 _(dst_address)                                  \
6811 _(tos)                                          \
6812 _(length)                                       \
6813 _(fragment_id)                                  \
6814 _(ttl)                                          \
6815 _(protocol)                                     \
6816 _(checksum)
6817
6818 typedef struct
6819 {
6820   u16 src_port, dst_port;
6821 } tcpudp_header_t;
6822
6823 #if VPP_API_TEST_BUILTIN == 0
6824 uword
6825 unformat_tcp_mask (unformat_input_t * input, va_list * args)
6826 {
6827   u8 **maskp = va_arg (*args, u8 **);
6828   u8 *mask = 0;
6829   u8 found_something = 0;
6830   tcp_header_t *tcp;
6831
6832 #define _(a) u8 a=0;
6833   foreach_tcp_proto_field;
6834 #undef _
6835
6836   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6837     {
6838       if (0);
6839 #define _(a) else if (unformat (input, #a)) a=1;
6840       foreach_tcp_proto_field
6841 #undef _
6842         else
6843         break;
6844     }
6845
6846 #define _(a) found_something += a;
6847   foreach_tcp_proto_field;
6848 #undef _
6849
6850   if (found_something == 0)
6851     return 0;
6852
6853   vec_validate (mask, sizeof (*tcp) - 1);
6854
6855   tcp = (tcp_header_t *) mask;
6856
6857 #define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
6858   foreach_tcp_proto_field;
6859 #undef _
6860
6861   *maskp = mask;
6862   return 1;
6863 }
6864
6865 uword
6866 unformat_udp_mask (unformat_input_t * input, va_list * args)
6867 {
6868   u8 **maskp = va_arg (*args, u8 **);
6869   u8 *mask = 0;
6870   u8 found_something = 0;
6871   udp_header_t *udp;
6872
6873 #define _(a) u8 a=0;
6874   foreach_udp_proto_field;
6875 #undef _
6876
6877   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6878     {
6879       if (0);
6880 #define _(a) else if (unformat (input, #a)) a=1;
6881       foreach_udp_proto_field
6882 #undef _
6883         else
6884         break;
6885     }
6886
6887 #define _(a) found_something += a;
6888   foreach_udp_proto_field;
6889 #undef _
6890
6891   if (found_something == 0)
6892     return 0;
6893
6894   vec_validate (mask, sizeof (*udp) - 1);
6895
6896   udp = (udp_header_t *) mask;
6897
6898 #define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
6899   foreach_udp_proto_field;
6900 #undef _
6901
6902   *maskp = mask;
6903   return 1;
6904 }
6905
6906 uword
6907 unformat_l4_mask (unformat_input_t * input, va_list * args)
6908 {
6909   u8 **maskp = va_arg (*args, u8 **);
6910   u16 src_port = 0, dst_port = 0;
6911   tcpudp_header_t *tcpudp;
6912
6913   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6914     {
6915       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
6916         return 1;
6917       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
6918         return 1;
6919       else if (unformat (input, "src_port"))
6920         src_port = 0xFFFF;
6921       else if (unformat (input, "dst_port"))
6922         dst_port = 0xFFFF;
6923       else
6924         return 0;
6925     }
6926
6927   if (!src_port && !dst_port)
6928     return 0;
6929
6930   u8 *mask = 0;
6931   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
6932
6933   tcpudp = (tcpudp_header_t *) mask;
6934   tcpudp->src_port = src_port;
6935   tcpudp->dst_port = dst_port;
6936
6937   *maskp = mask;
6938
6939   return 1;
6940 }
6941
6942 uword
6943 unformat_ip4_mask (unformat_input_t * input, va_list * args)
6944 {
6945   u8 **maskp = va_arg (*args, u8 **);
6946   u8 *mask = 0;
6947   u8 found_something = 0;
6948   ip4_header_t *ip;
6949
6950 #define _(a) u8 a=0;
6951   foreach_ip4_proto_field;
6952 #undef _
6953   u8 version = 0;
6954   u8 hdr_length = 0;
6955
6956
6957   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6958     {
6959       if (unformat (input, "version"))
6960         version = 1;
6961       else if (unformat (input, "hdr_length"))
6962         hdr_length = 1;
6963       else if (unformat (input, "src"))
6964         src_address = 1;
6965       else if (unformat (input, "dst"))
6966         dst_address = 1;
6967       else if (unformat (input, "proto"))
6968         protocol = 1;
6969
6970 #define _(a) else if (unformat (input, #a)) a=1;
6971       foreach_ip4_proto_field
6972 #undef _
6973         else
6974         break;
6975     }
6976
6977 #define _(a) found_something += a;
6978   foreach_ip4_proto_field;
6979 #undef _
6980
6981   if (found_something == 0)
6982     return 0;
6983
6984   vec_validate (mask, sizeof (*ip) - 1);
6985
6986   ip = (ip4_header_t *) mask;
6987
6988 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
6989   foreach_ip4_proto_field;
6990 #undef _
6991
6992   ip->ip_version_and_header_length = 0;
6993
6994   if (version)
6995     ip->ip_version_and_header_length |= 0xF0;
6996
6997   if (hdr_length)
6998     ip->ip_version_and_header_length |= 0x0F;
6999
7000   *maskp = mask;
7001   return 1;
7002 }
7003
7004 #define foreach_ip6_proto_field                 \
7005 _(src_address)                                  \
7006 _(dst_address)                                  \
7007 _(payload_length)                               \
7008 _(hop_limit)                                    \
7009 _(protocol)
7010
7011 uword
7012 unformat_ip6_mask (unformat_input_t * input, va_list * args)
7013 {
7014   u8 **maskp = va_arg (*args, u8 **);
7015   u8 *mask = 0;
7016   u8 found_something = 0;
7017   ip6_header_t *ip;
7018   u32 ip_version_traffic_class_and_flow_label;
7019
7020 #define _(a) u8 a=0;
7021   foreach_ip6_proto_field;
7022 #undef _
7023   u8 version = 0;
7024   u8 traffic_class = 0;
7025   u8 flow_label = 0;
7026
7027   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7028     {
7029       if (unformat (input, "version"))
7030         version = 1;
7031       else if (unformat (input, "traffic-class"))
7032         traffic_class = 1;
7033       else if (unformat (input, "flow-label"))
7034         flow_label = 1;
7035       else if (unformat (input, "src"))
7036         src_address = 1;
7037       else if (unformat (input, "dst"))
7038         dst_address = 1;
7039       else if (unformat (input, "proto"))
7040         protocol = 1;
7041
7042 #define _(a) else if (unformat (input, #a)) a=1;
7043       foreach_ip6_proto_field
7044 #undef _
7045         else
7046         break;
7047     }
7048
7049 #define _(a) found_something += a;
7050   foreach_ip6_proto_field;
7051 #undef _
7052
7053   if (found_something == 0)
7054     return 0;
7055
7056   vec_validate (mask, sizeof (*ip) - 1);
7057
7058   ip = (ip6_header_t *) mask;
7059
7060 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
7061   foreach_ip6_proto_field;
7062 #undef _
7063
7064   ip_version_traffic_class_and_flow_label = 0;
7065
7066   if (version)
7067     ip_version_traffic_class_and_flow_label |= 0xF0000000;
7068
7069   if (traffic_class)
7070     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
7071
7072   if (flow_label)
7073     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
7074
7075   ip->ip_version_traffic_class_and_flow_label =
7076     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7077
7078   *maskp = mask;
7079   return 1;
7080 }
7081
7082 uword
7083 unformat_l3_mask (unformat_input_t * input, va_list * args)
7084 {
7085   u8 **maskp = va_arg (*args, u8 **);
7086
7087   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7088     {
7089       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
7090         return 1;
7091       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
7092         return 1;
7093       else
7094         break;
7095     }
7096   return 0;
7097 }
7098
7099 uword
7100 unformat_l2_mask (unformat_input_t * input, va_list * args)
7101 {
7102   u8 **maskp = va_arg (*args, u8 **);
7103   u8 *mask = 0;
7104   u8 src = 0;
7105   u8 dst = 0;
7106   u8 proto = 0;
7107   u8 tag1 = 0;
7108   u8 tag2 = 0;
7109   u8 ignore_tag1 = 0;
7110   u8 ignore_tag2 = 0;
7111   u8 cos1 = 0;
7112   u8 cos2 = 0;
7113   u8 dot1q = 0;
7114   u8 dot1ad = 0;
7115   int len = 14;
7116
7117   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7118     {
7119       if (unformat (input, "src"))
7120         src = 1;
7121       else if (unformat (input, "dst"))
7122         dst = 1;
7123       else if (unformat (input, "proto"))
7124         proto = 1;
7125       else if (unformat (input, "tag1"))
7126         tag1 = 1;
7127       else if (unformat (input, "tag2"))
7128         tag2 = 1;
7129       else if (unformat (input, "ignore-tag1"))
7130         ignore_tag1 = 1;
7131       else if (unformat (input, "ignore-tag2"))
7132         ignore_tag2 = 1;
7133       else if (unformat (input, "cos1"))
7134         cos1 = 1;
7135       else if (unformat (input, "cos2"))
7136         cos2 = 1;
7137       else if (unformat (input, "dot1q"))
7138         dot1q = 1;
7139       else if (unformat (input, "dot1ad"))
7140         dot1ad = 1;
7141       else
7142         break;
7143     }
7144   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7145        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7146     return 0;
7147
7148   if (tag1 || ignore_tag1 || cos1 || dot1q)
7149     len = 18;
7150   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7151     len = 22;
7152
7153   vec_validate (mask, len - 1);
7154
7155   if (dst)
7156     clib_memset (mask, 0xff, 6);
7157
7158   if (src)
7159     clib_memset (mask + 6, 0xff, 6);
7160
7161   if (tag2 || dot1ad)
7162     {
7163       /* inner vlan tag */
7164       if (tag2)
7165         {
7166           mask[19] = 0xff;
7167           mask[18] = 0x0f;
7168         }
7169       if (cos2)
7170         mask[18] |= 0xe0;
7171       if (proto)
7172         mask[21] = mask[20] = 0xff;
7173       if (tag1)
7174         {
7175           mask[15] = 0xff;
7176           mask[14] = 0x0f;
7177         }
7178       if (cos1)
7179         mask[14] |= 0xe0;
7180       *maskp = mask;
7181       return 1;
7182     }
7183   if (tag1 | dot1q)
7184     {
7185       if (tag1)
7186         {
7187           mask[15] = 0xff;
7188           mask[14] = 0x0f;
7189         }
7190       if (cos1)
7191         mask[14] |= 0xe0;
7192       if (proto)
7193         mask[16] = mask[17] = 0xff;
7194
7195       *maskp = mask;
7196       return 1;
7197     }
7198   if (cos2)
7199     mask[18] |= 0xe0;
7200   if (cos1)
7201     mask[14] |= 0xe0;
7202   if (proto)
7203     mask[12] = mask[13] = 0xff;
7204
7205   *maskp = mask;
7206   return 1;
7207 }
7208
7209 uword
7210 unformat_classify_mask (unformat_input_t * input, va_list * args)
7211 {
7212   u8 **maskp = va_arg (*args, u8 **);
7213   u32 *skipp = va_arg (*args, u32 *);
7214   u32 *matchp = va_arg (*args, u32 *);
7215   u32 match;
7216   u8 *mask = 0;
7217   u8 *l2 = 0;
7218   u8 *l3 = 0;
7219   u8 *l4 = 0;
7220   int i;
7221
7222   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7223     {
7224       if (unformat (input, "hex %U", unformat_hex_string, &mask))
7225         ;
7226       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7227         ;
7228       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7229         ;
7230       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
7231         ;
7232       else
7233         break;
7234     }
7235
7236   if (l4 && !l3)
7237     {
7238       vec_free (mask);
7239       vec_free (l2);
7240       vec_free (l4);
7241       return 0;
7242     }
7243
7244   if (mask || l2 || l3 || l4)
7245     {
7246       if (l2 || l3 || l4)
7247         {
7248           /* "With a free Ethernet header in every package" */
7249           if (l2 == 0)
7250             vec_validate (l2, 13);
7251           mask = l2;
7252           if (vec_len (l3))
7253             {
7254               vec_append (mask, l3);
7255               vec_free (l3);
7256             }
7257           if (vec_len (l4))
7258             {
7259               vec_append (mask, l4);
7260               vec_free (l4);
7261             }
7262         }
7263
7264       /* Scan forward looking for the first significant mask octet */
7265       for (i = 0; i < vec_len (mask); i++)
7266         if (mask[i])
7267           break;
7268
7269       /* compute (skip, match) params */
7270       *skipp = i / sizeof (u32x4);
7271       vec_delete (mask, *skipp * sizeof (u32x4), 0);
7272
7273       /* Pad mask to an even multiple of the vector size */
7274       while (vec_len (mask) % sizeof (u32x4))
7275         vec_add1 (mask, 0);
7276
7277       match = vec_len (mask) / sizeof (u32x4);
7278
7279       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
7280         {
7281           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
7282           if (*tmp || *(tmp + 1))
7283             break;
7284           match--;
7285         }
7286       if (match == 0)
7287         clib_warning ("BUG: match 0");
7288
7289       _vec_len (mask) = match * sizeof (u32x4);
7290
7291       *matchp = match;
7292       *maskp = mask;
7293
7294       return 1;
7295     }
7296
7297   return 0;
7298 }
7299 #endif /* VPP_API_TEST_BUILTIN */
7300
7301 #define foreach_l2_next                         \
7302 _(drop, DROP)                                   \
7303 _(ethernet, ETHERNET_INPUT)                     \
7304 _(ip4, IP4_INPUT)                               \
7305 _(ip6, IP6_INPUT)
7306
7307 uword
7308 unformat_l2_next_index (unformat_input_t * input, va_list * args)
7309 {
7310   u32 *miss_next_indexp = va_arg (*args, u32 *);
7311   u32 next_index = 0;
7312   u32 tmp;
7313
7314 #define _(n,N) \
7315   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
7316   foreach_l2_next;
7317 #undef _
7318
7319   if (unformat (input, "%d", &tmp))
7320     {
7321       next_index = tmp;
7322       goto out;
7323     }
7324
7325   return 0;
7326
7327 out:
7328   *miss_next_indexp = next_index;
7329   return 1;
7330 }
7331
7332 #define foreach_ip_next                         \
7333 _(drop, DROP)                                   \
7334 _(local, LOCAL)                                 \
7335 _(rewrite, REWRITE)
7336
7337 uword
7338 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
7339 {
7340   u32 *miss_next_indexp = va_arg (*args, u32 *);
7341   u32 next_index = 0;
7342   u32 tmp;
7343
7344 #define _(n,N) \
7345   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
7346   foreach_ip_next;
7347 #undef _
7348
7349   if (unformat (input, "%d", &tmp))
7350     {
7351       next_index = tmp;
7352       goto out;
7353     }
7354
7355   return 0;
7356
7357 out:
7358   *miss_next_indexp = next_index;
7359   return 1;
7360 }
7361
7362 #define foreach_acl_next                        \
7363 _(deny, DENY)
7364
7365 uword
7366 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
7367 {
7368   u32 *miss_next_indexp = va_arg (*args, u32 *);
7369   u32 next_index = 0;
7370   u32 tmp;
7371
7372 #define _(n,N) \
7373   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
7374   foreach_acl_next;
7375 #undef _
7376
7377   if (unformat (input, "permit"))
7378     {
7379       next_index = ~0;
7380       goto out;
7381     }
7382   else if (unformat (input, "%d", &tmp))
7383     {
7384       next_index = tmp;
7385       goto out;
7386     }
7387
7388   return 0;
7389
7390 out:
7391   *miss_next_indexp = next_index;
7392   return 1;
7393 }
7394
7395 uword
7396 unformat_policer_precolor (unformat_input_t * input, va_list * args)
7397 {
7398   u32 *r = va_arg (*args, u32 *);
7399
7400   if (unformat (input, "conform-color"))
7401     *r = POLICE_CONFORM;
7402   else if (unformat (input, "exceed-color"))
7403     *r = POLICE_EXCEED;
7404   else
7405     return 0;
7406
7407   return 1;
7408 }
7409
7410 #if VPP_API_TEST_BUILTIN == 0
7411 uword
7412 unformat_l4_match (unformat_input_t * input, va_list * args)
7413 {
7414   u8 **matchp = va_arg (*args, u8 **);
7415
7416   u8 *proto_header = 0;
7417   int src_port = 0;
7418   int dst_port = 0;
7419
7420   tcpudp_header_t h;
7421
7422   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7423     {
7424       if (unformat (input, "src_port %d", &src_port))
7425         ;
7426       else if (unformat (input, "dst_port %d", &dst_port))
7427         ;
7428       else
7429         return 0;
7430     }
7431
7432   h.src_port = clib_host_to_net_u16 (src_port);
7433   h.dst_port = clib_host_to_net_u16 (dst_port);
7434   vec_validate (proto_header, sizeof (h) - 1);
7435   memcpy (proto_header, &h, sizeof (h));
7436
7437   *matchp = proto_header;
7438
7439   return 1;
7440 }
7441
7442 uword
7443 unformat_ip4_match (unformat_input_t * input, va_list * args)
7444 {
7445   u8 **matchp = va_arg (*args, u8 **);
7446   u8 *match = 0;
7447   ip4_header_t *ip;
7448   int version = 0;
7449   u32 version_val;
7450   int hdr_length = 0;
7451   u32 hdr_length_val;
7452   int src = 0, dst = 0;
7453   ip4_address_t src_val, dst_val;
7454   int proto = 0;
7455   u32 proto_val;
7456   int tos = 0;
7457   u32 tos_val;
7458   int length = 0;
7459   u32 length_val;
7460   int fragment_id = 0;
7461   u32 fragment_id_val;
7462   int ttl = 0;
7463   int ttl_val;
7464   int checksum = 0;
7465   u32 checksum_val;
7466
7467   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7468     {
7469       if (unformat (input, "version %d", &version_val))
7470         version = 1;
7471       else if (unformat (input, "hdr_length %d", &hdr_length_val))
7472         hdr_length = 1;
7473       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
7474         src = 1;
7475       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
7476         dst = 1;
7477       else if (unformat (input, "proto %d", &proto_val))
7478         proto = 1;
7479       else if (unformat (input, "tos %d", &tos_val))
7480         tos = 1;
7481       else if (unformat (input, "length %d", &length_val))
7482         length = 1;
7483       else if (unformat (input, "fragment_id %d", &fragment_id_val))
7484         fragment_id = 1;
7485       else if (unformat (input, "ttl %d", &ttl_val))
7486         ttl = 1;
7487       else if (unformat (input, "checksum %d", &checksum_val))
7488         checksum = 1;
7489       else
7490         break;
7491     }
7492
7493   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
7494       + ttl + checksum == 0)
7495     return 0;
7496
7497   /*
7498    * Aligned because we use the real comparison functions
7499    */
7500   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7501
7502   ip = (ip4_header_t *) match;
7503
7504   /* These are realistically matched in practice */
7505   if (src)
7506     ip->src_address.as_u32 = src_val.as_u32;
7507
7508   if (dst)
7509     ip->dst_address.as_u32 = dst_val.as_u32;
7510
7511   if (proto)
7512     ip->protocol = proto_val;
7513
7514
7515   /* These are not, but they're included for completeness */
7516   if (version)
7517     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
7518
7519   if (hdr_length)
7520     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
7521
7522   if (tos)
7523     ip->tos = tos_val;
7524
7525   if (length)
7526     ip->length = clib_host_to_net_u16 (length_val);
7527
7528   if (ttl)
7529     ip->ttl = ttl_val;
7530
7531   if (checksum)
7532     ip->checksum = clib_host_to_net_u16 (checksum_val);
7533
7534   *matchp = match;
7535   return 1;
7536 }
7537
7538 uword
7539 unformat_ip6_match (unformat_input_t * input, va_list * args)
7540 {
7541   u8 **matchp = va_arg (*args, u8 **);
7542   u8 *match = 0;
7543   ip6_header_t *ip;
7544   int version = 0;
7545   u32 version_val;
7546   u8 traffic_class = 0;
7547   u32 traffic_class_val = 0;
7548   u8 flow_label = 0;
7549   u8 flow_label_val;
7550   int src = 0, dst = 0;
7551   ip6_address_t src_val, dst_val;
7552   int proto = 0;
7553   u32 proto_val;
7554   int payload_length = 0;
7555   u32 payload_length_val;
7556   int hop_limit = 0;
7557   int hop_limit_val;
7558   u32 ip_version_traffic_class_and_flow_label;
7559
7560   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7561     {
7562       if (unformat (input, "version %d", &version_val))
7563         version = 1;
7564       else if (unformat (input, "traffic_class %d", &traffic_class_val))
7565         traffic_class = 1;
7566       else if (unformat (input, "flow_label %d", &flow_label_val))
7567         flow_label = 1;
7568       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
7569         src = 1;
7570       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
7571         dst = 1;
7572       else if (unformat (input, "proto %d", &proto_val))
7573         proto = 1;
7574       else if (unformat (input, "payload_length %d", &payload_length_val))
7575         payload_length = 1;
7576       else if (unformat (input, "hop_limit %d", &hop_limit_val))
7577         hop_limit = 1;
7578       else
7579         break;
7580     }
7581
7582   if (version + traffic_class + flow_label + src + dst + proto +
7583       payload_length + hop_limit == 0)
7584     return 0;
7585
7586   /*
7587    * Aligned because we use the real comparison functions
7588    */
7589   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
7590
7591   ip = (ip6_header_t *) match;
7592
7593   if (src)
7594     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
7595
7596   if (dst)
7597     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
7598
7599   if (proto)
7600     ip->protocol = proto_val;
7601
7602   ip_version_traffic_class_and_flow_label = 0;
7603
7604   if (version)
7605     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
7606
7607   if (traffic_class)
7608     ip_version_traffic_class_and_flow_label |=
7609       (traffic_class_val & 0xFF) << 20;
7610
7611   if (flow_label)
7612     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
7613
7614   ip->ip_version_traffic_class_and_flow_label =
7615     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7616
7617   if (payload_length)
7618     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
7619
7620   if (hop_limit)
7621     ip->hop_limit = hop_limit_val;
7622
7623   *matchp = match;
7624   return 1;
7625 }
7626
7627 uword
7628 unformat_l3_match (unformat_input_t * input, va_list * args)
7629 {
7630   u8 **matchp = va_arg (*args, u8 **);
7631
7632   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7633     {
7634       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
7635         return 1;
7636       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
7637         return 1;
7638       else
7639         break;
7640     }
7641   return 0;
7642 }
7643
7644 uword
7645 unformat_vlan_tag (unformat_input_t * input, va_list * args)
7646 {
7647   u8 *tagp = va_arg (*args, u8 *);
7648   u32 tag;
7649
7650   if (unformat (input, "%d", &tag))
7651     {
7652       tagp[0] = (tag >> 8) & 0x0F;
7653       tagp[1] = tag & 0xFF;
7654       return 1;
7655     }
7656
7657   return 0;
7658 }
7659
7660 uword
7661 unformat_l2_match (unformat_input_t * input, va_list * args)
7662 {
7663   u8 **matchp = va_arg (*args, u8 **);
7664   u8 *match = 0;
7665   u8 src = 0;
7666   u8 src_val[6];
7667   u8 dst = 0;
7668   u8 dst_val[6];
7669   u8 proto = 0;
7670   u16 proto_val;
7671   u8 tag1 = 0;
7672   u8 tag1_val[2];
7673   u8 tag2 = 0;
7674   u8 tag2_val[2];
7675   int len = 14;
7676   u8 ignore_tag1 = 0;
7677   u8 ignore_tag2 = 0;
7678   u8 cos1 = 0;
7679   u8 cos2 = 0;
7680   u32 cos1_val = 0;
7681   u32 cos2_val = 0;
7682
7683   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7684     {
7685       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
7686         src = 1;
7687       else
7688         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
7689         dst = 1;
7690       else if (unformat (input, "proto %U",
7691                          unformat_ethernet_type_host_byte_order, &proto_val))
7692         proto = 1;
7693       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
7694         tag1 = 1;
7695       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
7696         tag2 = 1;
7697       else if (unformat (input, "ignore-tag1"))
7698         ignore_tag1 = 1;
7699       else if (unformat (input, "ignore-tag2"))
7700         ignore_tag2 = 1;
7701       else if (unformat (input, "cos1 %d", &cos1_val))
7702         cos1 = 1;
7703       else if (unformat (input, "cos2 %d", &cos2_val))
7704         cos2 = 1;
7705       else
7706         break;
7707     }
7708   if ((src + dst + proto + tag1 + tag2 +
7709        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7710     return 0;
7711
7712   if (tag1 || ignore_tag1 || cos1)
7713     len = 18;
7714   if (tag2 || ignore_tag2 || cos2)
7715     len = 22;
7716
7717   vec_validate_aligned (match, len - 1, sizeof (u32x4));
7718
7719   if (dst)
7720     clib_memcpy (match, dst_val, 6);
7721
7722   if (src)
7723     clib_memcpy (match + 6, src_val, 6);
7724
7725   if (tag2)
7726     {
7727       /* inner vlan tag */
7728       match[19] = tag2_val[1];
7729       match[18] = tag2_val[0];
7730       if (cos2)
7731         match[18] |= (cos2_val & 0x7) << 5;
7732       if (proto)
7733         {
7734           match[21] = proto_val & 0xff;
7735           match[20] = proto_val >> 8;
7736         }
7737       if (tag1)
7738         {
7739           match[15] = tag1_val[1];
7740           match[14] = tag1_val[0];
7741         }
7742       if (cos1)
7743         match[14] |= (cos1_val & 0x7) << 5;
7744       *matchp = match;
7745       return 1;
7746     }
7747   if (tag1)
7748     {
7749       match[15] = tag1_val[1];
7750       match[14] = tag1_val[0];
7751       if (proto)
7752         {
7753           match[17] = proto_val & 0xff;
7754           match[16] = proto_val >> 8;
7755         }
7756       if (cos1)
7757         match[14] |= (cos1_val & 0x7) << 5;
7758
7759       *matchp = match;
7760       return 1;
7761     }
7762   if (cos2)
7763     match[18] |= (cos2_val & 0x7) << 5;
7764   if (cos1)
7765     match[14] |= (cos1_val & 0x7) << 5;
7766   if (proto)
7767     {
7768       match[13] = proto_val & 0xff;
7769       match[12] = proto_val >> 8;
7770     }
7771
7772   *matchp = match;
7773   return 1;
7774 }
7775
7776 uword
7777 unformat_qos_source (unformat_input_t * input, va_list * args)
7778 {
7779   int *qs = va_arg (*args, int *);
7780
7781   if (unformat (input, "ip"))
7782     *qs = QOS_SOURCE_IP;
7783   else if (unformat (input, "mpls"))
7784     *qs = QOS_SOURCE_MPLS;
7785   else if (unformat (input, "ext"))
7786     *qs = QOS_SOURCE_EXT;
7787   else if (unformat (input, "vlan"))
7788     *qs = QOS_SOURCE_VLAN;
7789   else
7790     return 0;
7791
7792   return 1;
7793 }
7794 #endif
7795
7796 uword
7797 api_unformat_classify_match (unformat_input_t * input, va_list * args)
7798 {
7799   u8 **matchp = va_arg (*args, u8 **);
7800   u32 skip_n_vectors = va_arg (*args, u32);
7801   u32 match_n_vectors = va_arg (*args, u32);
7802
7803   u8 *match = 0;
7804   u8 *l2 = 0;
7805   u8 *l3 = 0;
7806   u8 *l4 = 0;
7807
7808   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7809     {
7810       if (unformat (input, "hex %U", unformat_hex_string, &match))
7811         ;
7812       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
7813         ;
7814       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
7815         ;
7816       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
7817         ;
7818       else
7819         break;
7820     }
7821
7822   if (l4 && !l3)
7823     {
7824       vec_free (match);
7825       vec_free (l2);
7826       vec_free (l4);
7827       return 0;
7828     }
7829
7830   if (match || l2 || l3 || l4)
7831     {
7832       if (l2 || l3 || l4)
7833         {
7834           /* "Win a free Ethernet header in every packet" */
7835           if (l2 == 0)
7836             vec_validate_aligned (l2, 13, sizeof (u32x4));
7837           match = l2;
7838           if (vec_len (l3))
7839             {
7840               vec_append_aligned (match, l3, sizeof (u32x4));
7841               vec_free (l3);
7842             }
7843           if (vec_len (l4))
7844             {
7845               vec_append_aligned (match, l4, sizeof (u32x4));
7846               vec_free (l4);
7847             }
7848         }
7849
7850       /* Make sure the vector is big enough even if key is all 0's */
7851       vec_validate_aligned
7852         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
7853          sizeof (u32x4));
7854
7855       /* Set size, include skipped vectors */
7856       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
7857
7858       *matchp = match;
7859
7860       return 1;
7861     }
7862
7863   return 0;
7864 }
7865
7866 static int
7867 api_get_node_index (vat_main_t * vam)
7868 {
7869   unformat_input_t *i = vam->input;
7870   vl_api_get_node_index_t *mp;
7871   u8 *name = 0;
7872   int ret;
7873
7874   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7875     {
7876       if (unformat (i, "node %s", &name))
7877         ;
7878       else
7879         break;
7880     }
7881   if (name == 0)
7882     {
7883       errmsg ("node name required");
7884       return -99;
7885     }
7886   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
7887     {
7888       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7889       return -99;
7890     }
7891
7892   M (GET_NODE_INDEX, mp);
7893   clib_memcpy (mp->node_name, name, vec_len (name));
7894   vec_free (name);
7895
7896   S (mp);
7897   W (ret);
7898   return ret;
7899 }
7900
7901 static int
7902 api_get_next_index (vat_main_t * vam)
7903 {
7904   unformat_input_t *i = vam->input;
7905   vl_api_get_next_index_t *mp;
7906   u8 *node_name = 0, *next_node_name = 0;
7907   int ret;
7908
7909   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7910     {
7911       if (unformat (i, "node-name %s", &node_name))
7912         ;
7913       else if (unformat (i, "next-node-name %s", &next_node_name))
7914         break;
7915     }
7916
7917   if (node_name == 0)
7918     {
7919       errmsg ("node name required");
7920       return -99;
7921     }
7922   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
7923     {
7924       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7925       return -99;
7926     }
7927
7928   if (next_node_name == 0)
7929     {
7930       errmsg ("next node name required");
7931       return -99;
7932     }
7933   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
7934     {
7935       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
7936       return -99;
7937     }
7938
7939   M (GET_NEXT_INDEX, mp);
7940   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
7941   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
7942   vec_free (node_name);
7943   vec_free (next_node_name);
7944
7945   S (mp);
7946   W (ret);
7947   return ret;
7948 }
7949
7950 static int
7951 api_add_node_next (vat_main_t * vam)
7952 {
7953   unformat_input_t *i = vam->input;
7954   vl_api_add_node_next_t *mp;
7955   u8 *name = 0;
7956   u8 *next = 0;
7957   int ret;
7958
7959   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
7960     {
7961       if (unformat (i, "node %s", &name))
7962         ;
7963       else if (unformat (i, "next %s", &next))
7964         ;
7965       else
7966         break;
7967     }
7968   if (name == 0)
7969     {
7970       errmsg ("node name required");
7971       return -99;
7972     }
7973   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
7974     {
7975       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
7976       return -99;
7977     }
7978   if (next == 0)
7979     {
7980       errmsg ("next node required");
7981       return -99;
7982     }
7983   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
7984     {
7985       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
7986       return -99;
7987     }
7988
7989   M (ADD_NODE_NEXT, mp);
7990   clib_memcpy (mp->node_name, name, vec_len (name));
7991   clib_memcpy (mp->next_name, next, vec_len (next));
7992   vec_free (name);
7993   vec_free (next);
7994
7995   S (mp);
7996   W (ret);
7997   return ret;
7998 }
7999
8000 static void vl_api_sw_interface_tap_v2_details_t_handler
8001   (vl_api_sw_interface_tap_v2_details_t * mp)
8002 {
8003   vat_main_t *vam = &vat_main;
8004
8005   u8 *ip4 =
8006     format (0, "%U/%d", format_ip4_address, mp->host_ip4_prefix.address,
8007             mp->host_ip4_prefix.len);
8008   u8 *ip6 =
8009     format (0, "%U/%d", format_ip6_address, mp->host_ip6_prefix.address,
8010             mp->host_ip6_prefix.len);
8011
8012   print (vam->ofp,
8013          "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s 0x%-08x",
8014          mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id),
8015          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
8016          format_ethernet_address, mp->host_mac_addr, mp->host_namespace,
8017          mp->host_bridge, ip4, ip6, ntohl (mp->tap_flags));
8018
8019   vec_free (ip4);
8020   vec_free (ip6);
8021 }
8022
8023 static void vl_api_sw_interface_tap_v2_details_t_handler_json
8024   (vl_api_sw_interface_tap_v2_details_t * mp)
8025 {
8026   vat_main_t *vam = &vat_main;
8027   vat_json_node_t *node = NULL;
8028
8029   if (VAT_JSON_ARRAY != vam->json_tree.type)
8030     {
8031       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8032       vat_json_init_array (&vam->json_tree);
8033     }
8034   node = vat_json_array_add (&vam->json_tree);
8035
8036   vat_json_init_object (node);
8037   vat_json_object_add_uint (node, "id", ntohl (mp->id));
8038   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8039   vat_json_object_add_uint (node, "tap_flags", ntohl (mp->tap_flags));
8040   vat_json_object_add_string_copy (node, "dev_name", mp->dev_name);
8041   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
8042   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
8043   vat_json_object_add_string_copy (node, "host_mac_addr",
8044                                    format (0, "%U", format_ethernet_address,
8045                                            &mp->host_mac_addr));
8046   vat_json_object_add_string_copy (node, "host_namespace",
8047                                    mp->host_namespace);
8048   vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge);
8049   vat_json_object_add_string_copy (node, "host_ip4_addr",
8050                                    format (0, "%U/%d", format_ip4_address,
8051                                            mp->host_ip4_prefix.address,
8052                                            mp->host_ip4_prefix.len));
8053   vat_json_object_add_string_copy (node, "host_ip6_prefix",
8054                                    format (0, "%U/%d", format_ip6_address,
8055                                            mp->host_ip6_prefix.address,
8056                                            mp->host_ip6_prefix.len));
8057
8058 }
8059
8060 static int
8061 api_sw_interface_tap_v2_dump (vat_main_t * vam)
8062 {
8063   vl_api_sw_interface_tap_v2_dump_t *mp;
8064   vl_api_control_ping_t *mp_ping;
8065   int ret;
8066
8067   print (vam->ofp,
8068          "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s",
8069          "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz",
8070          "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr",
8071          "host_ip6_addr");
8072
8073   /* Get list of tap interfaces */
8074   M (SW_INTERFACE_TAP_V2_DUMP, mp);
8075   S (mp);
8076
8077   /* Use a control ping for synchronization */
8078   MPING (CONTROL_PING, mp_ping);
8079   S (mp_ping);
8080
8081   W (ret);
8082   return ret;
8083 }
8084
8085 static void vl_api_sw_interface_virtio_pci_details_t_handler
8086   (vl_api_sw_interface_virtio_pci_details_t * mp)
8087 {
8088   vat_main_t *vam = &vat_main;
8089
8090   typedef union
8091   {
8092     struct
8093     {
8094       u16 domain;
8095       u8 bus;
8096       u8 slot:5;
8097       u8 function:3;
8098     };
8099     u32 as_u32;
8100   } pci_addr_t;
8101   pci_addr_t addr;
8102
8103   addr.domain = ntohs (mp->pci_addr.domain);
8104   addr.bus = mp->pci_addr.bus;
8105   addr.slot = mp->pci_addr.slot;
8106   addr.function = mp->pci_addr.function;
8107
8108   u8 *pci_addr = format (0, "%04x:%02x:%02x.%x", addr.domain, addr.bus,
8109                          addr.slot, addr.function);
8110
8111   print (vam->ofp,
8112          "\n%-12s %-12d %-12d %-12d %-17U 0x%-08llx",
8113          pci_addr, ntohl (mp->sw_if_index),
8114          ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz),
8115          format_ethernet_address, mp->mac_addr,
8116          clib_net_to_host_u64 (mp->features));
8117   vec_free (pci_addr);
8118 }
8119
8120 static void vl_api_sw_interface_virtio_pci_details_t_handler_json
8121   (vl_api_sw_interface_virtio_pci_details_t * mp)
8122 {
8123   vat_main_t *vam = &vat_main;
8124   vat_json_node_t *node = NULL;
8125   vlib_pci_addr_t pci_addr;
8126
8127   if (VAT_JSON_ARRAY != vam->json_tree.type)
8128     {
8129       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8130       vat_json_init_array (&vam->json_tree);
8131     }
8132   node = vat_json_array_add (&vam->json_tree);
8133
8134   pci_addr.domain = ntohs (mp->pci_addr.domain);
8135   pci_addr.bus = mp->pci_addr.bus;
8136   pci_addr.slot = mp->pci_addr.slot;
8137   pci_addr.function = mp->pci_addr.function;
8138
8139   vat_json_init_object (node);
8140   vat_json_object_add_uint (node, "pci-addr", pci_addr.as_u32);
8141   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8142   vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz));
8143   vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz));
8144   vat_json_object_add_uint (node, "features",
8145                             clib_net_to_host_u64 (mp->features));
8146   vat_json_object_add_string_copy (node, "mac_addr",
8147                                    format (0, "%U", format_ethernet_address,
8148                                            &mp->mac_addr));
8149 }
8150
8151 static int
8152 api_sw_interface_virtio_pci_dump (vat_main_t * vam)
8153 {
8154   vl_api_sw_interface_virtio_pci_dump_t *mp;
8155   vl_api_control_ping_t *mp_ping;
8156   int ret;
8157
8158   print (vam->ofp,
8159          "\n%-12s %-12s %-12s %-12s %-17s %-08s",
8160          "pci_addr", "sw_if_index", "rx_ring_sz", "tx_ring_sz",
8161          "mac_addr", "features");
8162
8163   /* Get list of tap interfaces */
8164   M (SW_INTERFACE_VIRTIO_PCI_DUMP, mp);
8165   S (mp);
8166
8167   /* Use a control ping for synchronization */
8168   MPING (CONTROL_PING, mp_ping);
8169   S (mp_ping);
8170
8171   W (ret);
8172   return ret;
8173 }
8174
8175 static int
8176 api_l2_fib_clear_table (vat_main_t * vam)
8177 {
8178 //  unformat_input_t * i = vam->input;
8179   vl_api_l2_fib_clear_table_t *mp;
8180   int ret;
8181
8182   M (L2_FIB_CLEAR_TABLE, mp);
8183
8184   S (mp);
8185   W (ret);
8186   return ret;
8187 }
8188
8189 static int
8190 api_l2_interface_efp_filter (vat_main_t * vam)
8191 {
8192   unformat_input_t *i = vam->input;
8193   vl_api_l2_interface_efp_filter_t *mp;
8194   u32 sw_if_index;
8195   u8 enable = 1;
8196   u8 sw_if_index_set = 0;
8197   int ret;
8198
8199   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8200     {
8201       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8202         sw_if_index_set = 1;
8203       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8204         sw_if_index_set = 1;
8205       else if (unformat (i, "enable"))
8206         enable = 1;
8207       else if (unformat (i, "disable"))
8208         enable = 0;
8209       else
8210         {
8211           clib_warning ("parse error '%U'", format_unformat_error, i);
8212           return -99;
8213         }
8214     }
8215
8216   if (sw_if_index_set == 0)
8217     {
8218       errmsg ("missing sw_if_index");
8219       return -99;
8220     }
8221
8222   M (L2_INTERFACE_EFP_FILTER, mp);
8223
8224   mp->sw_if_index = ntohl (sw_if_index);
8225   mp->enable_disable = enable;
8226
8227   S (mp);
8228   W (ret);
8229   return ret;
8230 }
8231
8232 #define foreach_vtr_op                          \
8233 _("disable",  L2_VTR_DISABLED)                  \
8234 _("push-1",  L2_VTR_PUSH_1)                     \
8235 _("push-2",  L2_VTR_PUSH_2)                     \
8236 _("pop-1",  L2_VTR_POP_1)                       \
8237 _("pop-2",  L2_VTR_POP_2)                       \
8238 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
8239 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
8240 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
8241 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
8242
8243 static int
8244 api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
8245 {
8246   unformat_input_t *i = vam->input;
8247   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
8248   u32 sw_if_index;
8249   u8 sw_if_index_set = 0;
8250   u8 vtr_op_set = 0;
8251   u32 vtr_op = 0;
8252   u32 push_dot1q = 1;
8253   u32 tag1 = ~0;
8254   u32 tag2 = ~0;
8255   int ret;
8256
8257   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8258     {
8259       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8260         sw_if_index_set = 1;
8261       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8262         sw_if_index_set = 1;
8263       else if (unformat (i, "vtr_op %d", &vtr_op))
8264         vtr_op_set = 1;
8265 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
8266       foreach_vtr_op
8267 #undef _
8268         else if (unformat (i, "push_dot1q %d", &push_dot1q))
8269         ;
8270       else if (unformat (i, "tag1 %d", &tag1))
8271         ;
8272       else if (unformat (i, "tag2 %d", &tag2))
8273         ;
8274       else
8275         {
8276           clib_warning ("parse error '%U'", format_unformat_error, i);
8277           return -99;
8278         }
8279     }
8280
8281   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
8282     {
8283       errmsg ("missing vtr operation or sw_if_index");
8284       return -99;
8285     }
8286
8287   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
8288   mp->sw_if_index = ntohl (sw_if_index);
8289   mp->vtr_op = ntohl (vtr_op);
8290   mp->push_dot1q = ntohl (push_dot1q);
8291   mp->tag1 = ntohl (tag1);
8292   mp->tag2 = ntohl (tag2);
8293
8294   S (mp);
8295   W (ret);
8296   return ret;
8297 }
8298
8299 static int
8300 api_create_vhost_user_if (vat_main_t * vam)
8301 {
8302   unformat_input_t *i = vam->input;
8303   vl_api_create_vhost_user_if_t *mp;
8304   u8 *file_name;
8305   u8 is_server = 0;
8306   u8 file_name_set = 0;
8307   u32 custom_dev_instance = ~0;
8308   u8 hwaddr[6];
8309   u8 use_custom_mac = 0;
8310   u8 disable_mrg_rxbuf = 0;
8311   u8 disable_indirect_desc = 0;
8312   u8 *tag = 0;
8313   u8 enable_gso = 0;
8314   u8 enable_packed = 0;
8315   int ret;
8316
8317   /* Shut up coverity */
8318   clib_memset (hwaddr, 0, sizeof (hwaddr));
8319
8320   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8321     {
8322       if (unformat (i, "socket %s", &file_name))
8323         {
8324           file_name_set = 1;
8325         }
8326       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8327         ;
8328       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8329         use_custom_mac = 1;
8330       else if (unformat (i, "server"))
8331         is_server = 1;
8332       else if (unformat (i, "disable_mrg_rxbuf"))
8333         disable_mrg_rxbuf = 1;
8334       else if (unformat (i, "disable_indirect_desc"))
8335         disable_indirect_desc = 1;
8336       else if (unformat (i, "gso"))
8337         enable_gso = 1;
8338       else if (unformat (i, "packed"))
8339         enable_packed = 1;
8340       else if (unformat (i, "tag %s", &tag))
8341         ;
8342       else
8343         break;
8344     }
8345
8346   if (file_name_set == 0)
8347     {
8348       errmsg ("missing socket file name");
8349       return -99;
8350     }
8351
8352   if (vec_len (file_name) > 255)
8353     {
8354       errmsg ("socket file name too long");
8355       return -99;
8356     }
8357   vec_add1 (file_name, 0);
8358
8359   M (CREATE_VHOST_USER_IF, mp);
8360
8361   mp->is_server = is_server;
8362   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8363   mp->disable_indirect_desc = disable_indirect_desc;
8364   mp->enable_gso = enable_gso;
8365   mp->enable_packed = enable_packed;
8366   mp->custom_dev_instance = ntohl (custom_dev_instance);
8367   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8368   vec_free (file_name);
8369   if (custom_dev_instance != ~0)
8370     mp->renumber = 1;
8371
8372   mp->use_custom_mac = use_custom_mac;
8373   clib_memcpy (mp->mac_address, hwaddr, 6);
8374   if (tag)
8375     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8376   vec_free (tag);
8377
8378   S (mp);
8379   W (ret);
8380   return ret;
8381 }
8382
8383 static int
8384 api_modify_vhost_user_if (vat_main_t * vam)
8385 {
8386   unformat_input_t *i = vam->input;
8387   vl_api_modify_vhost_user_if_t *mp;
8388   u8 *file_name;
8389   u8 is_server = 0;
8390   u8 file_name_set = 0;
8391   u32 custom_dev_instance = ~0;
8392   u8 sw_if_index_set = 0;
8393   u32 sw_if_index = (u32) ~ 0;
8394   u8 enable_gso = 0;
8395   u8 enable_packed = 0;
8396   int ret;
8397
8398   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8399     {
8400       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8401         sw_if_index_set = 1;
8402       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8403         sw_if_index_set = 1;
8404       else if (unformat (i, "socket %s", &file_name))
8405         {
8406           file_name_set = 1;
8407         }
8408       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8409         ;
8410       else if (unformat (i, "server"))
8411         is_server = 1;
8412       else if (unformat (i, "gso"))
8413         enable_gso = 1;
8414       else if (unformat (i, "packed"))
8415         enable_packed = 1;
8416       else
8417         break;
8418     }
8419
8420   if (sw_if_index_set == 0)
8421     {
8422       errmsg ("missing sw_if_index or interface name");
8423       return -99;
8424     }
8425
8426   if (file_name_set == 0)
8427     {
8428       errmsg ("missing socket file name");
8429       return -99;
8430     }
8431
8432   if (vec_len (file_name) > 255)
8433     {
8434       errmsg ("socket file name too long");
8435       return -99;
8436     }
8437   vec_add1 (file_name, 0);
8438
8439   M (MODIFY_VHOST_USER_IF, mp);
8440
8441   mp->sw_if_index = ntohl (sw_if_index);
8442   mp->is_server = is_server;
8443   mp->enable_gso = enable_gso;
8444   mp->enable_packed = enable_packed;
8445   mp->custom_dev_instance = ntohl (custom_dev_instance);
8446   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8447   vec_free (file_name);
8448   if (custom_dev_instance != ~0)
8449     mp->renumber = 1;
8450
8451   S (mp);
8452   W (ret);
8453   return ret;
8454 }
8455
8456 static int
8457 api_create_vhost_user_if_v2 (vat_main_t * vam)
8458 {
8459   unformat_input_t *i = vam->input;
8460   vl_api_create_vhost_user_if_v2_t *mp;
8461   u8 *file_name;
8462   u8 is_server = 0;
8463   u8 file_name_set = 0;
8464   u32 custom_dev_instance = ~0;
8465   u8 hwaddr[6];
8466   u8 use_custom_mac = 0;
8467   u8 disable_mrg_rxbuf = 0;
8468   u8 disable_indirect_desc = 0;
8469   u8 *tag = 0;
8470   u8 enable_gso = 0;
8471   u8 enable_packed = 0;
8472   u8 enable_event_idx = 0;
8473   int ret;
8474
8475   /* Shut up coverity */
8476   clib_memset (hwaddr, 0, sizeof (hwaddr));
8477
8478   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8479     {
8480       if (unformat (i, "socket %s", &file_name))
8481         {
8482           file_name_set = 1;
8483         }
8484       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8485         ;
8486       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8487         use_custom_mac = 1;
8488       else if (unformat (i, "server"))
8489         is_server = 1;
8490       else if (unformat (i, "disable_mrg_rxbuf"))
8491         disable_mrg_rxbuf = 1;
8492       else if (unformat (i, "disable_indirect_desc"))
8493         disable_indirect_desc = 1;
8494       else if (unformat (i, "gso"))
8495         enable_gso = 1;
8496       else if (unformat (i, "packed"))
8497         enable_packed = 1;
8498       else if (unformat (i, "event-idx"))
8499         enable_event_idx = 1;
8500       else if (unformat (i, "tag %s", &tag))
8501         ;
8502       else
8503         break;
8504     }
8505
8506   if (file_name_set == 0)
8507     {
8508       errmsg ("missing socket file name");
8509       return -99;
8510     }
8511
8512   if (vec_len (file_name) > 255)
8513     {
8514       errmsg ("socket file name too long");
8515       return -99;
8516     }
8517   vec_add1 (file_name, 0);
8518
8519   M (CREATE_VHOST_USER_IF_V2, mp);
8520
8521   mp->is_server = is_server;
8522   mp->disable_mrg_rxbuf = disable_mrg_rxbuf;
8523   mp->disable_indirect_desc = disable_indirect_desc;
8524   mp->enable_gso = enable_gso;
8525   mp->enable_packed = enable_packed;
8526   mp->enable_event_idx = enable_event_idx;
8527   mp->custom_dev_instance = ntohl (custom_dev_instance);
8528   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8529   vec_free (file_name);
8530   if (custom_dev_instance != ~0)
8531     mp->renumber = 1;
8532
8533   mp->use_custom_mac = use_custom_mac;
8534   clib_memcpy (mp->mac_address, hwaddr, 6);
8535   if (tag)
8536     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
8537   vec_free (tag);
8538
8539   S (mp);
8540   W (ret);
8541   return ret;
8542 }
8543
8544 static int
8545 api_modify_vhost_user_if_v2 (vat_main_t * vam)
8546 {
8547   unformat_input_t *i = vam->input;
8548   vl_api_modify_vhost_user_if_v2_t *mp;
8549   u8 *file_name;
8550   u8 is_server = 0;
8551   u8 file_name_set = 0;
8552   u32 custom_dev_instance = ~0;
8553   u8 sw_if_index_set = 0;
8554   u32 sw_if_index = (u32) ~ 0;
8555   u8 enable_gso = 0;
8556   u8 enable_packed = 0;
8557   u8 enable_event_idx = 0;
8558   int ret;
8559
8560   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8561     {
8562       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8563         sw_if_index_set = 1;
8564       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8565         sw_if_index_set = 1;
8566       else if (unformat (i, "socket %s", &file_name))
8567         {
8568           file_name_set = 1;
8569         }
8570       else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance))
8571         ;
8572       else if (unformat (i, "server"))
8573         is_server = 1;
8574       else if (unformat (i, "gso"))
8575         enable_gso = 1;
8576       else if (unformat (i, "packed"))
8577         enable_packed = 1;
8578       else if (unformat (i, "event-idx"))
8579         enable_event_idx = 1;
8580       else
8581         break;
8582     }
8583
8584   if (sw_if_index_set == 0)
8585     {
8586       errmsg ("missing sw_if_index or interface name");
8587       return -99;
8588     }
8589
8590   if (file_name_set == 0)
8591     {
8592       errmsg ("missing socket file name");
8593       return -99;
8594     }
8595
8596   if (vec_len (file_name) > 255)
8597     {
8598       errmsg ("socket file name too long");
8599       return -99;
8600     }
8601   vec_add1 (file_name, 0);
8602
8603   M (MODIFY_VHOST_USER_IF_V2, mp);
8604
8605   mp->sw_if_index = ntohl (sw_if_index);
8606   mp->is_server = is_server;
8607   mp->enable_gso = enable_gso;
8608   mp->enable_packed = enable_packed;
8609   mp->enable_event_idx = enable_event_idx;
8610   mp->custom_dev_instance = ntohl (custom_dev_instance);
8611   clib_memcpy (mp->sock_filename, file_name, vec_len (file_name));
8612   vec_free (file_name);
8613   if (custom_dev_instance != ~0)
8614     mp->renumber = 1;
8615
8616   S (mp);
8617   W (ret);
8618   return ret;
8619 }
8620
8621 static int
8622 api_delete_vhost_user_if (vat_main_t * vam)
8623 {
8624   unformat_input_t *i = vam->input;
8625   vl_api_delete_vhost_user_if_t *mp;
8626   u32 sw_if_index = ~0;
8627   u8 sw_if_index_set = 0;
8628   int ret;
8629
8630   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8631     {
8632       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8633         sw_if_index_set = 1;
8634       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8635         sw_if_index_set = 1;
8636       else
8637         break;
8638     }
8639
8640   if (sw_if_index_set == 0)
8641     {
8642       errmsg ("missing sw_if_index or interface name");
8643       return -99;
8644     }
8645
8646
8647   M (DELETE_VHOST_USER_IF, mp);
8648
8649   mp->sw_if_index = ntohl (sw_if_index);
8650
8651   S (mp);
8652   W (ret);
8653   return ret;
8654 }
8655
8656 static void vl_api_sw_interface_vhost_user_details_t_handler
8657   (vl_api_sw_interface_vhost_user_details_t * mp)
8658 {
8659   vat_main_t *vam = &vat_main;
8660   u64 features;
8661
8662   features =
8663     clib_net_to_host_u32 (mp->features_first_32) | ((u64)
8664                                                     clib_net_to_host_u32
8665                                                     (mp->features_last_32) <<
8666                                                     32);
8667
8668   print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %16llx %6d %7d %s",
8669          (char *) mp->interface_name, ntohl (mp->sw_if_index),
8670          ntohl (mp->virtio_net_hdr_sz), features, mp->is_server,
8671          ntohl (mp->num_regions), (char *) mp->sock_filename);
8672   print (vam->ofp, "    Status: '%s'", strerror (ntohl (mp->sock_errno)));
8673 }
8674
8675 static void vl_api_sw_interface_vhost_user_details_t_handler_json
8676   (vl_api_sw_interface_vhost_user_details_t * mp)
8677 {
8678   vat_main_t *vam = &vat_main;
8679   vat_json_node_t *node = NULL;
8680
8681   if (VAT_JSON_ARRAY != vam->json_tree.type)
8682     {
8683       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8684       vat_json_init_array (&vam->json_tree);
8685     }
8686   node = vat_json_array_add (&vam->json_tree);
8687
8688   vat_json_init_object (node);
8689   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8690   vat_json_object_add_string_copy (node, "interface_name",
8691                                    mp->interface_name);
8692   vat_json_object_add_uint (node, "virtio_net_hdr_sz",
8693                             ntohl (mp->virtio_net_hdr_sz));
8694   vat_json_object_add_uint (node, "features_first_32",
8695                             clib_net_to_host_u32 (mp->features_first_32));
8696   vat_json_object_add_uint (node, "features_last_32",
8697                             clib_net_to_host_u32 (mp->features_last_32));
8698   vat_json_object_add_uint (node, "is_server", mp->is_server);
8699   vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename);
8700   vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions));
8701   vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno));
8702 }
8703
8704 static int
8705 api_sw_interface_vhost_user_dump (vat_main_t * vam)
8706 {
8707   unformat_input_t *i = vam->input;
8708   vl_api_sw_interface_vhost_user_dump_t *mp;
8709   vl_api_control_ping_t *mp_ping;
8710   int ret;
8711   u32 sw_if_index = ~0;
8712
8713   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8714     {
8715       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8716         ;
8717       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8718         ;
8719       else
8720         break;
8721     }
8722
8723   print (vam->ofp, "Interface name            idx hdr_sz         features "
8724                    "server regions filename");
8725
8726   /* Get list of vhost-user interfaces */
8727   M (SW_INTERFACE_VHOST_USER_DUMP, mp);
8728   mp->sw_if_index = ntohl (sw_if_index);
8729   S (mp);
8730
8731   /* Use a control ping for synchronization */
8732   MPING (CONTROL_PING, mp_ping);
8733   S (mp_ping);
8734
8735   W (ret);
8736   return ret;
8737 }
8738
8739 static int
8740 api_show_version (vat_main_t * vam)
8741 {
8742   vl_api_show_version_t *mp;
8743   int ret;
8744
8745   M (SHOW_VERSION, mp);
8746
8747   S (mp);
8748   W (ret);
8749   return ret;
8750 }
8751
8752 static void vl_api_l2_fib_table_details_t_handler
8753   (vl_api_l2_fib_table_details_t * mp)
8754 {
8755   vat_main_t *vam = &vat_main;
8756
8757   print (vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
8758          "       %d       %d     %d",
8759          ntohl (mp->bd_id), format_ethernet_address, mp->mac,
8760          ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac,
8761          mp->bvi_mac);
8762 }
8763
8764 static void vl_api_l2_fib_table_details_t_handler_json
8765   (vl_api_l2_fib_table_details_t * mp)
8766 {
8767   vat_main_t *vam = &vat_main;
8768   vat_json_node_t *node = NULL;
8769
8770   if (VAT_JSON_ARRAY != vam->json_tree.type)
8771     {
8772       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
8773       vat_json_init_array (&vam->json_tree);
8774     }
8775   node = vat_json_array_add (&vam->json_tree);
8776
8777   vat_json_init_object (node);
8778   vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id));
8779   vat_json_object_add_bytes (node, "mac", mp->mac, 6);
8780   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
8781   vat_json_object_add_uint (node, "static_mac", mp->static_mac);
8782   vat_json_object_add_uint (node, "filter_mac", mp->filter_mac);
8783   vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac);
8784 }
8785
8786 static int
8787 api_l2_fib_table_dump (vat_main_t * vam)
8788 {
8789   unformat_input_t *i = vam->input;
8790   vl_api_l2_fib_table_dump_t *mp;
8791   vl_api_control_ping_t *mp_ping;
8792   u32 bd_id;
8793   u8 bd_id_set = 0;
8794   int ret;
8795
8796   /* Parse args required to build the message */
8797   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8798     {
8799       if (unformat (i, "bd_id %d", &bd_id))
8800         bd_id_set = 1;
8801       else
8802         break;
8803     }
8804
8805   if (bd_id_set == 0)
8806     {
8807       errmsg ("missing bridge domain");
8808       return -99;
8809     }
8810
8811   print (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
8812
8813   /* Get list of l2 fib entries */
8814   M (L2_FIB_TABLE_DUMP, mp);
8815
8816   mp->bd_id = ntohl (bd_id);
8817   S (mp);
8818
8819   /* Use a control ping for synchronization */
8820   MPING (CONTROL_PING, mp_ping);
8821   S (mp_ping);
8822
8823   W (ret);
8824   return ret;
8825 }
8826
8827
8828 static int
8829 api_interface_name_renumber (vat_main_t * vam)
8830 {
8831   unformat_input_t *line_input = vam->input;
8832   vl_api_interface_name_renumber_t *mp;
8833   u32 sw_if_index = ~0;
8834   u32 new_show_dev_instance = ~0;
8835   int ret;
8836
8837   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8838     {
8839       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
8840                     &sw_if_index))
8841         ;
8842       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8843         ;
8844       else if (unformat (line_input, "new_show_dev_instance %d",
8845                          &new_show_dev_instance))
8846         ;
8847       else
8848         break;
8849     }
8850
8851   if (sw_if_index == ~0)
8852     {
8853       errmsg ("missing interface name or sw_if_index");
8854       return -99;
8855     }
8856
8857   if (new_show_dev_instance == ~0)
8858     {
8859       errmsg ("missing new_show_dev_instance");
8860       return -99;
8861     }
8862
8863   M (INTERFACE_NAME_RENUMBER, mp);
8864
8865   mp->sw_if_index = ntohl (sw_if_index);
8866   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
8867
8868   S (mp);
8869   W (ret);
8870   return ret;
8871 }
8872
8873 static int
8874 api_want_l2_macs_events (vat_main_t * vam)
8875 {
8876   unformat_input_t *line_input = vam->input;
8877   vl_api_want_l2_macs_events_t *mp;
8878   u8 enable_disable = 1;
8879   u32 scan_delay = 0;
8880   u32 max_macs_in_event = 0;
8881   u32 learn_limit = 0;
8882   int ret;
8883
8884   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
8885     {
8886       if (unformat (line_input, "learn-limit %d", &learn_limit))
8887         ;
8888       else if (unformat (line_input, "scan-delay %d", &scan_delay))
8889         ;
8890       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
8891         ;
8892       else if (unformat (line_input, "disable"))
8893         enable_disable = 0;
8894       else
8895         break;
8896     }
8897
8898   M (WANT_L2_MACS_EVENTS, mp);
8899   mp->enable_disable = enable_disable;
8900   mp->pid = htonl (getpid ());
8901   mp->learn_limit = htonl (learn_limit);
8902   mp->scan_delay = (u8) scan_delay;
8903   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
8904   S (mp);
8905   W (ret);
8906   return ret;
8907 }
8908
8909 static int
8910 api_ip_address_dump (vat_main_t * vam)
8911 {
8912   unformat_input_t *i = vam->input;
8913   vl_api_ip_address_dump_t *mp;
8914   vl_api_control_ping_t *mp_ping;
8915   u32 sw_if_index = ~0;
8916   u8 sw_if_index_set = 0;
8917   u8 ipv4_set = 0;
8918   u8 ipv6_set = 0;
8919   int ret;
8920
8921   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
8922     {
8923       if (unformat (i, "sw_if_index %d", &sw_if_index))
8924         sw_if_index_set = 1;
8925       else
8926         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
8927         sw_if_index_set = 1;
8928       else if (unformat (i, "ipv4"))
8929         ipv4_set = 1;
8930       else if (unformat (i, "ipv6"))
8931         ipv6_set = 1;
8932       else
8933         break;
8934     }
8935
8936   if (ipv4_set && ipv6_set)
8937     {
8938       errmsg ("ipv4 and ipv6 flags cannot be both set");
8939       return -99;
8940     }
8941
8942   if ((!ipv4_set) && (!ipv6_set))
8943     {
8944       errmsg ("no ipv4 nor ipv6 flag set");
8945       return -99;
8946     }
8947
8948   if (sw_if_index_set == 0)
8949     {
8950       errmsg ("missing interface name or sw_if_index");
8951       return -99;
8952     }
8953
8954   vam->current_sw_if_index = sw_if_index;
8955   vam->is_ipv6 = ipv6_set;
8956
8957   M (IP_ADDRESS_DUMP, mp);
8958   mp->sw_if_index = ntohl (sw_if_index);
8959   mp->is_ipv6 = ipv6_set;
8960   S (mp);
8961
8962   /* Use a control ping for synchronization */
8963   MPING (CONTROL_PING, mp_ping);
8964   S (mp_ping);
8965
8966   W (ret);
8967   return ret;
8968 }
8969
8970 static int
8971 api_ip_dump (vat_main_t * vam)
8972 {
8973   vl_api_ip_dump_t *mp;
8974   vl_api_control_ping_t *mp_ping;
8975   unformat_input_t *in = vam->input;
8976   int ipv4_set = 0;
8977   int ipv6_set = 0;
8978   int is_ipv6;
8979   int i;
8980   int ret;
8981
8982   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
8983     {
8984       if (unformat (in, "ipv4"))
8985         ipv4_set = 1;
8986       else if (unformat (in, "ipv6"))
8987         ipv6_set = 1;
8988       else
8989         break;
8990     }
8991
8992   if (ipv4_set && ipv6_set)
8993     {
8994       errmsg ("ipv4 and ipv6 flags cannot be both set");
8995       return -99;
8996     }
8997
8998   if ((!ipv4_set) && (!ipv6_set))
8999     {
9000       errmsg ("no ipv4 nor ipv6 flag set");
9001       return -99;
9002     }
9003
9004   is_ipv6 = ipv6_set;
9005   vam->is_ipv6 = is_ipv6;
9006
9007   /* free old data */
9008   for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
9009     {
9010       vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
9011     }
9012   vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
9013
9014   M (IP_DUMP, mp);
9015   mp->is_ipv6 = ipv6_set;
9016   S (mp);
9017
9018   /* Use a control ping for synchronization */
9019   MPING (CONTROL_PING, mp_ping);
9020   S (mp_ping);
9021
9022   W (ret);
9023   return ret;
9024 }
9025
9026 static int
9027 api_ipsec_spd_add_del (vat_main_t * vam)
9028 {
9029   unformat_input_t *i = vam->input;
9030   vl_api_ipsec_spd_add_del_t *mp;
9031   u32 spd_id = ~0;
9032   u8 is_add = 1;
9033   int ret;
9034
9035   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9036     {
9037       if (unformat (i, "spd_id %d", &spd_id))
9038         ;
9039       else if (unformat (i, "del"))
9040         is_add = 0;
9041       else
9042         {
9043           clib_warning ("parse error '%U'", format_unformat_error, i);
9044           return -99;
9045         }
9046     }
9047   if (spd_id == ~0)
9048     {
9049       errmsg ("spd_id must be set");
9050       return -99;
9051     }
9052
9053   M (IPSEC_SPD_ADD_DEL, mp);
9054
9055   mp->spd_id = ntohl (spd_id);
9056   mp->is_add = is_add;
9057
9058   S (mp);
9059   W (ret);
9060   return ret;
9061 }
9062
9063 static int
9064 api_ipsec_interface_add_del_spd (vat_main_t * vam)
9065 {
9066   unformat_input_t *i = vam->input;
9067   vl_api_ipsec_interface_add_del_spd_t *mp;
9068   u32 sw_if_index;
9069   u8 sw_if_index_set = 0;
9070   u32 spd_id = (u32) ~ 0;
9071   u8 is_add = 1;
9072   int ret;
9073
9074   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9075     {
9076       if (unformat (i, "del"))
9077         is_add = 0;
9078       else if (unformat (i, "spd_id %d", &spd_id))
9079         ;
9080       else
9081         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
9082         sw_if_index_set = 1;
9083       else if (unformat (i, "sw_if_index %d", &sw_if_index))
9084         sw_if_index_set = 1;
9085       else
9086         {
9087           clib_warning ("parse error '%U'", format_unformat_error, i);
9088           return -99;
9089         }
9090
9091     }
9092
9093   if (spd_id == (u32) ~ 0)
9094     {
9095       errmsg ("spd_id must be set");
9096       return -99;
9097     }
9098
9099   if (sw_if_index_set == 0)
9100     {
9101       errmsg ("missing interface name or sw_if_index");
9102       return -99;
9103     }
9104
9105   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
9106
9107   mp->spd_id = ntohl (spd_id);
9108   mp->sw_if_index = ntohl (sw_if_index);
9109   mp->is_add = is_add;
9110
9111   S (mp);
9112   W (ret);
9113   return ret;
9114 }
9115
9116 static int
9117 api_ipsec_spd_entry_add_del (vat_main_t * vam)
9118 {
9119   unformat_input_t *i = vam->input;
9120   vl_api_ipsec_spd_entry_add_del_t *mp;
9121   u8 is_add = 1, is_outbound = 0;
9122   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
9123   i32 priority = 0;
9124   u32 rport_start = 0, rport_stop = (u32) ~ 0;
9125   u32 lport_start = 0, lport_stop = (u32) ~ 0;
9126   vl_api_address_t laddr_start = { }, laddr_stop =
9127   {
9128   }, raddr_start =
9129   {
9130   }, raddr_stop =
9131   {
9132   };
9133   int ret;
9134
9135   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9136     {
9137       if (unformat (i, "del"))
9138         is_add = 0;
9139       if (unformat (i, "outbound"))
9140         is_outbound = 1;
9141       if (unformat (i, "inbound"))
9142         is_outbound = 0;
9143       else if (unformat (i, "spd_id %d", &spd_id))
9144         ;
9145       else if (unformat (i, "sa_id %d", &sa_id))
9146         ;
9147       else if (unformat (i, "priority %d", &priority))
9148         ;
9149       else if (unformat (i, "protocol %d", &protocol))
9150         ;
9151       else if (unformat (i, "lport_start %d", &lport_start))
9152         ;
9153       else if (unformat (i, "lport_stop %d", &lport_stop))
9154         ;
9155       else if (unformat (i, "rport_start %d", &rport_start))
9156         ;
9157       else if (unformat (i, "rport_stop %d", &rport_stop))
9158         ;
9159       else if (unformat (i, "laddr_start %U",
9160                          unformat_vl_api_address, &laddr_start))
9161         ;
9162       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
9163                          &laddr_stop))
9164         ;
9165       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
9166                          &raddr_start))
9167         ;
9168       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
9169                          &raddr_stop))
9170         ;
9171       else
9172         if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
9173         {
9174           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
9175             {
9176               clib_warning ("unsupported action: 'resolve'");
9177               return -99;
9178             }
9179         }
9180       else
9181         {
9182           clib_warning ("parse error '%U'", format_unformat_error, i);
9183           return -99;
9184         }
9185
9186     }
9187
9188   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
9189
9190   mp->is_add = is_add;
9191
9192   mp->entry.spd_id = ntohl (spd_id);
9193   mp->entry.priority = ntohl (priority);
9194   mp->entry.is_outbound = is_outbound;
9195
9196   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
9197                sizeof (vl_api_address_t));
9198   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
9199                sizeof (vl_api_address_t));
9200   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
9201                sizeof (vl_api_address_t));
9202   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
9203                sizeof (vl_api_address_t));
9204
9205   mp->entry.protocol = (u8) protocol;
9206   mp->entry.local_port_start = ntohs ((u16) lport_start);
9207   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
9208   mp->entry.remote_port_start = ntohs ((u16) rport_start);
9209   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
9210   mp->entry.policy = (u8) policy;
9211   mp->entry.sa_id = ntohl (sa_id);
9212
9213   S (mp);
9214   W (ret);
9215   return ret;
9216 }
9217
9218 static int
9219 api_ipsec_sad_entry_add_del (vat_main_t * vam)
9220 {
9221   unformat_input_t *i = vam->input;
9222   vl_api_ipsec_sad_entry_add_del_t *mp;
9223   u32 sad_id = 0, spi = 0;
9224   u8 *ck = 0, *ik = 0;
9225   u8 is_add = 1;
9226
9227   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
9228   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
9229   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
9230   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
9231   vl_api_address_t tun_src, tun_dst;
9232   int ret;
9233
9234   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9235     {
9236       if (unformat (i, "del"))
9237         is_add = 0;
9238       else if (unformat (i, "sad_id %d", &sad_id))
9239         ;
9240       else if (unformat (i, "spi %d", &spi))
9241         ;
9242       else if (unformat (i, "esp"))
9243         protocol = IPSEC_API_PROTO_ESP;
9244       else
9245         if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
9246         {
9247           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
9248           if (ADDRESS_IP6 == tun_src.af)
9249             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
9250         }
9251       else
9252         if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
9253         {
9254           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
9255           if (ADDRESS_IP6 == tun_src.af)
9256             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
9257         }
9258       else
9259         if (unformat (i, "crypto_alg %U",
9260                       unformat_ipsec_api_crypto_alg, &crypto_alg))
9261         ;
9262       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
9263         ;
9264       else if (unformat (i, "integ_alg %U",
9265                          unformat_ipsec_api_integ_alg, &integ_alg))
9266         ;
9267       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
9268         ;
9269       else
9270         {
9271           clib_warning ("parse error '%U'", format_unformat_error, i);
9272           return -99;
9273         }
9274
9275     }
9276
9277   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
9278
9279   mp->is_add = is_add;
9280   mp->entry.sad_id = ntohl (sad_id);
9281   mp->entry.protocol = protocol;
9282   mp->entry.spi = ntohl (spi);
9283   mp->entry.flags = flags;
9284
9285   mp->entry.crypto_algorithm = crypto_alg;
9286   mp->entry.integrity_algorithm = integ_alg;
9287   mp->entry.crypto_key.length = vec_len (ck);
9288   mp->entry.integrity_key.length = vec_len (ik);
9289
9290   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
9291     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
9292
9293   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
9294     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
9295
9296   if (ck)
9297     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
9298   if (ik)
9299     clib_memcpy (mp->entry.integrity_key.data, ik,
9300                  mp->entry.integrity_key.length);
9301
9302   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
9303     {
9304       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
9305                    sizeof (mp->entry.tunnel_src));
9306       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
9307                    sizeof (mp->entry.tunnel_dst));
9308     }
9309
9310   S (mp);
9311   W (ret);
9312   return ret;
9313 }
9314
9315 static void
9316 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp)
9317 {
9318   vat_main_t *vam = &vat_main;
9319
9320   print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
9321          "crypto_key %U integ_alg %u integ_key %U flags %x "
9322          "tunnel_src_addr %U tunnel_dst_addr %U "
9323          "salt %u seq_outbound %lu last_seq_inbound %lu "
9324          "replay_window %lu stat_index %u\n",
9325          ntohl (mp->entry.sad_id),
9326          ntohl (mp->sw_if_index),
9327          ntohl (mp->entry.spi),
9328          ntohl (mp->entry.protocol),
9329          ntohl (mp->entry.crypto_algorithm),
9330          format_hex_bytes, mp->entry.crypto_key.data,
9331          mp->entry.crypto_key.length, ntohl (mp->entry.integrity_algorithm),
9332          format_hex_bytes, mp->entry.integrity_key.data,
9333          mp->entry.integrity_key.length, ntohl (mp->entry.flags),
9334          format_vl_api_address, &mp->entry.tunnel_src, format_vl_api_address,
9335          &mp->entry.tunnel_dst, ntohl (mp->salt),
9336          clib_net_to_host_u64 (mp->seq_outbound),
9337          clib_net_to_host_u64 (mp->last_seq_inbound),
9338          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
9339 }
9340
9341 #define vl_api_ipsec_sa_details_t_endian vl_noop_handler
9342 #define vl_api_ipsec_sa_details_t_print vl_noop_handler
9343
9344 static void vl_api_ipsec_sa_details_t_handler_json
9345   (vl_api_ipsec_sa_details_t * mp)
9346 {
9347   vat_main_t *vam = &vat_main;
9348   vat_json_node_t *node = NULL;
9349   vl_api_ipsec_sad_flags_t flags;
9350
9351   if (VAT_JSON_ARRAY != vam->json_tree.type)
9352     {
9353       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9354       vat_json_init_array (&vam->json_tree);
9355     }
9356   node = vat_json_array_add (&vam->json_tree);
9357
9358   vat_json_init_object (node);
9359   vat_json_object_add_uint (node, "sa_id", ntohl (mp->entry.sad_id));
9360   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9361   vat_json_object_add_uint (node, "spi", ntohl (mp->entry.spi));
9362   vat_json_object_add_uint (node, "proto", ntohl (mp->entry.protocol));
9363   vat_json_object_add_uint (node, "crypto_alg",
9364                             ntohl (mp->entry.crypto_algorithm));
9365   vat_json_object_add_uint (node, "integ_alg",
9366                             ntohl (mp->entry.integrity_algorithm));
9367   flags = ntohl (mp->entry.flags);
9368   vat_json_object_add_uint (node, "use_esn",
9369                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ESN));
9370   vat_json_object_add_uint (node, "use_anti_replay",
9371                             ! !(flags & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY));
9372   vat_json_object_add_uint (node, "is_tunnel",
9373                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL));
9374   vat_json_object_add_uint (node, "is_tunnel_ip6",
9375                             ! !(flags & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6));
9376   vat_json_object_add_uint (node, "udp_encap",
9377                             ! !(flags & IPSEC_API_SAD_FLAG_UDP_ENCAP));
9378   vat_json_object_add_bytes (node, "crypto_key", mp->entry.crypto_key.data,
9379                              mp->entry.crypto_key.length);
9380   vat_json_object_add_bytes (node, "integ_key", mp->entry.integrity_key.data,
9381                              mp->entry.integrity_key.length);
9382   vat_json_object_add_address (node, "src", &mp->entry.tunnel_src);
9383   vat_json_object_add_address (node, "dst", &mp->entry.tunnel_dst);
9384   vat_json_object_add_uint (node, "replay_window",
9385                             clib_net_to_host_u64 (mp->replay_window));
9386   vat_json_object_add_uint (node, "stat_index", ntohl (mp->stat_index));
9387 }
9388
9389 static int
9390 api_ipsec_sa_dump (vat_main_t * vam)
9391 {
9392   unformat_input_t *i = vam->input;
9393   vl_api_ipsec_sa_dump_t *mp;
9394   vl_api_control_ping_t *mp_ping;
9395   u32 sa_id = ~0;
9396   int ret;
9397
9398   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9399     {
9400       if (unformat (i, "sa_id %d", &sa_id))
9401         ;
9402       else
9403         {
9404           clib_warning ("parse error '%U'", format_unformat_error, i);
9405           return -99;
9406         }
9407     }
9408
9409   M (IPSEC_SA_DUMP, mp);
9410
9411   mp->sa_id = ntohl (sa_id);
9412
9413   S (mp);
9414
9415   /* Use a control ping for synchronization */
9416   M (CONTROL_PING, mp_ping);
9417   S (mp_ping);
9418
9419   W (ret);
9420   return ret;
9421 }
9422
9423 static int
9424 api_get_first_msg_id (vat_main_t * vam)
9425 {
9426   vl_api_get_first_msg_id_t *mp;
9427   unformat_input_t *i = vam->input;
9428   u8 *name;
9429   u8 name_set = 0;
9430   int ret;
9431
9432   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9433     {
9434       if (unformat (i, "client %s", &name))
9435         name_set = 1;
9436       else
9437         break;
9438     }
9439
9440   if (name_set == 0)
9441     {
9442       errmsg ("missing client name");
9443       return -99;
9444     }
9445   vec_add1 (name, 0);
9446
9447   if (vec_len (name) > 63)
9448     {
9449       errmsg ("client name too long");
9450       return -99;
9451     }
9452
9453   M (GET_FIRST_MSG_ID, mp);
9454   clib_memcpy (mp->name, name, vec_len (name));
9455   S (mp);
9456   W (ret);
9457   return ret;
9458 }
9459
9460 static int
9461 api_get_node_graph (vat_main_t * vam)
9462 {
9463   vl_api_get_node_graph_t *mp;
9464   int ret;
9465
9466   M (GET_NODE_GRAPH, mp);
9467
9468   /* send it... */
9469   S (mp);
9470   /* Wait for the reply */
9471   W (ret);
9472   return ret;
9473 }
9474
9475 static int
9476 api_af_packet_create (vat_main_t * vam)
9477 {
9478   unformat_input_t *i = vam->input;
9479   vl_api_af_packet_create_t *mp;
9480   u8 *host_if_name = 0;
9481   u8 hw_addr[6];
9482   u8 random_hw_addr = 1;
9483   int ret;
9484
9485   clib_memset (hw_addr, 0, sizeof (hw_addr));
9486
9487   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9488     {
9489       if (unformat (i, "name %s", &host_if_name))
9490         vec_add1 (host_if_name, 0);
9491       else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
9492         random_hw_addr = 0;
9493       else
9494         break;
9495     }
9496
9497   if (!vec_len (host_if_name))
9498     {
9499       errmsg ("host-interface name must be specified");
9500       return -99;
9501     }
9502
9503   if (vec_len (host_if_name) > 64)
9504     {
9505       errmsg ("host-interface name too long");
9506       return -99;
9507     }
9508
9509   M (AF_PACKET_CREATE, mp);
9510
9511   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9512   clib_memcpy (mp->hw_addr, hw_addr, 6);
9513   mp->use_random_hw_addr = random_hw_addr;
9514   vec_free (host_if_name);
9515
9516   S (mp);
9517
9518   /* *INDENT-OFF* */
9519   W2 (ret,
9520       ({
9521         if (ret == 0)
9522           fprintf (vam->ofp ? vam->ofp : stderr,
9523                    " new sw_if_index = %d\n", vam->sw_if_index);
9524       }));
9525   /* *INDENT-ON* */
9526   return ret;
9527 }
9528
9529 static int
9530 api_af_packet_delete (vat_main_t * vam)
9531 {
9532   unformat_input_t *i = vam->input;
9533   vl_api_af_packet_delete_t *mp;
9534   u8 *host_if_name = 0;
9535   int ret;
9536
9537   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9538     {
9539       if (unformat (i, "name %s", &host_if_name))
9540         vec_add1 (host_if_name, 0);
9541       else
9542         break;
9543     }
9544
9545   if (!vec_len (host_if_name))
9546     {
9547       errmsg ("host-interface name must be specified");
9548       return -99;
9549     }
9550
9551   if (vec_len (host_if_name) > 64)
9552     {
9553       errmsg ("host-interface name too long");
9554       return -99;
9555     }
9556
9557   M (AF_PACKET_DELETE, mp);
9558
9559   clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
9560   vec_free (host_if_name);
9561
9562   S (mp);
9563   W (ret);
9564   return ret;
9565 }
9566
9567 static void vl_api_af_packet_details_t_handler
9568   (vl_api_af_packet_details_t * mp)
9569 {
9570   vat_main_t *vam = &vat_main;
9571
9572   print (vam->ofp, "%-16s %d",
9573          mp->host_if_name, clib_net_to_host_u32 (mp->sw_if_index));
9574 }
9575
9576 static void vl_api_af_packet_details_t_handler_json
9577   (vl_api_af_packet_details_t * mp)
9578 {
9579   vat_main_t *vam = &vat_main;
9580   vat_json_node_t *node = NULL;
9581
9582   if (VAT_JSON_ARRAY != vam->json_tree.type)
9583     {
9584       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9585       vat_json_init_array (&vam->json_tree);
9586     }
9587   node = vat_json_array_add (&vam->json_tree);
9588
9589   vat_json_init_object (node);
9590   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
9591   vat_json_object_add_string_copy (node, "dev_name", mp->host_if_name);
9592 }
9593
9594 static int
9595 api_af_packet_dump (vat_main_t * vam)
9596 {
9597   vl_api_af_packet_dump_t *mp;
9598   vl_api_control_ping_t *mp_ping;
9599   int ret;
9600
9601   print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index");
9602   /* Get list of tap interfaces */
9603   M (AF_PACKET_DUMP, mp);
9604   S (mp);
9605
9606   /* Use a control ping for synchronization */
9607   MPING (CONTROL_PING, mp_ping);
9608   S (mp_ping);
9609
9610   W (ret);
9611   return ret;
9612 }
9613
9614 static int
9615 api_policer_add_del (vat_main_t * vam)
9616 {
9617   unformat_input_t *i = vam->input;
9618   vl_api_policer_add_del_t *mp;
9619   u8 is_add = 1;
9620   u8 *name = 0;
9621   u32 cir = 0;
9622   u32 eir = 0;
9623   u64 cb = 0;
9624   u64 eb = 0;
9625   u8 rate_type = 0;
9626   u8 round_type = 0;
9627   u8 type = 0;
9628   u8 color_aware = 0;
9629   qos_pol_action_params_st conform_action, exceed_action, violate_action;
9630   int ret;
9631
9632   conform_action.action_type = QOS_ACTION_TRANSMIT;
9633   conform_action.dscp = 0;
9634   exceed_action.action_type = QOS_ACTION_MARK_AND_TRANSMIT;
9635   exceed_action.dscp = 0;
9636   violate_action.action_type = QOS_ACTION_DROP;
9637   violate_action.dscp = 0;
9638
9639   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9640     {
9641       if (unformat (i, "del"))
9642         is_add = 0;
9643       else if (unformat (i, "name %s", &name))
9644         vec_add1 (name, 0);
9645       else if (unformat (i, "cir %u", &cir))
9646         ;
9647       else if (unformat (i, "eir %u", &eir))
9648         ;
9649       else if (unformat (i, "cb %u", &cb))
9650         ;
9651       else if (unformat (i, "eb %u", &eb))
9652         ;
9653       else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
9654                          &rate_type))
9655         ;
9656       else if (unformat (i, "round_type %U", unformat_policer_round_type,
9657                          &round_type))
9658         ;
9659       else if (unformat (i, "type %U", unformat_policer_type, &type))
9660         ;
9661       else if (unformat (i, "conform_action %U", unformat_policer_action_type,
9662                          &conform_action))
9663         ;
9664       else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
9665                          &exceed_action))
9666         ;
9667       else if (unformat (i, "violate_action %U", unformat_policer_action_type,
9668                          &violate_action))
9669         ;
9670       else if (unformat (i, "color-aware"))
9671         color_aware = 1;
9672       else
9673         break;
9674     }
9675
9676   if (!vec_len (name))
9677     {
9678       errmsg ("policer name must be specified");
9679       return -99;
9680     }
9681
9682   if (vec_len (name) > 64)
9683     {
9684       errmsg ("policer name too long");
9685       return -99;
9686     }
9687
9688   M (POLICER_ADD_DEL, mp);
9689
9690   clib_memcpy (mp->name, name, vec_len (name));
9691   vec_free (name);
9692   mp->is_add = is_add;
9693   mp->cir = ntohl (cir);
9694   mp->eir = ntohl (eir);
9695   mp->cb = clib_net_to_host_u64 (cb);
9696   mp->eb = clib_net_to_host_u64 (eb);
9697   mp->rate_type = rate_type;
9698   mp->round_type = round_type;
9699   mp->type = type;
9700   mp->conform_action.type =
9701     (vl_api_sse2_qos_action_type_t) conform_action.action_type;
9702   mp->conform_action.dscp = conform_action.dscp;
9703   mp->exceed_action.type =
9704     (vl_api_sse2_qos_action_type_t) exceed_action.action_type;
9705   mp->exceed_action.dscp = exceed_action.dscp;
9706   mp->violate_action.type =
9707     (vl_api_sse2_qos_action_type_t) violate_action.action_type;
9708   mp->violate_action.dscp = violate_action.dscp;
9709   mp->color_aware = color_aware;
9710
9711   S (mp);
9712   W (ret);
9713   return ret;
9714 }
9715
9716 static int
9717 api_policer_dump (vat_main_t * vam)
9718 {
9719   unformat_input_t *i = vam->input;
9720   vl_api_policer_dump_t *mp;
9721   vl_api_control_ping_t *mp_ping;
9722   u8 *match_name = 0;
9723   u8 match_name_valid = 0;
9724   int ret;
9725
9726   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
9727     {
9728       if (unformat (i, "name %s", &match_name))
9729         {
9730           vec_add1 (match_name, 0);
9731           match_name_valid = 1;
9732         }
9733       else
9734         break;
9735     }
9736
9737   M (POLICER_DUMP, mp);
9738   mp->match_name_valid = match_name_valid;
9739   clib_memcpy (mp->match_name, match_name, vec_len (match_name));
9740   vec_free (match_name);
9741   /* send it... */
9742   S (mp);
9743
9744   /* Use a control ping for synchronization */
9745   MPING (CONTROL_PING, mp_ping);
9746   S (mp_ping);
9747
9748   /* Wait for a reply... */
9749   W (ret);
9750   return ret;
9751 }
9752
9753 static u8 *
9754 format_fib_api_path_nh_proto (u8 * s, va_list * args)
9755 {
9756   vl_api_fib_path_nh_proto_t proto =
9757     va_arg (*args, vl_api_fib_path_nh_proto_t);
9758
9759   switch (proto)
9760     {
9761     case FIB_API_PATH_NH_PROTO_IP4:
9762       s = format (s, "ip4");
9763       break;
9764     case FIB_API_PATH_NH_PROTO_IP6:
9765       s = format (s, "ip6");
9766       break;
9767     case FIB_API_PATH_NH_PROTO_MPLS:
9768       s = format (s, "mpls");
9769       break;
9770     case FIB_API_PATH_NH_PROTO_BIER:
9771       s = format (s, "bier");
9772       break;
9773     case FIB_API_PATH_NH_PROTO_ETHERNET:
9774       s = format (s, "ethernet");
9775       break;
9776     }
9777
9778   return (s);
9779 }
9780
9781 static u8 *
9782 format_vl_api_ip_address_union (u8 * s, va_list * args)
9783 {
9784   vl_api_address_family_t af = va_arg (*args, int);
9785   const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
9786
9787   switch (af)
9788     {
9789     case ADDRESS_IP4:
9790       s = format (s, "%U", format_ip4_address, u->ip4);
9791       break;
9792     case ADDRESS_IP6:
9793       s = format (s, "%U", format_ip6_address, u->ip6);
9794       break;
9795     }
9796   return (s);
9797 }
9798
9799 static u8 *
9800 format_vl_api_fib_path_type (u8 * s, va_list * args)
9801 {
9802   vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
9803
9804   switch (t)
9805     {
9806     case FIB_API_PATH_TYPE_NORMAL:
9807       s = format (s, "normal");
9808       break;
9809     case FIB_API_PATH_TYPE_LOCAL:
9810       s = format (s, "local");
9811       break;
9812     case FIB_API_PATH_TYPE_DROP:
9813       s = format (s, "drop");
9814       break;
9815     case FIB_API_PATH_TYPE_UDP_ENCAP:
9816       s = format (s, "udp-encap");
9817       break;
9818     case FIB_API_PATH_TYPE_BIER_IMP:
9819       s = format (s, "bier-imp");
9820       break;
9821     case FIB_API_PATH_TYPE_ICMP_UNREACH:
9822       s = format (s, "unreach");
9823       break;
9824     case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
9825       s = format (s, "prohibit");
9826       break;
9827     case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
9828       s = format (s, "src-lookup");
9829       break;
9830     case FIB_API_PATH_TYPE_DVR:
9831       s = format (s, "dvr");
9832       break;
9833     case FIB_API_PATH_TYPE_INTERFACE_RX:
9834       s = format (s, "interface-rx");
9835       break;
9836     case FIB_API_PATH_TYPE_CLASSIFY:
9837       s = format (s, "classify");
9838       break;
9839     }
9840
9841   return (s);
9842 }
9843
9844 static void
9845 vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
9846 {
9847   print (vam->ofp,
9848          "  weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
9849          ntohl (fp->weight), ntohl (fp->sw_if_index),
9850          format_vl_api_fib_path_type, fp->type,
9851          format_fib_api_path_nh_proto, fp->proto,
9852          format_vl_api_ip_address_union, &fp->nh.address);
9853 }
9854
9855 static void
9856 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
9857                                  vl_api_fib_path_t * fp)
9858 {
9859   struct in_addr ip4;
9860   struct in6_addr ip6;
9861
9862   vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
9863   vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
9864   vat_json_object_add_uint (node, "type", fp->type);
9865   vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
9866   if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
9867     {
9868       clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
9869       vat_json_object_add_ip4 (node, "next_hop", ip4);
9870     }
9871   else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
9872     {
9873       clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
9874       vat_json_object_add_ip6 (node, "next_hop", ip6);
9875     }
9876 }
9877
9878 static void
9879 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
9880 {
9881   vat_main_t *vam = &vat_main;
9882   int count = ntohl (mp->mt_tunnel.mt_n_paths);
9883   vl_api_fib_path_t *fp;
9884   i32 i;
9885
9886   print (vam->ofp, "sw_if_index %d via:",
9887          ntohl (mp->mt_tunnel.mt_sw_if_index));
9888   fp = mp->mt_tunnel.mt_paths;
9889   for (i = 0; i < count; i++)
9890     {
9891       vl_api_fib_path_print (vam, fp);
9892       fp++;
9893     }
9894
9895   print (vam->ofp, "");
9896 }
9897
9898 #define vl_api_mpls_tunnel_details_t_endian vl_noop_handler
9899 #define vl_api_mpls_tunnel_details_t_print vl_noop_handler
9900
9901 static void
9902 vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
9903 {
9904   vat_main_t *vam = &vat_main;
9905   vat_json_node_t *node = NULL;
9906   int count = ntohl (mp->mt_tunnel.mt_n_paths);
9907   vl_api_fib_path_t *fp;
9908   i32 i;
9909
9910   if (VAT_JSON_ARRAY != vam->json_tree.type)
9911     {
9912       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9913       vat_json_init_array (&vam->json_tree);
9914     }
9915   node = vat_json_array_add (&vam->json_tree);
9916
9917   vat_json_init_object (node);
9918   vat_json_object_add_uint (node, "sw_if_index",
9919                             ntohl (mp->mt_tunnel.mt_sw_if_index));
9920
9921   vat_json_object_add_uint (node, "l2_only", mp->mt_tunnel.mt_l2_only);
9922
9923   fp = mp->mt_tunnel.mt_paths;
9924   for (i = 0; i < count; i++)
9925     {
9926       vl_api_mpls_fib_path_json_print (node, fp);
9927       fp++;
9928     }
9929 }
9930
9931 static int
9932 api_mpls_tunnel_dump (vat_main_t * vam)
9933 {
9934   vl_api_mpls_tunnel_dump_t *mp;
9935   vl_api_control_ping_t *mp_ping;
9936   int ret;
9937
9938   M (MPLS_TUNNEL_DUMP, mp);
9939
9940   S (mp);
9941
9942   /* Use a control ping for synchronization */
9943   MPING (CONTROL_PING, mp_ping);
9944   S (mp_ping);
9945
9946   W (ret);
9947   return ret;
9948 }
9949
9950 #define vl_api_mpls_table_details_t_endian vl_noop_handler
9951 #define vl_api_mpls_table_details_t_print vl_noop_handler
9952
9953
9954 static void
9955 vl_api_mpls_table_details_t_handler (vl_api_mpls_table_details_t * mp)
9956 {
9957   vat_main_t *vam = &vat_main;
9958
9959   print (vam->ofp, "table-id %d,", ntohl (mp->mt_table.mt_table_id));
9960 }
9961
9962 static void vl_api_mpls_table_details_t_handler_json
9963   (vl_api_mpls_table_details_t * mp)
9964 {
9965   vat_main_t *vam = &vat_main;
9966   vat_json_node_t *node = NULL;
9967
9968   if (VAT_JSON_ARRAY != vam->json_tree.type)
9969     {
9970       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
9971       vat_json_init_array (&vam->json_tree);
9972     }
9973   node = vat_json_array_add (&vam->json_tree);
9974
9975   vat_json_init_object (node);
9976   vat_json_object_add_uint (node, "table", ntohl (mp->mt_table.mt_table_id));
9977 }
9978
9979 static int
9980 api_mpls_table_dump (vat_main_t * vam)
9981 {
9982   vl_api_mpls_table_dump_t *mp;
9983   vl_api_control_ping_t *mp_ping;
9984   int ret;
9985
9986   M (MPLS_TABLE_DUMP, mp);
9987   S (mp);
9988
9989   /* Use a control ping for synchronization */
9990   MPING (CONTROL_PING, mp_ping);
9991   S (mp_ping);
9992
9993   W (ret);
9994   return ret;
9995 }
9996
9997 #define vl_api_mpls_route_details_t_endian vl_noop_handler
9998 #define vl_api_mpls_route_details_t_print vl_noop_handler
9999
10000 static void
10001 vl_api_mpls_route_details_t_handler (vl_api_mpls_route_details_t * mp)
10002 {
10003   vat_main_t *vam = &vat_main;
10004   int count = (int) clib_net_to_host_u32 (mp->mr_route.mr_n_paths);
10005   vl_api_fib_path_t *fp;
10006   int i;
10007
10008   print (vam->ofp,
10009          "table-id %d, label %u, ess_bit %u",
10010          ntohl (mp->mr_route.mr_table_id),
10011          ntohl (mp->mr_route.mr_label), mp->mr_route.mr_eos);
10012   fp = mp->mr_route.mr_paths;
10013   for (i = 0; i < count; i++)
10014     {
10015       vl_api_fib_path_print (vam, fp);
10016       fp++;
10017     }
10018 }
10019
10020 static void vl_api_mpls_route_details_t_handler_json
10021   (vl_api_mpls_route_details_t * mp)
10022 {
10023   vat_main_t *vam = &vat_main;
10024   int count = (int) clib_host_to_net_u32 (mp->mr_route.mr_n_paths);
10025   vat_json_node_t *node = NULL;
10026   vl_api_fib_path_t *fp;
10027   int i;
10028
10029   if (VAT_JSON_ARRAY != vam->json_tree.type)
10030     {
10031       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10032       vat_json_init_array (&vam->json_tree);
10033     }
10034   node = vat_json_array_add (&vam->json_tree);
10035
10036   vat_json_init_object (node);
10037   vat_json_object_add_uint (node, "table", ntohl (mp->mr_route.mr_table_id));
10038   vat_json_object_add_uint (node, "s_bit", mp->mr_route.mr_eos);
10039   vat_json_object_add_uint (node, "label", ntohl (mp->mr_route.mr_label));
10040   vat_json_object_add_uint (node, "path_count", count);
10041   fp = mp->mr_route.mr_paths;
10042   for (i = 0; i < count; i++)
10043     {
10044       vl_api_mpls_fib_path_json_print (node, fp);
10045       fp++;
10046     }
10047 }
10048
10049 static int
10050 api_mpls_route_dump (vat_main_t * vam)
10051 {
10052   unformat_input_t *input = vam->input;
10053   vl_api_mpls_route_dump_t *mp;
10054   vl_api_control_ping_t *mp_ping;
10055   u32 table_id;
10056   int ret;
10057
10058   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10059     {
10060       if (unformat (input, "table_id %d", &table_id))
10061         ;
10062       else
10063         break;
10064     }
10065   if (table_id == ~0)
10066     {
10067       errmsg ("missing table id");
10068       return -99;
10069     }
10070
10071   M (MPLS_ROUTE_DUMP, mp);
10072
10073   mp->table.mt_table_id = ntohl (table_id);
10074   S (mp);
10075
10076   /* Use a control ping for synchronization */
10077   MPING (CONTROL_PING, mp_ping);
10078   S (mp_ping);
10079
10080   W (ret);
10081   return ret;
10082 }
10083
10084 #define vl_api_ip_table_details_t_endian vl_noop_handler
10085 #define vl_api_ip_table_details_t_print vl_noop_handler
10086
10087 static void
10088 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
10089 {
10090   vat_main_t *vam = &vat_main;
10091
10092   print (vam->ofp,
10093          "%s; table-id %d, prefix %U/%d",
10094          mp->table.name, ntohl (mp->table.table_id));
10095 }
10096
10097
10098 static void vl_api_ip_table_details_t_handler_json
10099   (vl_api_ip_table_details_t * mp)
10100 {
10101   vat_main_t *vam = &vat_main;
10102   vat_json_node_t *node = NULL;
10103
10104   if (VAT_JSON_ARRAY != vam->json_tree.type)
10105     {
10106       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10107       vat_json_init_array (&vam->json_tree);
10108     }
10109   node = vat_json_array_add (&vam->json_tree);
10110
10111   vat_json_init_object (node);
10112   vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
10113 }
10114
10115 static int
10116 api_ip_table_dump (vat_main_t * vam)
10117 {
10118   vl_api_ip_table_dump_t *mp;
10119   vl_api_control_ping_t *mp_ping;
10120   int ret;
10121
10122   M (IP_TABLE_DUMP, mp);
10123   S (mp);
10124
10125   /* Use a control ping for synchronization */
10126   MPING (CONTROL_PING, mp_ping);
10127   S (mp_ping);
10128
10129   W (ret);
10130   return ret;
10131 }
10132
10133 static int
10134 api_ip_mtable_dump (vat_main_t * vam)
10135 {
10136   vl_api_ip_mtable_dump_t *mp;
10137   vl_api_control_ping_t *mp_ping;
10138   int ret;
10139
10140   M (IP_MTABLE_DUMP, mp);
10141   S (mp);
10142
10143   /* Use a control ping for synchronization */
10144   MPING (CONTROL_PING, mp_ping);
10145   S (mp_ping);
10146
10147   W (ret);
10148   return ret;
10149 }
10150
10151 static int
10152 api_ip_mroute_dump (vat_main_t * vam)
10153 {
10154   unformat_input_t *input = vam->input;
10155   vl_api_control_ping_t *mp_ping;
10156   vl_api_ip_mroute_dump_t *mp;
10157   int ret, is_ip6;
10158   u32 table_id;
10159
10160   is_ip6 = 0;
10161   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10162     {
10163       if (unformat (input, "table_id %d", &table_id))
10164         ;
10165       else if (unformat (input, "ip6"))
10166         is_ip6 = 1;
10167       else if (unformat (input, "ip4"))
10168         is_ip6 = 0;
10169       else
10170         break;
10171     }
10172   if (table_id == ~0)
10173     {
10174       errmsg ("missing table id");
10175       return -99;
10176     }
10177
10178   M (IP_MROUTE_DUMP, mp);
10179   mp->table.table_id = table_id;
10180   mp->table.is_ip6 = is_ip6;
10181   S (mp);
10182
10183   /* Use a control ping for synchronization */
10184   MPING (CONTROL_PING, mp_ping);
10185   S (mp_ping);
10186
10187   W (ret);
10188   return ret;
10189 }
10190
10191 #define vl_api_ip_route_details_t_endian vl_noop_handler
10192 #define vl_api_ip_route_details_t_print vl_noop_handler
10193
10194 static void
10195 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
10196 {
10197   vat_main_t *vam = &vat_main;
10198   u8 count = mp->route.n_paths;
10199   vl_api_fib_path_t *fp;
10200   int i;
10201
10202   print (vam->ofp,
10203          "table-id %d, prefix %U/%d",
10204          ntohl (mp->route.table_id),
10205          format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
10206   for (i = 0; i < count; i++)
10207     {
10208       fp = &mp->route.paths[i];
10209
10210       vl_api_fib_path_print (vam, fp);
10211       fp++;
10212     }
10213 }
10214
10215 static void vl_api_ip_route_details_t_handler_json
10216   (vl_api_ip_route_details_t * mp)
10217 {
10218   vat_main_t *vam = &vat_main;
10219   u8 count = mp->route.n_paths;
10220   vat_json_node_t *node = NULL;
10221   struct in_addr ip4;
10222   struct in6_addr ip6;
10223   vl_api_fib_path_t *fp;
10224   int i;
10225
10226   if (VAT_JSON_ARRAY != vam->json_tree.type)
10227     {
10228       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10229       vat_json_init_array (&vam->json_tree);
10230     }
10231   node = vat_json_array_add (&vam->json_tree);
10232
10233   vat_json_init_object (node);
10234   vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
10235   if (ADDRESS_IP6 == mp->route.prefix.address.af)
10236     {
10237       clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
10238       vat_json_object_add_ip6 (node, "prefix", ip6);
10239     }
10240   else
10241     {
10242       clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
10243       vat_json_object_add_ip4 (node, "prefix", ip4);
10244     }
10245   vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
10246   vat_json_object_add_uint (node, "path_count", count);
10247   for (i = 0; i < count; i++)
10248     {
10249       fp = &mp->route.paths[i];
10250       vl_api_mpls_fib_path_json_print (node, fp);
10251     }
10252 }
10253
10254 static int
10255 api_ip_route_dump (vat_main_t * vam)
10256 {
10257   unformat_input_t *input = vam->input;
10258   vl_api_ip_route_dump_t *mp;
10259   vl_api_control_ping_t *mp_ping;
10260   u32 table_id;
10261   u8 is_ip6;
10262   int ret;
10263
10264   is_ip6 = 0;
10265   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10266     {
10267       if (unformat (input, "table_id %d", &table_id))
10268         ;
10269       else if (unformat (input, "ip6"))
10270         is_ip6 = 1;
10271       else if (unformat (input, "ip4"))
10272         is_ip6 = 0;
10273       else
10274         break;
10275     }
10276   if (table_id == ~0)
10277     {
10278       errmsg ("missing table id");
10279       return -99;
10280     }
10281
10282   M (IP_ROUTE_DUMP, mp);
10283
10284   mp->table.table_id = table_id;
10285   mp->table.is_ip6 = is_ip6;
10286
10287   S (mp);
10288
10289   /* Use a control ping for synchronization */
10290   MPING (CONTROL_PING, mp_ping);
10291   S (mp_ping);
10292
10293   W (ret);
10294   return ret;
10295 }
10296
10297 static int
10298 api_sw_interface_span_enable_disable (vat_main_t * vam)
10299 {
10300   unformat_input_t *i = vam->input;
10301   vl_api_sw_interface_span_enable_disable_t *mp;
10302   u32 src_sw_if_index = ~0;
10303   u32 dst_sw_if_index = ~0;
10304   u8 state = 3;
10305   int ret;
10306   u8 is_l2 = 0;
10307
10308   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10309     {
10310       if (unformat
10311           (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index))
10312         ;
10313       else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index))
10314         ;
10315       else
10316         if (unformat
10317             (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index))
10318         ;
10319       else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index))
10320         ;
10321       else if (unformat (i, "disable"))
10322         state = 0;
10323       else if (unformat (i, "rx"))
10324         state = 1;
10325       else if (unformat (i, "tx"))
10326         state = 2;
10327       else if (unformat (i, "both"))
10328         state = 3;
10329       else if (unformat (i, "l2"))
10330         is_l2 = 1;
10331       else
10332         break;
10333     }
10334
10335   M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp);
10336
10337   mp->sw_if_index_from = htonl (src_sw_if_index);
10338   mp->sw_if_index_to = htonl (dst_sw_if_index);
10339   mp->state = state;
10340   mp->is_l2 = is_l2;
10341
10342   S (mp);
10343   W (ret);
10344   return ret;
10345 }
10346
10347 static void
10348 vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
10349                                             * mp)
10350 {
10351   vat_main_t *vam = &vat_main;
10352   u8 *sw_if_from_name = 0;
10353   u8 *sw_if_to_name = 0;
10354   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
10355   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
10356   char *states[] = { "none", "rx", "tx", "both" };
10357   hash_pair_t *p;
10358
10359   /* *INDENT-OFF* */
10360   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
10361   ({
10362     if ((u32) p->value[0] == sw_if_index_from)
10363       {
10364         sw_if_from_name = (u8 *)(p->key);
10365         if (sw_if_to_name)
10366           break;
10367       }
10368     if ((u32) p->value[0] == sw_if_index_to)
10369       {
10370         sw_if_to_name = (u8 *)(p->key);
10371         if (sw_if_from_name)
10372           break;
10373       }
10374   }));
10375   /* *INDENT-ON* */
10376   print (vam->ofp, "%20s => %20s (%s) %s",
10377          sw_if_from_name, sw_if_to_name, states[mp->state],
10378          mp->is_l2 ? "l2" : "device");
10379 }
10380
10381 static void
10382   vl_api_sw_interface_span_details_t_handler_json
10383   (vl_api_sw_interface_span_details_t * mp)
10384 {
10385   vat_main_t *vam = &vat_main;
10386   vat_json_node_t *node = NULL;
10387   u8 *sw_if_from_name = 0;
10388   u8 *sw_if_to_name = 0;
10389   u32 sw_if_index_from = ntohl (mp->sw_if_index_from);
10390   u32 sw_if_index_to = ntohl (mp->sw_if_index_to);
10391   hash_pair_t *p;
10392
10393   /* *INDENT-OFF* */
10394   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
10395   ({
10396     if ((u32) p->value[0] == sw_if_index_from)
10397       {
10398         sw_if_from_name = (u8 *)(p->key);
10399         if (sw_if_to_name)
10400           break;
10401       }
10402     if ((u32) p->value[0] == sw_if_index_to)
10403       {
10404         sw_if_to_name = (u8 *)(p->key);
10405         if (sw_if_from_name)
10406           break;
10407       }
10408   }));
10409   /* *INDENT-ON* */
10410
10411   if (VAT_JSON_ARRAY != vam->json_tree.type)
10412     {
10413       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10414       vat_json_init_array (&vam->json_tree);
10415     }
10416   node = vat_json_array_add (&vam->json_tree);
10417
10418   vat_json_init_object (node);
10419   vat_json_object_add_uint (node, "src-if-index", sw_if_index_from);
10420   vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name);
10421   vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to);
10422   if (0 != sw_if_to_name)
10423     {
10424       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
10425     }
10426   vat_json_object_add_uint (node, "state", mp->state);
10427   vat_json_object_add_uint (node, "is-l2", mp->is_l2);
10428 }
10429
10430 static int
10431 api_sw_interface_span_dump (vat_main_t * vam)
10432 {
10433   unformat_input_t *input = vam->input;
10434   vl_api_sw_interface_span_dump_t *mp;
10435   vl_api_control_ping_t *mp_ping;
10436   u8 is_l2 = 0;
10437   int ret;
10438
10439   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10440     {
10441       if (unformat (input, "l2"))
10442         is_l2 = 1;
10443       else
10444         break;
10445     }
10446
10447   M (SW_INTERFACE_SPAN_DUMP, mp);
10448   mp->is_l2 = is_l2;
10449   S (mp);
10450
10451   /* Use a control ping for synchronization */
10452   MPING (CONTROL_PING, mp_ping);
10453   S (mp_ping);
10454
10455   W (ret);
10456   return ret;
10457 }
10458
10459 int
10460 api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
10461 {
10462   unformat_input_t *input = vam->input;
10463   vl_api_ip_source_and_port_range_check_add_del_t *mp;
10464
10465   u16 *low_ports = 0;
10466   u16 *high_ports = 0;
10467   u16 this_low;
10468   u16 this_hi;
10469   vl_api_prefix_t prefix;
10470   u32 tmp, tmp2;
10471   u8 prefix_set = 0;
10472   u32 vrf_id = ~0;
10473   u8 is_add = 1;
10474   int ret;
10475
10476   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10477     {
10478       if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
10479         prefix_set = 1;
10480       else if (unformat (input, "vrf %d", &vrf_id))
10481         ;
10482       else if (unformat (input, "del"))
10483         is_add = 0;
10484       else if (unformat (input, "port %d", &tmp))
10485         {
10486           if (tmp == 0 || tmp > 65535)
10487             {
10488               errmsg ("port %d out of range", tmp);
10489               return -99;
10490             }
10491           this_low = tmp;
10492           this_hi = this_low + 1;
10493           vec_add1 (low_ports, this_low);
10494           vec_add1 (high_ports, this_hi);
10495         }
10496       else if (unformat (input, "range %d - %d", &tmp, &tmp2))
10497         {
10498           if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
10499             {
10500               errmsg ("incorrect range parameters");
10501               return -99;
10502             }
10503           this_low = tmp;
10504           /* Note: in debug CLI +1 is added to high before
10505              passing to real fn that does "the work"
10506              (ip_source_and_port_range_check_add_del).
10507              This fn is a wrapper around the binary API fn a
10508              control plane will call, which expects this increment
10509              to have occurred. Hence letting the binary API control
10510              plane fn do the increment for consistency between VAT
10511              and other control planes.
10512            */
10513           this_hi = tmp2;
10514           vec_add1 (low_ports, this_low);
10515           vec_add1 (high_ports, this_hi);
10516         }
10517       else
10518         break;
10519     }
10520
10521   if (prefix_set == 0)
10522     {
10523       errmsg ("<address>/<mask> not specified");
10524       return -99;
10525     }
10526
10527   if (vrf_id == ~0)
10528     {
10529       errmsg ("VRF ID required, not specified");
10530       return -99;
10531     }
10532
10533   if (vrf_id == 0)
10534     {
10535       errmsg
10536         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
10537       return -99;
10538     }
10539
10540   if (vec_len (low_ports) == 0)
10541     {
10542       errmsg ("At least one port or port range required");
10543       return -99;
10544     }
10545
10546   M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
10547
10548   mp->is_add = is_add;
10549
10550   clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
10551
10552   mp->number_of_ranges = vec_len (low_ports);
10553
10554   clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
10555   vec_free (low_ports);
10556
10557   clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
10558   vec_free (high_ports);
10559
10560   mp->vrf_id = ntohl (vrf_id);
10561
10562   S (mp);
10563   W (ret);
10564   return ret;
10565 }
10566
10567 int
10568 api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
10569 {
10570   unformat_input_t *input = vam->input;
10571   vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
10572   u32 sw_if_index = ~0;
10573   int vrf_set = 0;
10574   u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
10575   u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
10576   u8 is_add = 1;
10577   int ret;
10578
10579   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10580     {
10581       if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10582         ;
10583       else if (unformat (input, "sw_if_index %d", &sw_if_index))
10584         ;
10585       else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
10586         vrf_set = 1;
10587       else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
10588         vrf_set = 1;
10589       else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
10590         vrf_set = 1;
10591       else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
10592         vrf_set = 1;
10593       else if (unformat (input, "del"))
10594         is_add = 0;
10595       else
10596         break;
10597     }
10598
10599   if (sw_if_index == ~0)
10600     {
10601       errmsg ("Interface required but not specified");
10602       return -99;
10603     }
10604
10605   if (vrf_set == 0)
10606     {
10607       errmsg ("VRF ID required but not specified");
10608       return -99;
10609     }
10610
10611   if (tcp_out_vrf_id == 0
10612       || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
10613     {
10614       errmsg
10615         ("VRF ID should not be default. Should be distinct VRF for this purpose.");
10616       return -99;
10617     }
10618
10619   /* Construct the API message */
10620   M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
10621
10622   mp->sw_if_index = ntohl (sw_if_index);
10623   mp->is_add = is_add;
10624   mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
10625   mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
10626   mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
10627   mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
10628
10629   /* send it... */
10630   S (mp);
10631
10632   /* Wait for a reply... */
10633   W (ret);
10634   return ret;
10635 }
10636
10637 static int
10638 api_set_punt (vat_main_t * vam)
10639 {
10640   unformat_input_t *i = vam->input;
10641   vl_api_address_family_t af;
10642   vl_api_set_punt_t *mp;
10643   u32 protocol = ~0;
10644   u32 port = ~0;
10645   int is_add = 1;
10646   int ret;
10647
10648   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10649     {
10650       if (unformat (i, "%U", unformat_vl_api_address_family, &af))
10651         ;
10652       else if (unformat (i, "protocol %d", &protocol))
10653         ;
10654       else if (unformat (i, "port %d", &port))
10655         ;
10656       else if (unformat (i, "del"))
10657         is_add = 0;
10658       else
10659         {
10660           clib_warning ("parse error '%U'", format_unformat_error, i);
10661           return -99;
10662         }
10663     }
10664
10665   M (SET_PUNT, mp);
10666
10667   mp->is_add = (u8) is_add;
10668   mp->punt.type = PUNT_API_TYPE_L4;
10669   mp->punt.punt.l4.af = af;
10670   mp->punt.punt.l4.protocol = (u8) protocol;
10671   mp->punt.punt.l4.port = htons ((u16) port);
10672
10673   S (mp);
10674   W (ret);
10675   return ret;
10676 }
10677
10678 static int
10679 api_delete_subif (vat_main_t * vam)
10680 {
10681   unformat_input_t *i = vam->input;
10682   vl_api_delete_subif_t *mp;
10683   u32 sw_if_index = ~0;
10684   int ret;
10685
10686   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10687     {
10688       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10689         ;
10690       if (unformat (i, "sw_if_index %d", &sw_if_index))
10691         ;
10692       else
10693         break;
10694     }
10695
10696   if (sw_if_index == ~0)
10697     {
10698       errmsg ("missing sw_if_index");
10699       return -99;
10700     }
10701
10702   /* Construct the API message */
10703   M (DELETE_SUBIF, mp);
10704   mp->sw_if_index = ntohl (sw_if_index);
10705
10706   S (mp);
10707   W (ret);
10708   return ret;
10709 }
10710
10711 #define foreach_pbb_vtr_op      \
10712 _("disable",  L2_VTR_DISABLED)  \
10713 _("pop",  L2_VTR_POP_2)         \
10714 _("push",  L2_VTR_PUSH_2)
10715
10716 static int
10717 api_l2_interface_pbb_tag_rewrite (vat_main_t * vam)
10718 {
10719   unformat_input_t *i = vam->input;
10720   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
10721   u32 sw_if_index = ~0, vtr_op = ~0;
10722   u16 outer_tag = ~0;
10723   u8 dmac[6], smac[6];
10724   u8 dmac_set = 0, smac_set = 0;
10725   u16 vlanid = 0;
10726   u32 sid = ~0;
10727   u32 tmp;
10728   int ret;
10729
10730   /* Shut up coverity */
10731   clib_memset (dmac, 0, sizeof (dmac));
10732   clib_memset (smac, 0, sizeof (smac));
10733
10734   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10735     {
10736       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10737         ;
10738       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10739         ;
10740       else if (unformat (i, "vtr_op %d", &vtr_op))
10741         ;
10742 #define _(n,v) else if (unformat(i, n)) {vtr_op = v;}
10743       foreach_pbb_vtr_op
10744 #undef _
10745         else if (unformat (i, "translate_pbb_stag"))
10746         {
10747           if (unformat (i, "%d", &tmp))
10748             {
10749               vtr_op = L2_VTR_TRANSLATE_2_1;
10750               outer_tag = tmp;
10751             }
10752           else
10753             {
10754               errmsg
10755                 ("translate_pbb_stag operation requires outer tag definition");
10756               return -99;
10757             }
10758         }
10759       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
10760         dmac_set++;
10761       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
10762         smac_set++;
10763       else if (unformat (i, "sid %d", &sid))
10764         ;
10765       else if (unformat (i, "vlanid %d", &tmp))
10766         vlanid = tmp;
10767       else
10768         {
10769           clib_warning ("parse error '%U'", format_unformat_error, i);
10770           return -99;
10771         }
10772     }
10773
10774   if ((sw_if_index == ~0) || (vtr_op == ~0))
10775     {
10776       errmsg ("missing sw_if_index or vtr operation");
10777       return -99;
10778     }
10779   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2))
10780       && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
10781     {
10782       errmsg
10783         ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid");
10784       return -99;
10785     }
10786
10787   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
10788   mp->sw_if_index = ntohl (sw_if_index);
10789   mp->vtr_op = ntohl (vtr_op);
10790   mp->outer_tag = ntohs (outer_tag);
10791   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
10792   clib_memcpy (mp->b_smac, smac, sizeof (smac));
10793   mp->b_vlanid = ntohs (vlanid);
10794   mp->i_sid = ntohl (sid);
10795
10796   S (mp);
10797   W (ret);
10798   return ret;
10799 }
10800
10801 static int
10802 api_sw_interface_tag_add_del (vat_main_t * vam)
10803 {
10804   unformat_input_t *i = vam->input;
10805   vl_api_sw_interface_tag_add_del_t *mp;
10806   u32 sw_if_index = ~0;
10807   u8 *tag = 0;
10808   u8 enable = 1;
10809   int ret;
10810
10811   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10812     {
10813       if (unformat (i, "tag %s", &tag))
10814         ;
10815       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10816         ;
10817       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10818         ;
10819       else if (unformat (i, "del"))
10820         enable = 0;
10821       else
10822         break;
10823     }
10824
10825   if (sw_if_index == ~0)
10826     {
10827       errmsg ("missing interface name or sw_if_index");
10828       return -99;
10829     }
10830
10831   if (enable && (tag == 0))
10832     {
10833       errmsg ("no tag specified");
10834       return -99;
10835     }
10836
10837   /* Construct the API message */
10838   M (SW_INTERFACE_TAG_ADD_DEL, mp);
10839   mp->sw_if_index = ntohl (sw_if_index);
10840   mp->is_add = enable;
10841   if (enable)
10842     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
10843   vec_free (tag);
10844
10845   S (mp);
10846   W (ret);
10847   return ret;
10848 }
10849
10850 static int
10851 api_sw_interface_add_del_mac_address (vat_main_t * vam)
10852 {
10853   unformat_input_t *i = vam->input;
10854   vl_api_mac_address_t mac = { 0 };
10855   vl_api_sw_interface_add_del_mac_address_t *mp;
10856   u32 sw_if_index = ~0;
10857   u8 is_add = 1;
10858   u8 mac_set = 0;
10859   int ret;
10860
10861   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10862     {
10863       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10864         ;
10865       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10866         ;
10867       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
10868         mac_set++;
10869       else if (unformat (i, "del"))
10870         is_add = 0;
10871       else
10872         break;
10873     }
10874
10875   if (sw_if_index == ~0)
10876     {
10877       errmsg ("missing interface name or sw_if_index");
10878       return -99;
10879     }
10880
10881   if (!mac_set)
10882     {
10883       errmsg ("missing MAC address");
10884       return -99;
10885     }
10886
10887   /* Construct the API message */
10888   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
10889   mp->sw_if_index = ntohl (sw_if_index);
10890   mp->is_add = is_add;
10891   clib_memcpy (&mp->addr, &mac, sizeof (mac));
10892
10893   S (mp);
10894   W (ret);
10895   return ret;
10896 }
10897
10898 static void vl_api_l2_xconnect_details_t_handler
10899   (vl_api_l2_xconnect_details_t * mp)
10900 {
10901   vat_main_t *vam = &vat_main;
10902
10903   print (vam->ofp, "%15d%15d",
10904          ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index));
10905 }
10906
10907 static void vl_api_l2_xconnect_details_t_handler_json
10908   (vl_api_l2_xconnect_details_t * mp)
10909 {
10910   vat_main_t *vam = &vat_main;
10911   vat_json_node_t *node = NULL;
10912
10913   if (VAT_JSON_ARRAY != vam->json_tree.type)
10914     {
10915       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
10916       vat_json_init_array (&vam->json_tree);
10917     }
10918   node = vat_json_array_add (&vam->json_tree);
10919
10920   vat_json_init_object (node);
10921   vat_json_object_add_uint (node, "rx_sw_if_index",
10922                             ntohl (mp->rx_sw_if_index));
10923   vat_json_object_add_uint (node, "tx_sw_if_index",
10924                             ntohl (mp->tx_sw_if_index));
10925 }
10926
10927 static int
10928 api_l2_xconnect_dump (vat_main_t * vam)
10929 {
10930   vl_api_l2_xconnect_dump_t *mp;
10931   vl_api_control_ping_t *mp_ping;
10932   int ret;
10933
10934   if (!vam->json_output)
10935     {
10936       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
10937     }
10938
10939   M (L2_XCONNECT_DUMP, mp);
10940
10941   S (mp);
10942
10943   /* Use a control ping for synchronization */
10944   MPING (CONTROL_PING, mp_ping);
10945   S (mp_ping);
10946
10947   W (ret);
10948   return ret;
10949 }
10950
10951 static int
10952 api_hw_interface_set_mtu (vat_main_t * vam)
10953 {
10954   unformat_input_t *i = vam->input;
10955   vl_api_hw_interface_set_mtu_t *mp;
10956   u32 sw_if_index = ~0;
10957   u32 mtu = 0;
10958   int ret;
10959
10960   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
10961     {
10962       if (unformat (i, "mtu %d", &mtu))
10963         ;
10964       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
10965         ;
10966       else if (unformat (i, "sw_if_index %d", &sw_if_index))
10967         ;
10968       else
10969         break;
10970     }
10971
10972   if (sw_if_index == ~0)
10973     {
10974       errmsg ("missing interface name or sw_if_index");
10975       return -99;
10976     }
10977
10978   if (mtu == 0)
10979     {
10980       errmsg ("no mtu specified");
10981       return -99;
10982     }
10983
10984   /* Construct the API message */
10985   M (HW_INTERFACE_SET_MTU, mp);
10986   mp->sw_if_index = ntohl (sw_if_index);
10987   mp->mtu = ntohs ((u16) mtu);
10988
10989   S (mp);
10990   W (ret);
10991   return ret;
10992 }
10993
10994 static int
10995 api_p2p_ethernet_add (vat_main_t * vam)
10996 {
10997   unformat_input_t *i = vam->input;
10998   vl_api_p2p_ethernet_add_t *mp;
10999   u32 parent_if_index = ~0;
11000   u32 sub_id = ~0;
11001   u8 remote_mac[6];
11002   u8 mac_set = 0;
11003   int ret;
11004
11005   clib_memset (remote_mac, 0, sizeof (remote_mac));
11006   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11007     {
11008       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
11009         ;
11010       else if (unformat (i, "sw_if_index %d", &parent_if_index))
11011         ;
11012       else
11013         if (unformat
11014             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
11015         mac_set++;
11016       else if (unformat (i, "sub_id %d", &sub_id))
11017         ;
11018       else
11019         {
11020           clib_warning ("parse error '%U'", format_unformat_error, i);
11021           return -99;
11022         }
11023     }
11024
11025   if (parent_if_index == ~0)
11026     {
11027       errmsg ("missing interface name or sw_if_index");
11028       return -99;
11029     }
11030   if (mac_set == 0)
11031     {
11032       errmsg ("missing remote mac address");
11033       return -99;
11034     }
11035   if (sub_id == ~0)
11036     {
11037       errmsg ("missing sub-interface id");
11038       return -99;
11039     }
11040
11041   M (P2P_ETHERNET_ADD, mp);
11042   mp->parent_if_index = ntohl (parent_if_index);
11043   mp->subif_id = ntohl (sub_id);
11044   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
11045
11046   S (mp);
11047   W (ret);
11048   return ret;
11049 }
11050
11051 static int
11052 api_p2p_ethernet_del (vat_main_t * vam)
11053 {
11054   unformat_input_t *i = vam->input;
11055   vl_api_p2p_ethernet_del_t *mp;
11056   u32 parent_if_index = ~0;
11057   u8 remote_mac[6];
11058   u8 mac_set = 0;
11059   int ret;
11060
11061   clib_memset (remote_mac, 0, sizeof (remote_mac));
11062   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11063     {
11064       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index))
11065         ;
11066       else if (unformat (i, "sw_if_index %d", &parent_if_index))
11067         ;
11068       else
11069         if (unformat
11070             (i, "remote_mac %U", unformat_ethernet_address, remote_mac))
11071         mac_set++;
11072       else
11073         {
11074           clib_warning ("parse error '%U'", format_unformat_error, i);
11075           return -99;
11076         }
11077     }
11078
11079   if (parent_if_index == ~0)
11080     {
11081       errmsg ("missing interface name or sw_if_index");
11082       return -99;
11083     }
11084   if (mac_set == 0)
11085     {
11086       errmsg ("missing remote mac address");
11087       return -99;
11088     }
11089
11090   M (P2P_ETHERNET_DEL, mp);
11091   mp->parent_if_index = ntohl (parent_if_index);
11092   clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac));
11093
11094   S (mp);
11095   W (ret);
11096   return ret;
11097 }
11098
11099 static int
11100 api_tcp_configure_src_addresses (vat_main_t * vam)
11101 {
11102   vl_api_tcp_configure_src_addresses_t *mp;
11103   unformat_input_t *i = vam->input;
11104   vl_api_address_t first, last;
11105   u8 range_set = 0;
11106   u32 vrf_id = 0;
11107   int ret;
11108
11109   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11110     {
11111       if (unformat (i, "%U - %U",
11112                     unformat_vl_api_address, &first,
11113                     unformat_vl_api_address, &last))
11114         {
11115           if (range_set)
11116             {
11117               errmsg ("one range per message (range already set)");
11118               return -99;
11119             }
11120           range_set = 1;
11121         }
11122       else if (unformat (i, "vrf %d", &vrf_id))
11123         ;
11124       else
11125         break;
11126     }
11127
11128   if (range_set == 0)
11129     {
11130       errmsg ("address range not set");
11131       return -99;
11132     }
11133
11134   M (TCP_CONFIGURE_SRC_ADDRESSES, mp);
11135
11136   mp->vrf_id = ntohl (vrf_id);
11137   clib_memcpy (&mp->first_address, &first, sizeof (first));
11138   clib_memcpy (&mp->last_address, &last, sizeof (last));
11139
11140   S (mp);
11141   W (ret);
11142   return ret;
11143 }
11144
11145 static void vl_api_app_namespace_add_del_reply_t_handler
11146   (vl_api_app_namespace_add_del_reply_t * mp)
11147 {
11148   vat_main_t *vam = &vat_main;
11149   i32 retval = ntohl (mp->retval);
11150   if (vam->async_mode)
11151     {
11152       vam->async_errors += (retval < 0);
11153     }
11154   else
11155     {
11156       vam->retval = retval;
11157       if (retval == 0)
11158         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
11159       vam->result_ready = 1;
11160     }
11161 }
11162
11163 static void vl_api_app_namespace_add_del_reply_t_handler_json
11164   (vl_api_app_namespace_add_del_reply_t * mp)
11165 {
11166   vat_main_t *vam = &vat_main;
11167   vat_json_node_t node;
11168
11169   vat_json_init_object (&node);
11170   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
11171   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
11172
11173   vat_json_print (vam->ofp, &node);
11174   vat_json_free (&node);
11175
11176   vam->retval = ntohl (mp->retval);
11177   vam->result_ready = 1;
11178 }
11179
11180 static int
11181 api_app_namespace_add_del (vat_main_t * vam)
11182 {
11183   vl_api_app_namespace_add_del_t *mp;
11184   unformat_input_t *i = vam->input;
11185   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
11186   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
11187   u64 secret;
11188   int ret;
11189
11190   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11191     {
11192       if (unformat (i, "id %_%v%_", &ns_id))
11193         ;
11194       else if (unformat (i, "secret %lu", &secret))
11195         secret_set = 1;
11196       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11197         sw_if_index_set = 1;
11198       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
11199         ;
11200       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
11201         ;
11202       else
11203         break;
11204     }
11205   if (!ns_id || !secret_set || !sw_if_index_set)
11206     {
11207       errmsg ("namespace id, secret and sw_if_index must be set");
11208       return -99;
11209     }
11210   if (vec_len (ns_id) > 64)
11211     {
11212       errmsg ("namespace id too long");
11213       return -99;
11214     }
11215   M (APP_NAMESPACE_ADD_DEL, mp);
11216
11217   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
11218   mp->secret = clib_host_to_net_u64 (secret);
11219   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
11220   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
11221   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
11222   vec_free (ns_id);
11223   S (mp);
11224   W (ret);
11225   return ret;
11226 }
11227
11228 static int
11229 api_sock_init_shm (vat_main_t * vam)
11230 {
11231 #if VPP_API_TEST_BUILTIN == 0
11232   unformat_input_t *i = vam->input;
11233   vl_api_shm_elem_config_t *config = 0;
11234   u64 size = 64 << 20;
11235   int rv;
11236
11237   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11238     {
11239       if (unformat (i, "size %U", unformat_memory_size, &size))
11240         ;
11241       else
11242         break;
11243     }
11244
11245   /*
11246    * Canned custom ring allocator config.
11247    * Should probably parse all of this
11248    */
11249   vec_validate (config, 6);
11250   config[0].type = VL_API_VLIB_RING;
11251   config[0].size = 256;
11252   config[0].count = 32;
11253
11254   config[1].type = VL_API_VLIB_RING;
11255   config[1].size = 1024;
11256   config[1].count = 16;
11257
11258   config[2].type = VL_API_VLIB_RING;
11259   config[2].size = 4096;
11260   config[2].count = 2;
11261
11262   config[3].type = VL_API_CLIENT_RING;
11263   config[3].size = 256;
11264   config[3].count = 32;
11265
11266   config[4].type = VL_API_CLIENT_RING;
11267   config[4].size = 1024;
11268   config[4].count = 16;
11269
11270   config[5].type = VL_API_CLIENT_RING;
11271   config[5].size = 4096;
11272   config[5].count = 2;
11273
11274   config[6].type = VL_API_QUEUE;
11275   config[6].count = 128;
11276   config[6].size = sizeof (uword);
11277
11278   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
11279   if (!rv)
11280     vam->client_index_invalid = 1;
11281   return rv;
11282 #else
11283   return -99;
11284 #endif
11285 }
11286
11287 static void
11288 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
11289 {
11290   vat_main_t *vam = &vat_main;
11291   fib_prefix_t lcl, rmt;
11292
11293   ip_prefix_decode (&mp->lcl, &lcl);
11294   ip_prefix_decode (&mp->rmt, &rmt);
11295
11296   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
11297     {
11298       print (vam->ofp,
11299              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
11300              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
11301              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
11302              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
11303              &rmt.fp_addr.ip4, rmt.fp_len,
11304              clib_net_to_host_u16 (mp->rmt_port),
11305              clib_net_to_host_u32 (mp->action_index), mp->tag);
11306     }
11307   else
11308     {
11309       print (vam->ofp,
11310              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
11311              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
11312              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
11313              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
11314              &rmt.fp_addr.ip6, rmt.fp_len,
11315              clib_net_to_host_u16 (mp->rmt_port),
11316              clib_net_to_host_u32 (mp->action_index), mp->tag);
11317     }
11318 }
11319
11320 static void
11321 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
11322                                              mp)
11323 {
11324   vat_main_t *vam = &vat_main;
11325   vat_json_node_t *node = NULL;
11326   struct in6_addr ip6;
11327   struct in_addr ip4;
11328
11329   fib_prefix_t lcl, rmt;
11330
11331   ip_prefix_decode (&mp->lcl, &lcl);
11332   ip_prefix_decode (&mp->rmt, &rmt);
11333
11334   if (VAT_JSON_ARRAY != vam->json_tree.type)
11335     {
11336       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
11337       vat_json_init_array (&vam->json_tree);
11338     }
11339   node = vat_json_array_add (&vam->json_tree);
11340   vat_json_init_object (node);
11341
11342   vat_json_object_add_uint (node, "appns_index",
11343                             clib_net_to_host_u32 (mp->appns_index));
11344   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
11345   vat_json_object_add_uint (node, "scope", mp->scope);
11346   vat_json_object_add_uint (node, "action_index",
11347                             clib_net_to_host_u32 (mp->action_index));
11348   vat_json_object_add_uint (node, "lcl_port",
11349                             clib_net_to_host_u16 (mp->lcl_port));
11350   vat_json_object_add_uint (node, "rmt_port",
11351                             clib_net_to_host_u16 (mp->rmt_port));
11352   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
11353   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
11354   vat_json_object_add_string_copy (node, "tag", mp->tag);
11355   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
11356     {
11357       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
11358       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
11359       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
11360       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
11361     }
11362   else
11363     {
11364       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
11365       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
11366       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
11367       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
11368     }
11369 }
11370
11371 static int
11372 api_session_rule_add_del (vat_main_t * vam)
11373 {
11374   vl_api_session_rule_add_del_t *mp;
11375   unformat_input_t *i = vam->input;
11376   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
11377   u32 appns_index = 0, scope = 0;
11378   ip4_address_t lcl_ip4, rmt_ip4;
11379   ip6_address_t lcl_ip6, rmt_ip6;
11380   u8 is_ip4 = 1, conn_set = 0;
11381   u8 is_add = 1, *tag = 0;
11382   int ret;
11383   fib_prefix_t lcl, rmt;
11384
11385   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11386     {
11387       if (unformat (i, "del"))
11388         is_add = 0;
11389       else if (unformat (i, "add"))
11390         ;
11391       else if (unformat (i, "proto tcp"))
11392         proto = 0;
11393       else if (unformat (i, "proto udp"))
11394         proto = 1;
11395       else if (unformat (i, "appns %d", &appns_index))
11396         ;
11397       else if (unformat (i, "scope %d", &scope))
11398         ;
11399       else if (unformat (i, "tag %_%v%_", &tag))
11400         ;
11401       else
11402         if (unformat
11403             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
11404              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
11405              &rmt_port))
11406         {
11407           is_ip4 = 1;
11408           conn_set = 1;
11409         }
11410       else
11411         if (unformat
11412             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
11413              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
11414              &rmt_port))
11415         {
11416           is_ip4 = 0;
11417           conn_set = 1;
11418         }
11419       else if (unformat (i, "action %d", &action))
11420         ;
11421       else
11422         break;
11423     }
11424   if (proto == ~0 || !conn_set || action == ~0)
11425     {
11426       errmsg ("transport proto, connection and action must be set");
11427       return -99;
11428     }
11429
11430   if (scope > 3)
11431     {
11432       errmsg ("scope should be 0-3");
11433       return -99;
11434     }
11435
11436   M (SESSION_RULE_ADD_DEL, mp);
11437
11438   clib_memset (&lcl, 0, sizeof (lcl));
11439   clib_memset (&rmt, 0, sizeof (rmt));
11440   if (is_ip4)
11441     {
11442       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
11443       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
11444       lcl.fp_len = lcl_plen;
11445       rmt.fp_len = rmt_plen;
11446     }
11447   else
11448     {
11449       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
11450       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
11451       lcl.fp_len = lcl_plen;
11452       rmt.fp_len = rmt_plen;
11453     }
11454
11455
11456   ip_prefix_encode (&lcl, &mp->lcl);
11457   ip_prefix_encode (&rmt, &mp->rmt);
11458   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
11459   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
11460   mp->transport_proto =
11461     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
11462   mp->action_index = clib_host_to_net_u32 (action);
11463   mp->appns_index = clib_host_to_net_u32 (appns_index);
11464   mp->scope = scope;
11465   mp->is_add = is_add;
11466   if (tag)
11467     {
11468       clib_memcpy (mp->tag, tag, vec_len (tag));
11469       vec_free (tag);
11470     }
11471
11472   S (mp);
11473   W (ret);
11474   return ret;
11475 }
11476
11477 static int
11478 api_session_rules_dump (vat_main_t * vam)
11479 {
11480   vl_api_session_rules_dump_t *mp;
11481   vl_api_control_ping_t *mp_ping;
11482   int ret;
11483
11484   if (!vam->json_output)
11485     {
11486       print (vam->ofp, "%=20s", "Session Rules");
11487     }
11488
11489   M (SESSION_RULES_DUMP, mp);
11490   /* send it... */
11491   S (mp);
11492
11493   /* Use a control ping for synchronization */
11494   MPING (CONTROL_PING, mp_ping);
11495   S (mp_ping);
11496
11497   /* Wait for a reply... */
11498   W (ret);
11499   return ret;
11500 }
11501
11502 static int
11503 api_ip_container_proxy_add_del (vat_main_t * vam)
11504 {
11505   vl_api_ip_container_proxy_add_del_t *mp;
11506   unformat_input_t *i = vam->input;
11507   u32 sw_if_index = ~0;
11508   vl_api_prefix_t pfx = { };
11509   u8 is_add = 1;
11510   int ret;
11511
11512   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11513     {
11514       if (unformat (i, "del"))
11515         is_add = 0;
11516       else if (unformat (i, "add"))
11517         ;
11518       if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
11519         ;
11520       else if (unformat (i, "sw_if_index %u", &sw_if_index))
11521         ;
11522       else
11523         break;
11524     }
11525   if (sw_if_index == ~0 || pfx.len == 0)
11526     {
11527       errmsg ("address and sw_if_index must be set");
11528       return -99;
11529     }
11530
11531   M (IP_CONTAINER_PROXY_ADD_DEL, mp);
11532
11533   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
11534   mp->is_add = is_add;
11535   clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
11536
11537   S (mp);
11538   W (ret);
11539   return ret;
11540 }
11541
11542 static int
11543 api_qos_record_enable_disable (vat_main_t * vam)
11544 {
11545   unformat_input_t *i = vam->input;
11546   vl_api_qos_record_enable_disable_t *mp;
11547   u32 sw_if_index, qs = 0xff;
11548   u8 sw_if_index_set = 0;
11549   u8 enable = 1;
11550   int ret;
11551
11552   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
11553     {
11554       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
11555         sw_if_index_set = 1;
11556       else if (unformat (i, "sw_if_index %d", &sw_if_index))
11557         sw_if_index_set = 1;
11558       else if (unformat (i, "%U", unformat_qos_source, &qs))
11559         ;
11560       else if (unformat (i, "disable"))
11561         enable = 0;
11562       else
11563         {
11564           clib_warning ("parse error '%U'", format_unformat_error, i);
11565           return -99;
11566         }
11567     }
11568
11569   if (sw_if_index_set == 0)
11570     {
11571       errmsg ("missing interface name or sw_if_index");
11572       return -99;
11573     }
11574   if (qs == 0xff)
11575     {
11576       errmsg ("input location must be specified");
11577       return -99;
11578     }
11579
11580   M (QOS_RECORD_ENABLE_DISABLE, mp);
11581
11582   mp->record.sw_if_index = ntohl (sw_if_index);
11583   mp->record.input_source = qs;
11584   mp->enable = enable;
11585
11586   S (mp);
11587   W (ret);
11588   return ret;
11589 }
11590
11591
11592 static int
11593 q_or_quit (vat_main_t * vam)
11594 {
11595 #if VPP_API_TEST_BUILTIN == 0
11596   longjmp (vam->jump_buf, 1);
11597 #endif
11598   return 0;                     /* not so much */
11599 }
11600
11601 static int
11602 q (vat_main_t * vam)
11603 {
11604   return q_or_quit (vam);
11605 }
11606
11607 static int
11608 quit (vat_main_t * vam)
11609 {
11610   return q_or_quit (vam);
11611 }
11612
11613 static int
11614 comment (vat_main_t * vam)
11615 {
11616   return 0;
11617 }
11618
11619 static int
11620 elog_save (vat_main_t * vam)
11621 {
11622 #if VPP_API_TEST_BUILTIN == 0
11623   elog_main_t *em = &vam->elog_main;
11624   unformat_input_t *i = vam->input;
11625   char *file, *chroot_file;
11626   clib_error_t *error;
11627
11628   if (!unformat (i, "%s", &file))
11629     {
11630       errmsg ("expected file name, got `%U'", format_unformat_error, i);
11631       return 0;
11632     }
11633
11634   /* It's fairly hard to get "../oopsie" through unformat; just in case */
11635   if (strstr (file, "..") || index (file, '/'))
11636     {
11637       errmsg ("illegal characters in filename '%s'", file);
11638       return 0;
11639     }
11640
11641   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
11642
11643   vec_free (file);
11644
11645   errmsg ("Saving %wd of %wd events to %s",
11646           elog_n_events_in_buffer (em),
11647           elog_buffer_capacity (em), chroot_file);
11648
11649   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
11650   vec_free (chroot_file);
11651
11652   if (error)
11653     clib_error_report (error);
11654 #else
11655   errmsg ("Use the vpp event loger...");
11656 #endif
11657
11658   return 0;
11659 }
11660
11661 static int
11662 elog_setup (vat_main_t * vam)
11663 {
11664 #if VPP_API_TEST_BUILTIN == 0
11665   elog_main_t *em = &vam->elog_main;
11666   unformat_input_t *i = vam->input;
11667   u32 nevents = 128 << 10;
11668
11669   (void) unformat (i, "nevents %d", &nevents);
11670
11671   elog_init (em, nevents);
11672   vl_api_set_elog_main (em);
11673   vl_api_set_elog_trace_api_messages (1);
11674   errmsg ("Event logger initialized with %u events", nevents);
11675 #else
11676   errmsg ("Use the vpp event loger...");
11677 #endif
11678   return 0;
11679 }
11680
11681 static int
11682 elog_enable (vat_main_t * vam)
11683 {
11684 #if VPP_API_TEST_BUILTIN == 0
11685   elog_main_t *em = &vam->elog_main;
11686
11687   elog_enable_disable (em, 1 /* enable */ );
11688   vl_api_set_elog_trace_api_messages (1);
11689   errmsg ("Event logger enabled...");
11690 #else
11691   errmsg ("Use the vpp event loger...");
11692 #endif
11693   return 0;
11694 }
11695
11696 static int
11697 elog_disable (vat_main_t * vam)
11698 {
11699 #if VPP_API_TEST_BUILTIN == 0
11700   elog_main_t *em = &vam->elog_main;
11701
11702   elog_enable_disable (em, 0 /* enable */ );
11703   vl_api_set_elog_trace_api_messages (1);
11704   errmsg ("Event logger disabled...");
11705 #else
11706   errmsg ("Use the vpp event loger...");
11707 #endif
11708   return 0;
11709 }
11710
11711 static int
11712 statseg (vat_main_t * vam)
11713 {
11714   ssvm_private_t *ssvmp = &vam->stat_segment;
11715   ssvm_shared_header_t *shared_header = ssvmp->sh;
11716   vlib_counter_t **counters;
11717   u64 thread0_index1_packets;
11718   u64 thread0_index1_bytes;
11719   f64 vector_rate, input_rate;
11720   uword *p;
11721
11722   uword *counter_vector_by_name;
11723   if (vam->stat_segment_lockp == 0)
11724     {
11725       errmsg ("Stat segment not mapped...");
11726       return -99;
11727     }
11728
11729   /* look up "/if/rx for sw_if_index 1 as a test */
11730
11731   clib_spinlock_lock (vam->stat_segment_lockp);
11732
11733   counter_vector_by_name = (uword *) shared_header->opaque[1];
11734
11735   p = hash_get_mem (counter_vector_by_name, "/if/rx");
11736   if (p == 0)
11737     {
11738       clib_spinlock_unlock (vam->stat_segment_lockp);
11739       errmsg ("/if/tx not found?");
11740       return -99;
11741     }
11742
11743   /* Fish per-thread vector of combined counters from shared memory */
11744   counters = (vlib_counter_t **) p[0];
11745
11746   if (vec_len (counters[0]) < 2)
11747     {
11748       clib_spinlock_unlock (vam->stat_segment_lockp);
11749       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
11750       return -99;
11751     }
11752
11753   /* Read thread 0 sw_if_index 1 counter */
11754   thread0_index1_packets = counters[0][1].packets;
11755   thread0_index1_bytes = counters[0][1].bytes;
11756
11757   p = hash_get_mem (counter_vector_by_name, "vector_rate");
11758   if (p == 0)
11759     {
11760       clib_spinlock_unlock (vam->stat_segment_lockp);
11761       errmsg ("vector_rate not found?");
11762       return -99;
11763     }
11764
11765   vector_rate = *(f64 *) (p[0]);
11766   p = hash_get_mem (counter_vector_by_name, "input_rate");
11767   if (p == 0)
11768     {
11769       clib_spinlock_unlock (vam->stat_segment_lockp);
11770       errmsg ("input_rate not found?");
11771       return -99;
11772     }
11773   input_rate = *(f64 *) (p[0]);
11774
11775   clib_spinlock_unlock (vam->stat_segment_lockp);
11776
11777   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
11778          vector_rate, input_rate);
11779   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
11780          thread0_index1_packets, thread0_index1_bytes);
11781
11782   return 0;
11783 }
11784
11785 static int
11786 cmd_cmp (void *a1, void *a2)
11787 {
11788   u8 **c1 = a1;
11789   u8 **c2 = a2;
11790
11791   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
11792 }
11793
11794 static int
11795 help (vat_main_t * vam)
11796 {
11797   u8 **cmds = 0;
11798   u8 *name = 0;
11799   hash_pair_t *p;
11800   unformat_input_t *i = vam->input;
11801   int j;
11802
11803   if (unformat (i, "%s", &name))
11804     {
11805       uword *hs;
11806
11807       vec_add1 (name, 0);
11808
11809       hs = hash_get_mem (vam->help_by_name, name);
11810       if (hs)
11811         print (vam->ofp, "usage: %s %s", name, hs[0]);
11812       else
11813         print (vam->ofp, "No such msg / command '%s'", name);
11814       vec_free (name);
11815       return 0;
11816     }
11817
11818   print (vam->ofp, "Help is available for the following:");
11819
11820     /* *INDENT-OFF* */
11821     hash_foreach_pair (p, vam->function_by_name,
11822     ({
11823       vec_add1 (cmds, (u8 *)(p->key));
11824     }));
11825     /* *INDENT-ON* */
11826
11827   vec_sort_with_function (cmds, cmd_cmp);
11828
11829   for (j = 0; j < vec_len (cmds); j++)
11830     print (vam->ofp, "%s", cmds[j]);
11831
11832   vec_free (cmds);
11833   return 0;
11834 }
11835
11836 static int
11837 set (vat_main_t * vam)
11838 {
11839   u8 *name = 0, *value = 0;
11840   unformat_input_t *i = vam->input;
11841
11842   if (unformat (i, "%s", &name))
11843     {
11844       /* The input buffer is a vector, not a string. */
11845       value = vec_dup (i->buffer);
11846       vec_delete (value, i->index, 0);
11847       /* Almost certainly has a trailing newline */
11848       if (value[vec_len (value) - 1] == '\n')
11849         value[vec_len (value) - 1] = 0;
11850       /* Make sure it's a proper string, one way or the other */
11851       vec_add1 (value, 0);
11852       (void) clib_macro_set_value (&vam->macro_main,
11853                                    (char *) name, (char *) value);
11854     }
11855   else
11856     errmsg ("usage: set <name> <value>");
11857
11858   vec_free (name);
11859   vec_free (value);
11860   return 0;
11861 }
11862
11863 static int
11864 unset (vat_main_t * vam)
11865 {
11866   u8 *name = 0;
11867
11868   if (unformat (vam->input, "%s", &name))
11869     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
11870       errmsg ("unset: %s wasn't set", name);
11871   vec_free (name);
11872   return 0;
11873 }
11874
11875 typedef struct
11876 {
11877   u8 *name;
11878   u8 *value;
11879 } macro_sort_t;
11880
11881
11882 static int
11883 macro_sort_cmp (void *a1, void *a2)
11884 {
11885   macro_sort_t *s1 = a1;
11886   macro_sort_t *s2 = a2;
11887
11888   return strcmp ((char *) (s1->name), (char *) (s2->name));
11889 }
11890
11891 static int
11892 dump_macro_table (vat_main_t * vam)
11893 {
11894   macro_sort_t *sort_me = 0, *sm;
11895   int i;
11896   hash_pair_t *p;
11897
11898     /* *INDENT-OFF* */
11899     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
11900     ({
11901       vec_add2 (sort_me, sm, 1);
11902       sm->name = (u8 *)(p->key);
11903       sm->value = (u8 *) (p->value[0]);
11904     }));
11905     /* *INDENT-ON* */
11906
11907   vec_sort_with_function (sort_me, macro_sort_cmp);
11908
11909   if (vec_len (sort_me))
11910     print (vam->ofp, "%-15s%s", "Name", "Value");
11911   else
11912     print (vam->ofp, "The macro table is empty...");
11913
11914   for (i = 0; i < vec_len (sort_me); i++)
11915     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
11916   return 0;
11917 }
11918
11919 static int
11920 dump_node_table (vat_main_t * vam)
11921 {
11922   int i, j;
11923   vlib_node_t *node, *next_node;
11924
11925   if (vec_len (vam->graph_nodes) == 0)
11926     {
11927       print (vam->ofp, "Node table empty, issue get_node_graph...");
11928       return 0;
11929     }
11930
11931   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
11932     {
11933       node = vam->graph_nodes[0][i];
11934       print (vam->ofp, "[%d] %s", i, node->name);
11935       for (j = 0; j < vec_len (node->next_nodes); j++)
11936         {
11937           if (node->next_nodes[j] != ~0)
11938             {
11939               next_node = vam->graph_nodes[0][node->next_nodes[j]];
11940               print (vam->ofp, "  [%d] %s", j, next_node->name);
11941             }
11942         }
11943     }
11944   return 0;
11945 }
11946
11947 static int
11948 value_sort_cmp (void *a1, void *a2)
11949 {
11950   name_sort_t *n1 = a1;
11951   name_sort_t *n2 = a2;
11952
11953   if (n1->value < n2->value)
11954     return -1;
11955   if (n1->value > n2->value)
11956     return 1;
11957   return 0;
11958 }
11959
11960
11961 static int
11962 dump_msg_api_table (vat_main_t * vam)
11963 {
11964   api_main_t *am = vlibapi_get_main ();
11965   name_sort_t *nses = 0, *ns;
11966   hash_pair_t *hp;
11967   int i;
11968
11969   /* *INDENT-OFF* */
11970   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
11971   ({
11972     vec_add2 (nses, ns, 1);
11973     ns->name = (u8 *)(hp->key);
11974     ns->value = (u32) hp->value[0];
11975   }));
11976   /* *INDENT-ON* */
11977
11978   vec_sort_with_function (nses, value_sort_cmp);
11979
11980   for (i = 0; i < vec_len (nses); i++)
11981     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
11982   vec_free (nses);
11983   return 0;
11984 }
11985
11986 static int
11987 get_msg_id (vat_main_t * vam)
11988 {
11989   u8 *name_and_crc;
11990   u32 message_index;
11991
11992   if (unformat (vam->input, "%s", &name_and_crc))
11993     {
11994       message_index = vl_msg_api_get_msg_index (name_and_crc);
11995       if (message_index == ~0)
11996         {
11997           print (vam->ofp, " '%s' not found", name_and_crc);
11998           return 0;
11999         }
12000       print (vam->ofp, " '%s' has message index %d",
12001              name_and_crc, message_index);
12002       return 0;
12003     }
12004   errmsg ("name_and_crc required...");
12005   return 0;
12006 }
12007
12008 static int
12009 search_node_table (vat_main_t * vam)
12010 {
12011   unformat_input_t *line_input = vam->input;
12012   u8 *node_to_find;
12013   int j;
12014   vlib_node_t *node, *next_node;
12015   uword *p;
12016
12017   if (vam->graph_node_index_by_name == 0)
12018     {
12019       print (vam->ofp, "Node table empty, issue get_node_graph...");
12020       return 0;
12021     }
12022
12023   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
12024     {
12025       if (unformat (line_input, "%s", &node_to_find))
12026         {
12027           vec_add1 (node_to_find, 0);
12028           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
12029           if (p == 0)
12030             {
12031               print (vam->ofp, "%s not found...", node_to_find);
12032               goto out;
12033             }
12034           node = vam->graph_nodes[0][p[0]];
12035           print (vam->ofp, "[%d] %s", p[0], node->name);
12036           for (j = 0; j < vec_len (node->next_nodes); j++)
12037             {
12038               if (node->next_nodes[j] != ~0)
12039                 {
12040                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
12041                   print (vam->ofp, "  [%d] %s", j, next_node->name);
12042                 }
12043             }
12044         }
12045
12046       else
12047         {
12048           clib_warning ("parse error '%U'", format_unformat_error,
12049                         line_input);
12050           return -99;
12051         }
12052
12053     out:
12054       vec_free (node_to_find);
12055
12056     }
12057
12058   return 0;
12059 }
12060
12061
12062 static int
12063 script (vat_main_t * vam)
12064 {
12065 #if (VPP_API_TEST_BUILTIN==0)
12066   u8 *s = 0;
12067   char *save_current_file;
12068   unformat_input_t save_input;
12069   jmp_buf save_jump_buf;
12070   u32 save_line_number;
12071
12072   FILE *new_fp, *save_ifp;
12073
12074   if (unformat (vam->input, "%s", &s))
12075     {
12076       new_fp = fopen ((char *) s, "r");
12077       if (new_fp == 0)
12078         {
12079           errmsg ("Couldn't open script file %s", s);
12080           vec_free (s);
12081           return -99;
12082         }
12083     }
12084   else
12085     {
12086       errmsg ("Missing script name");
12087       return -99;
12088     }
12089
12090   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
12091   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
12092   save_ifp = vam->ifp;
12093   save_line_number = vam->input_line_number;
12094   save_current_file = (char *) vam->current_file;
12095
12096   vam->input_line_number = 0;
12097   vam->ifp = new_fp;
12098   vam->current_file = s;
12099   do_one_file (vam);
12100
12101   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
12102   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
12103   vam->ifp = save_ifp;
12104   vam->input_line_number = save_line_number;
12105   vam->current_file = (u8 *) save_current_file;
12106   vec_free (s);
12107
12108   return 0;
12109 #else
12110   clib_warning ("use the exec command...");
12111   return -99;
12112 #endif
12113 }
12114
12115 static int
12116 echo (vat_main_t * vam)
12117 {
12118   print (vam->ofp, "%v", vam->input->buffer);
12119   return 0;
12120 }
12121
12122 /* List of API message constructors, CLI names map to api_xxx */
12123 #define foreach_vpe_api_msg                                             \
12124 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
12125 _(sw_interface_dump,"")                                                 \
12126 _(sw_interface_set_flags,                                               \
12127   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
12128 _(sw_interface_add_del_address,                                         \
12129   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
12130 _(sw_interface_set_rx_mode,                                             \
12131   "<intfc> | sw_if_index <id> [queue <id>] <polling | interrupt | adaptive>") \
12132 _(sw_interface_set_rx_placement,                                        \
12133   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
12134 _(sw_interface_rx_placement_dump,                                       \
12135   "[<intfc> | sw_if_index <id>]")                                         \
12136 _(sw_interface_set_table,                                               \
12137   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
12138 _(sw_interface_set_mpls_enable,                                         \
12139   "<intfc> | sw_if_index [disable | dis]")                              \
12140 _(sw_interface_set_vpath,                                               \
12141   "<intfc> | sw_if_index <id> enable | disable")                        \
12142 _(sw_interface_set_l2_xconnect,                                         \
12143   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
12144   "enable | disable")                                                   \
12145 _(sw_interface_set_l2_bridge,                                           \
12146   "{<intfc> | sw_if_index <id>} bd_id <bridge-domain-id>\n"             \
12147   "[shg <split-horizon-group>] [bvi]\n"                                 \
12148   "enable | disable")                                                   \
12149 _(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255")  \
12150 _(bridge_domain_add_del,                                                \
12151   "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") \
12152 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")                   \
12153 _(l2fib_add_del,                                                        \
12154   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
12155 _(l2fib_flush_bd, "bd_id <bridge-domain-id>")                           \
12156 _(l2fib_flush_int, "<intfc> | sw_if_index <id>")                        \
12157 _(l2_flags,                                                             \
12158   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
12159 _(bridge_flags,                                                         \
12160   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
12161 _(tap_create_v2,                                                        \
12162   "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]") \
12163 _(tap_delete_v2,                                                        \
12164   "<vpp-if-name> | sw_if_index <id>")                                   \
12165 _(sw_interface_tap_v2_dump, "")                                         \
12166 _(virtio_pci_create_v2,                                                    \
12167   "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]") \
12168 _(virtio_pci_delete,                                                    \
12169   "<vpp-if-name> | sw_if_index <id>")                                   \
12170 _(sw_interface_virtio_pci_dump, "")                                     \
12171 _(bond_create,                                                          \
12172   "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
12173   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
12174   "[id <if-id>]")                                                       \
12175 _(bond_create2,                                                         \
12176   "[hw-addr <mac-addr>] {mode round-robin | active-backup | "           \
12177   "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]} "        \
12178   "[id <if-id>] [gso]")                                                 \
12179 _(bond_delete,                                                          \
12180   "<vpp-if-name> | sw_if_index <id>")                                   \
12181 _(bond_add_member,                                                      \
12182   "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]")  \
12183 _(bond_detach_member,                                                   \
12184   "sw_if_index <n>")                                                    \
12185  _(sw_interface_set_bond_weight, "<intfc> | sw_if_index <nn> weight <value>") \
12186  _(sw_bond_interface_dump, "<intfc> | sw_if_index <nn>")                \
12187  _(sw_member_interface_dump,                                            \
12188   "<vpp-if-name> | sw_if_index <id>")                                   \
12189 _(ip_table_add_del,                                                     \
12190   "table <n> [ipv6] [add | del]\n")                                     \
12191 _(ip_route_add_del,                                                     \
12192   "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
12193   "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
12194   "[weight <n>] [drop] [local] [classify <n>]  [out-label <n>]\n"       \
12195   "[multipath] [count <n>] [del]")                                      \
12196 _(ip_mroute_add_del,                                                    \
12197   "<src> <grp>/<mask> [table-id <n>]\n"                                 \
12198   "[<intfc> | sw_if_index <id>] [local] [del]")                         \
12199 _(mpls_table_add_del,                                                   \
12200   "table <n> [add | del]\n")                                            \
12201 _(mpls_route_add_del,                                                   \
12202   "<label> <eos> via <addr | next-hop-table <n> | via-label <n> |\n"    \
12203   "lookup-ip4-table <n> | lookup-in-ip6-table <n> |\n"                  \
12204   "l2-input-on <intfc> | l2-input-on sw_if_index <id>>\n"               \
12205   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>] [weight <n>]\n"  \
12206   "[drop] [local] [classify <n>] [out-label <n>] [multipath]\n"         \
12207   "[count <n>] [del]")                                                  \
12208 _(mpls_ip_bind_unbind,                                                  \
12209   "<label> <addr/len>")                                                 \
12210 _(mpls_tunnel_add_del,                                                  \
12211   "[add | del <intfc | sw_if_index <id>>] via <addr | via-label <n>>\n" \
12212   "[<intfc> | sw_if_index <id> | next-hop-table <id>]\n"                \
12213   "[l2-only]  [out-label <n>]")                                         \
12214 _(sr_mpls_policy_add,                                                   \
12215   "bsid <id> [weight <n>] [spray] next <sid> [next <sid>]")             \
12216 _(sr_mpls_policy_del,                                                   \
12217   "bsid <id>")                                                          \
12218 _(sw_interface_set_unnumbered,                                          \
12219   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
12220 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
12221 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
12222   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
12223   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
12224   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
12225 _(ip_table_replace_begin, "table <n> [ipv6]")                           \
12226 _(ip_table_flush, "table <n> [ipv6]")                                   \
12227 _(ip_table_replace_end, "table <n> [ipv6]")                             \
12228 _(set_ip_flow_hash,                                                     \
12229   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
12230 _(sw_interface_ip6_enable_disable,                                      \
12231   "<intfc> | sw_if_index <id> enable | disable")                        \
12232 _(l2_patch_add_del,                                                     \
12233   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
12234   "enable | disable")                                                   \
12235 _(sr_localsid_add_del,                                                  \
12236   "(del) address <addr> next_hop <addr> behavior <beh>\n"               \
12237   "fib-table <num> (end.psp) sw_if_index <num>")                        \
12238 _(get_node_index, "node <node-name")                                    \
12239 _(add_node_next, "node <node-name> next <next-node-name>")              \
12240 _(l2_fib_clear_table, "")                                               \
12241 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
12242 _(l2_interface_vlan_tag_rewrite,                                        \
12243   "<intfc> | sw_if_index <nn> \n"                                       \
12244   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
12245   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
12246 _(create_vhost_user_if,                                                 \
12247         "socket <filename> [server] [renumber <dev_instance>] "         \
12248         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
12249         "[mac <mac_address>] [packed]")                                 \
12250 _(modify_vhost_user_if,                                                 \
12251         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
12252         "[server] [renumber <dev_instance>] [gso] [packed]")            \
12253 _(create_vhost_user_if_v2,                                              \
12254         "socket <filename> [server] [renumber <dev_instance>] "         \
12255         "[disable_mrg_rxbuf] [disable_indirect_desc] [gso] "            \
12256         "[mac <mac_address>] [packed] [event-idx]")                     \
12257 _(modify_vhost_user_if_v2,                                              \
12258         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
12259         "[server] [renumber <dev_instance>] [gso] [packed] [event-idx]")\
12260 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
12261 _(sw_interface_vhost_user_dump, "<intfc> | sw_if_index <nn>")           \
12262 _(show_version, "")                                                     \
12263 _(show_threads, "")                                                     \
12264 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
12265 _(interface_name_renumber,                                              \
12266   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
12267 _(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
12268 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
12269 _(ip_dump, "ipv4 | ipv6")                                               \
12270 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
12271 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
12272   "  spid_id <n> ")                                                     \
12273 _(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
12274   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
12275   "  integ_alg <alg> integ_key <hex>")                                  \
12276 _(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
12277   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
12278   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
12279   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
12280 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
12281 _(delete_loopback,"sw_if_index <nn>")                                   \
12282 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
12283 _(bd_ip_mac_flush, "bd_id <bridge-domain-id>")                          \
12284 _(bd_ip_mac_dump, "[bd_id] <bridge-domain-id>")                         \
12285 _(want_interface_events,  "enable|disable")                             \
12286 _(get_first_msg_id, "client <name>")                                    \
12287 _(get_node_graph, " ")                                                  \
12288 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
12289 _(ioam_enable, "[trace] [pow] [ppc <encap|decap>]")                     \
12290 _(ioam_disable, "")                                                     \
12291 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
12292 _(af_packet_delete, "name <host interface name>")                       \
12293 _(af_packet_dump, "")                                                   \
12294 _(policer_add_del, "name <policer name> <params> [del]")                \
12295 _(policer_dump, "[name <policer name>]")                                \
12296 _(mpls_tunnel_dump, "tunnel_index <tunnel-id>")                         \
12297 _(mpls_table_dump, "")                                                  \
12298 _(mpls_route_dump, "table-id <ID>")                                     \
12299 _(sw_interface_span_enable_disable, "[l2] [src <intfc> | src_sw_if_index <id>] [disable | [[dst <intfc> | dst_sw_if_index <id>] [both|rx|tx]]]") \
12300 _(sw_interface_span_dump, "[l2]")                                           \
12301 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
12302 _(ip_source_and_port_range_check_add_del,                               \
12303   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
12304 _(ip_source_and_port_range_check_interface_add_del,                     \
12305   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
12306   "[udp-in-vrf <id>] [udp-out-vrf <id>]")                               \
12307 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
12308 _(l2_interface_pbb_tag_rewrite,                                         \
12309   "<intfc> | sw_if_index <nn> \n"                                       \
12310   "[disable | push | pop | translate_pbb_stag <outer_tag>] \n"          \
12311   "dmac <mac> smac <mac> sid <nn> [vlanid <nn>]")                       \
12312 _(set_punt, "protocol <l4-protocol> [ip <ver>] [port <l4-port>] [del]")     \
12313 _(ip_table_dump, "")                                                    \
12314 _(ip_route_dump, "table-id [ip4|ip6]")                                  \
12315 _(ip_mtable_dump, "")                                                   \
12316 _(ip_mroute_dump, "table-id [ip4|ip6]")                                 \
12317 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
12318 "[disable]")                                                            \
12319 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
12320   "mac <mac-address> [del]")                                            \
12321 _(l2_xconnect_dump, "")                                                 \
12322 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
12323 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
12324 _(p2p_ethernet_add, "<intfc> | sw_if_index <nn> remote_mac <mac-address> sub_id <id>") \
12325 _(p2p_ethernet_del, "<intfc> | sw_if_index <nn> remote_mac <mac-address>") \
12326 _(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]")   \
12327 _(sock_init_shm, "size <nnn>")                                          \
12328 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
12329 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
12330   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
12331 _(session_rules_dump, "")                                               \
12332 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")      \
12333 _(qos_record_enable_disable, "<record-source> <intfc> | sw_if_index <id> [disable]")
12334
12335 /* List of command functions, CLI names map directly to functions */
12336 #define foreach_cli_function                                    \
12337 _(comment, "usage: comment <ignore-rest-of-line>")              \
12338 _(dump_interface_table, "usage: dump_interface_table")          \
12339 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
12340 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
12341 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
12342 _(dump_macro_table, "usage: dump_macro_table ")                 \
12343 _(dump_node_table, "usage: dump_node_table")                    \
12344 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
12345 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
12346 _(elog_disable, "usage: elog_disable")                          \
12347 _(elog_enable, "usage: elog_enable")                            \
12348 _(elog_save, "usage: elog_save <filename>")                     \
12349 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
12350 _(echo, "usage: echo <message>")                                \
12351 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
12352 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
12353 _(help, "usage: help")                                          \
12354 _(q, "usage: quit")                                             \
12355 _(quit, "usage: quit")                                          \
12356 _(search_node_table, "usage: search_node_table <name>...")      \
12357 _(set, "usage: set <variable-name> <value>")                    \
12358 _(script, "usage: script <file-name>")                          \
12359 _(statseg, "usage: statseg")                                    \
12360 _(unset, "usage: unset <variable-name>")
12361
12362 #define _(N,n)                                  \
12363     static void vl_api_##n##_t_handler_uni      \
12364     (vl_api_##n##_t * mp)                       \
12365     {                                           \
12366         vat_main_t * vam = &vat_main;           \
12367         if (vam->json_output) {                 \
12368             vl_api_##n##_t_handler_json(mp);    \
12369         } else {                                \
12370             vl_api_##n##_t_handler(mp);         \
12371         }                                       \
12372     }
12373 foreach_vpe_api_reply_msg;
12374 #if VPP_API_TEST_BUILTIN == 0
12375 foreach_standalone_reply_msg;
12376 #endif
12377 #undef _
12378
12379 void
12380 vat_api_hookup (vat_main_t * vam)
12381 {
12382 #define _(N,n)                                                  \
12383     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
12384                            vl_api_##n##_t_handler_uni,          \
12385                            vl_noop_handler,                     \
12386                            vl_api_##n##_t_endian,               \
12387                            vl_api_##n##_t_print,                \
12388                            sizeof(vl_api_##n##_t), 1);
12389   foreach_vpe_api_reply_msg;
12390 #if VPP_API_TEST_BUILTIN == 0
12391   foreach_standalone_reply_msg;
12392 #endif
12393 #undef _
12394
12395 #if (VPP_API_TEST_BUILTIN==0)
12396   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
12397
12398   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
12399
12400   vam->function_by_name = hash_create_string (0, sizeof (uword));
12401
12402   vam->help_by_name = hash_create_string (0, sizeof (uword));
12403 #endif
12404
12405   /* API messages we can send */
12406 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
12407   foreach_vpe_api_msg;
12408 #undef _
12409
12410   /* Help strings */
12411 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
12412   foreach_vpe_api_msg;
12413 #undef _
12414
12415   /* CLI functions */
12416 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
12417   foreach_cli_function;
12418 #undef _
12419
12420   /* Help strings */
12421 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
12422   foreach_cli_function;
12423 #undef _
12424 }
12425
12426 #if VPP_API_TEST_BUILTIN
12427 static clib_error_t *
12428 vat_api_hookup_shim (vlib_main_t * vm)
12429 {
12430   vat_api_hookup (&vat_main);
12431   return 0;
12432 }
12433
12434 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
12435 #endif
12436
12437 /*
12438  * fd.io coding-style-patch-verification: ON
12439  *
12440  * Local Variables:
12441  * eval: (c-set-style "gnu")
12442  * End:
12443  */