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