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