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