LISP multihoming API changes and cleanup
[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/ip/ip_source_and_port_range_check.h>
49 #include <vnet/policer/xlate.h>
50 #include <vnet/policer/policer.h>
51 #include <vnet/policer/police.h>
52
53 #include "vat/json_format.h"
54
55 #include <sys/stat.h>
56
57 #define vl_typedefs             /* define message structures */
58 #include <vpp-api/vpe_all_api_h.h>
59 #undef vl_typedefs
60
61 /* declare message handlers for each api */
62
63 #define vl_endianfun             /* define message structures */
64 #include <vpp-api/vpe_all_api_h.h>
65 #undef vl_endianfun
66
67 /* instantiate all the print functions we know about */
68 #define vl_print(handle, ...)
69 #define vl_printfun
70 #include <vpp-api/vpe_all_api_h.h>
71 #undef vl_printfun
72
73 uword unformat_sw_if_index (unformat_input_t * input, va_list * args)
74 {
75   vat_main_t * vam = va_arg (*args, vat_main_t *);
76   u32 * result = va_arg (*args, u32 *);
77   u8 * if_name;
78   uword * p;
79
80   if (!unformat (input, "%s", &if_name))
81       return 0;
82
83   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
84   if (p == 0)
85       return 0;
86   *result = p[0];
87   return 1;
88 }
89
90 /* Parse an IP4 address %d.%d.%d.%d. */
91 uword unformat_ip4_address (unformat_input_t * input, va_list * args)
92 {
93   u8 * result = va_arg (*args, u8 *);
94   unsigned a[4];
95
96   if (! unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
97     return 0;
98
99   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
100     return 0;
101
102   result[0] = a[0];
103   result[1] = a[1];
104   result[2] = a[2];
105   result[3] = a[3];
106
107   return 1;
108 }
109
110
111 uword
112 unformat_ethernet_address (unformat_input_t * input, va_list * args)
113 {
114   u8 * result = va_arg (*args, u8 *);
115   u32 i, a[6];
116
117   if (! unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
118                   &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
119     return 0;
120
121   /* Check range. */
122   for (i = 0; i < 6; i++)
123     if (a[i] >= (1 << 8))
124       return 0;
125
126   for (i = 0; i < 6; i++)
127     result[i] = a[i];
128
129   return 1;
130 }
131
132 /* Returns ethernet type as an int in host byte order. */
133 uword
134 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
135                                         va_list * args)
136 {
137   u16 * result = va_arg (*args, u16 *);
138   int type;
139
140   /* Numeric type. */
141   if (unformat (input, "0x%x", &type)
142       || unformat (input, "%d", &type))
143     {
144       if (type >= (1 << 16))
145         return 0;
146       *result = type;
147       return 1;
148     }
149   return 0;
150 }
151
152 /* Parse an IP6 address. */
153 uword unformat_ip6_address (unformat_input_t * input, va_list * args)
154 {
155   ip6_address_t * result = va_arg (*args, ip6_address_t *);
156   u16 hex_quads[8];
157   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
158   uword c, n_colon, double_colon_index;
159
160   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
161   double_colon_index = ARRAY_LEN (hex_quads);
162   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
163     {
164       hex_digit = 16;
165       if (c >= '0' && c <= '9')
166         hex_digit = c - '0';
167       else if (c >= 'a' && c <= 'f')
168         hex_digit = c + 10 - 'a';
169       else if (c >= 'A' && c <= 'F')
170         hex_digit = c + 10 - 'A';
171       else if (c == ':' && n_colon < 2)
172         n_colon++;
173       else
174         {
175           unformat_put_input (input);
176           break;
177         }
178
179       /* Too many hex quads. */
180       if (n_hex_quads >= ARRAY_LEN (hex_quads))
181         return 0;
182
183       if (hex_digit < 16)
184         {
185           hex_quad = (hex_quad << 4) | hex_digit;
186
187           /* Hex quad must fit in 16 bits. */
188           if (n_hex_digits >= 4)
189             return 0;
190
191           n_colon = 0;
192           n_hex_digits++;
193         }
194
195       /* Save position of :: */
196       if (n_colon == 2)
197         {
198           /* More than one :: ? */
199           if (double_colon_index < ARRAY_LEN (hex_quads))
200             return 0;
201           double_colon_index = n_hex_quads;
202         }
203
204       if (n_colon > 0 && n_hex_digits > 0)
205         {
206           hex_quads[n_hex_quads++] = hex_quad;
207           hex_quad = 0;
208           n_hex_digits = 0;
209         }
210     }
211
212   if (n_hex_digits > 0)
213     hex_quads[n_hex_quads++] = hex_quad;
214
215   {
216     word i;
217
218     /* Expand :: to appropriate number of zero hex quads. */
219     if (double_colon_index < ARRAY_LEN (hex_quads))
220       {
221         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
222
223         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
224           hex_quads[n_zero + i] = hex_quads[i];
225
226         for (i = 0; i < n_zero; i++)
227           hex_quads[double_colon_index + i] = 0;
228
229         n_hex_quads = ARRAY_LEN (hex_quads);
230       }
231
232     /* Too few hex quads given. */
233     if (n_hex_quads < ARRAY_LEN (hex_quads))
234       return 0;
235
236     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
237       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
238
239     return 1;
240   }
241 }
242
243 uword
244 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
245 {
246 #if DPDK > 0
247   u32 * r = va_arg (*args, u32 *);
248
249   if (0) ;
250 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
251   foreach_ipsec_policy_action
252 #undef _
253   else
254     return 0;
255   return 1;
256 #else
257   return 0;
258 #endif
259 }
260
261 uword
262 unformat_ipsec_crypto_alg (unformat_input_t * input, va_list * args)
263 {
264 #if DPDK > 0
265   u32 * r = va_arg (*args, u32 *);
266
267   if (0) ;
268 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_CRYPTO_ALG_##f;
269   foreach_ipsec_crypto_alg
270 #undef _
271   else
272     return 0;
273   return 1;
274 #else
275   return 0;
276 #endif
277 }
278
279 u8 *
280 format_ipsec_crypto_alg (u8 * s, va_list * args)
281 {
282 #if DPDK > 0
283   u32 i = va_arg (*args, u32);
284   u8 * t = 0;
285
286   switch (i)
287     {
288 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
289   foreach_ipsec_crypto_alg
290 #undef _
291       default:
292         return format (s, "unknown");
293     }
294   return format (s, "%s", t);
295 #else
296   return format (s, "Unimplemented");
297 #endif
298 }
299
300 uword
301 unformat_ipsec_integ_alg (unformat_input_t * input, va_list * args)
302 {
303 #if DPDK > 0
304   u32 * r = va_arg (*args, u32 *);
305
306   if (0) ;
307 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_INTEG_ALG_##f;
308   foreach_ipsec_integ_alg
309 #undef _
310   else
311     return 0;
312   return 1;
313 #else
314   return 0;
315 #endif
316 }
317
318 u8 *
319 format_ipsec_integ_alg (u8 * s, va_list * args)
320 {
321 #if DPDK > 0
322   u32 i = va_arg (*args, u32);
323   u8 * t = 0;
324
325   switch (i)
326     {
327 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
328   foreach_ipsec_integ_alg
329 #undef _
330       default:
331         return format (s, "unknown");
332     }
333   return format (s, "%s", t);
334 #else
335   return format (s, "Unsupported");
336 #endif
337 }
338
339 uword
340 unformat_ikev2_auth_method (unformat_input_t * input, va_list * args)
341 {
342 #if DPDK > 0
343   u32 * r = va_arg (*args, u32 *);
344
345   if (0) ;
346 #define _(v,f,s) else if (unformat (input, s)) *r = IKEV2_AUTH_METHOD_##f;
347   foreach_ikev2_auth_method
348 #undef _
349   else
350     return 0;
351   return 1;
352 #else
353   return 0;
354 #endif
355 }
356
357 uword
358 unformat_ikev2_id_type (unformat_input_t * input, va_list * args)
359 {
360 #if DPDK > 0
361   u32 * r = va_arg (*args, u32 *);
362
363   if (0) ;
364 #define _(v,f,s) else if (unformat (input, s)) *r = IKEV2_ID_TYPE_##f;
365   foreach_ikev2_id_type
366 #undef _
367   else
368     return 0;
369   return 1;
370 #else
371   return 0;
372 #endif
373 }
374
375 uword
376 unformat_policer_rate_type (unformat_input_t * input, va_list * args)
377 {
378   u8 * r = va_arg (*args, u8 *);
379
380   if (unformat (input, "kbps"))
381     *r = SSE2_QOS_RATE_KBPS;
382   else if (unformat(input, "pps"))
383     *r = SSE2_QOS_RATE_PPS;
384   else
385     return 0;
386   return 1;
387 }
388
389 uword
390 unformat_policer_round_type (unformat_input_t * input, va_list * args)
391 {
392   u8 * r = va_arg (*args, u8 *);
393
394   if (unformat(input, "closest"))
395     *r = SSE2_QOS_ROUND_TO_CLOSEST;
396   else if (unformat (input, "up"))
397     *r = SSE2_QOS_ROUND_TO_UP;
398   else if (unformat (input, "down"))
399     *r = SSE2_QOS_ROUND_TO_DOWN;
400   else
401     return 0;
402   return 1;
403 }
404
405 uword
406 unformat_policer_type (unformat_input_t * input, va_list * args)
407 {
408   u8 * r = va_arg (*args, u8 *);
409
410   if (unformat (input, "1r2c"))
411     *r = SSE2_QOS_POLICER_TYPE_1R2C;
412   else if (unformat (input, "1r3c"))
413     *r = SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697;
414   else if (unformat (input, "2r3c-2698"))
415     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698;
416   else if (unformat (input, "2r3c-4115"))
417     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115;
418   else if (unformat (input, "2r3c-mef5cf1"))
419     *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
420   else
421     return 0;
422   return 1;
423 }
424
425 uword
426 unformat_dscp (unformat_input_t * input, va_list * va)
427 {
428   u8 * r = va_arg (*va, u8 *);
429
430   if (0) ;
431 #define _(v,f,str) else if (unformat (input, str)) *r = VNET_DSCP_##f;
432       foreach_vnet_dscp
433 #undef _
434   else
435     return 0;
436   return 1;
437 }
438
439 uword
440 unformat_policer_action_type (unformat_input_t * input, va_list * va)
441 {
442   sse2_qos_pol_action_params_st * a
443     = va_arg (*va, sse2_qos_pol_action_params_st *);
444
445   if (unformat (input, "drop"))
446     a->action_type = SSE2_QOS_ACTION_DROP;
447   else if (unformat (input, "transmit"))
448     a->action_type = SSE2_QOS_ACTION_TRANSMIT;
449   else if (unformat (input, "mark-and-transmit %U", unformat_dscp, &a->dscp))
450     a->action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT;
451   else
452     return 0;
453   return 1;
454 }
455
456 uword
457 unformat_classify_table_type (unformat_input_t * input, va_list * va)
458 {
459   u32 * r = va_arg (*va, u32 *);
460   u32 tid;
461
462   if (unformat (input, "ip4"))
463     tid = POLICER_CLASSIFY_TABLE_IP4;
464   else if (unformat (input, "ip6"))
465     tid = POLICER_CLASSIFY_TABLE_IP6;
466   else if (unformat (input, "l2"))
467     tid = POLICER_CLASSIFY_TABLE_L2;
468   else
469     return 0;
470
471   *r = tid;
472   return 1;
473 }
474
475 u8 * format_ip4_address (u8 * s, va_list * args)
476 {
477   u8 * a = va_arg (*args, u8 *);
478   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
479 }
480
481 u8 * format_ip6_address (u8 * s, va_list * args)
482 {
483     ip6_address_t * a = va_arg (*args, ip6_address_t *);
484     u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
485
486     i_max_n_zero = ARRAY_LEN (a->as_u16);
487     max_n_zeros = 0;
488     i_first_zero = i_max_n_zero;
489     n_zeros = 0;
490     for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
491       {
492         u32 is_zero = a->as_u16[i] == 0;
493         if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
494           {
495             i_first_zero = i;
496             n_zeros = 0;
497           }
498         n_zeros += is_zero;
499         if ((! is_zero && n_zeros > max_n_zeros)
500             || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
501           {
502             i_max_n_zero = i_first_zero;
503             max_n_zeros = n_zeros;
504             i_first_zero = ARRAY_LEN (a->as_u16);
505             n_zeros = 0;
506           }
507       }
508
509     last_double_colon = 0;
510     for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
511       {
512         if (i == i_max_n_zero && max_n_zeros > 1)
513           {
514             s = format (s, "::");
515             i += max_n_zeros - 1;
516             last_double_colon = 1;
517           }
518         else
519           {
520             s = format (s, "%s%x",
521                         (last_double_colon || i == 0) ? "" : ":",
522                         clib_net_to_host_u16 (a->as_u16[i]));
523             last_double_colon = 0;
524           }
525       }
526
527     return s;
528 }
529
530 /* Format an IP46 address. */
531 u8 * format_ip46_address (u8 * s, va_list * args)
532 {
533   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
534   ip46_type_t type = va_arg (*args, ip46_type_t);
535   int is_ip4 = 1;
536
537   switch (type)
538     {
539       case IP46_TYPE_ANY:
540        is_ip4 = ip46_address_is_ip4(ip46);
541        break;
542       case IP46_TYPE_IP4:
543        is_ip4 = 1;
544        break;
545       case IP46_TYPE_IP6:
546        is_ip4 = 0;
547        break;
548     }
549
550   return is_ip4 ?
551       format(s, "%U", format_ip4_address, &ip46->ip4):
552       format(s, "%U", format_ip6_address, &ip46->ip6);
553 }
554
555 u8 * format_ethernet_address (u8 * s, va_list * args)
556 {
557   u8 * a = va_arg (*args, u8 *);
558
559   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
560                  a[0], a[1], a[2], a[3], a[4], a[5]);
561 }
562
563 void increment_v4_address (ip4_address_t * a)
564 {
565     u32 v;
566
567     v = ntohl(a->as_u32) + 1;
568     a->as_u32 = ntohl(v);
569 }
570
571 void increment_v6_address (ip6_address_t * a)
572 {
573     u64 v0, v1;
574
575     v0 = clib_net_to_host_u64 (a->as_u64[0]);
576     v1 = clib_net_to_host_u64 (a->as_u64[1]);
577
578     v1 += 1;
579     if (v1 == 0)
580         v0 += 1;
581     a->as_u64[0] = clib_net_to_host_u64 (v0);
582     a->as_u64[1] = clib_net_to_host_u64 (v1);
583 }
584
585 void increment_mac_address (u64 *mac)
586 {
587     u64 tmp = *mac;
588
589     tmp = clib_net_to_host_u64(tmp);
590     tmp += 1<<16; /* skip unused (least significant) octets */
591     tmp = clib_host_to_net_u64 (tmp);
592     *mac = tmp;
593 }
594
595 static void vl_api_create_loopback_reply_t_handler
596 (vl_api_create_loopback_reply_t * mp)
597 {
598     vat_main_t * vam = &vat_main;
599     i32 retval = ntohl(mp->retval);
600
601     vam->retval = retval;
602     vam->regenerate_interface_table = 1;
603     vam->sw_if_index = ntohl (mp->sw_if_index);
604     vam->result_ready = 1;
605 }
606
607 static void vl_api_create_loopback_reply_t_handler_json
608 (vl_api_create_loopback_reply_t * mp)
609 {
610     vat_main_t * vam = &vat_main;
611     vat_json_node_t node;
612
613     vat_json_init_object(&node);
614     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
615     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
616
617     vat_json_print(vam->ofp, &node);
618     vat_json_free(&node);
619     vam->retval = ntohl(mp->retval);
620     vam->result_ready = 1;
621 }
622
623 static void vl_api_af_packet_create_reply_t_handler
624 (vl_api_af_packet_create_reply_t * mp)
625 {
626     vat_main_t * vam = &vat_main;
627     i32 retval = ntohl(mp->retval);
628
629     vam->retval = retval;
630     vam->regenerate_interface_table = 1;
631     vam->sw_if_index = ntohl (mp->sw_if_index);
632     vam->result_ready = 1;
633 }
634
635 static void vl_api_af_packet_create_reply_t_handler_json
636 (vl_api_af_packet_create_reply_t * mp)
637 {
638     vat_main_t * vam = &vat_main;
639     vat_json_node_t node;
640
641     vat_json_init_object(&node);
642     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
643     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
644
645     vat_json_print(vam->ofp, &node);
646     vat_json_free(&node);
647
648     vam->retval = ntohl(mp->retval);
649     vam->result_ready = 1;
650 }
651
652 static void vl_api_create_vlan_subif_reply_t_handler
653 (vl_api_create_vlan_subif_reply_t * mp)
654 {
655     vat_main_t * vam = &vat_main;
656     i32 retval = ntohl(mp->retval);
657
658     vam->retval = retval;
659     vam->regenerate_interface_table = 1;
660     vam->sw_if_index = ntohl (mp->sw_if_index);
661     vam->result_ready = 1;
662 }
663
664 static void vl_api_create_vlan_subif_reply_t_handler_json
665 (vl_api_create_vlan_subif_reply_t * mp)
666 {
667     vat_main_t * vam = &vat_main;
668     vat_json_node_t node;
669
670     vat_json_init_object(&node);
671     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
672     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
673
674     vat_json_print(vam->ofp, &node);
675     vat_json_free(&node);
676
677     vam->retval = ntohl(mp->retval);
678     vam->result_ready = 1;
679 }
680
681 static void vl_api_create_subif_reply_t_handler
682 (vl_api_create_subif_reply_t * mp)
683 {
684     vat_main_t * vam = &vat_main;
685     i32 retval = ntohl(mp->retval);
686
687     vam->retval = retval;
688     vam->regenerate_interface_table = 1;
689     vam->sw_if_index = ntohl (mp->sw_if_index);
690     vam->result_ready = 1;
691 }
692
693 static void vl_api_create_subif_reply_t_handler_json
694 (vl_api_create_subif_reply_t * mp)
695 {
696     vat_main_t * vam = &vat_main;
697     vat_json_node_t node;
698
699     vat_json_init_object(&node);
700     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
701     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
702
703     vat_json_print(vam->ofp, &node);
704     vat_json_free(&node);
705
706     vam->retval = ntohl(mp->retval);
707     vam->result_ready = 1;
708 }
709
710 static void vl_api_interface_name_renumber_reply_t_handler
711 (vl_api_interface_name_renumber_reply_t * mp)
712 {
713     vat_main_t * vam = &vat_main;
714     i32 retval = ntohl(mp->retval);
715
716     vam->retval = retval;
717     vam->regenerate_interface_table = 1;
718     vam->result_ready = 1;
719 }
720
721 static void vl_api_interface_name_renumber_reply_t_handler_json
722 (vl_api_interface_name_renumber_reply_t * mp)
723 {
724     vat_main_t * vam = &vat_main;
725     vat_json_node_t node;
726
727     vat_json_init_object(&node);
728     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
729
730     vat_json_print(vam->ofp, &node);
731     vat_json_free(&node);
732
733     vam->retval = ntohl(mp->retval);
734     vam->result_ready = 1;
735 }
736
737 /*
738  * Special-case: build the interface table, maintain
739  * the next loopback sw_if_index vbl.
740  */
741 static void vl_api_sw_interface_details_t_handler
742 (vl_api_sw_interface_details_t * mp)
743 {
744     vat_main_t * vam = &vat_main;
745     u8 * s = format (0, "%s%c", mp->interface_name, 0);
746
747     hash_set_mem (vam->sw_if_index_by_interface_name, s,
748                   ntohl(mp->sw_if_index));
749
750     /* In sub interface case, fill the sub interface table entry */
751     if (mp->sw_if_index != mp->sup_sw_if_index) {
752         sw_interface_subif_t * sub = NULL;
753
754         vec_add2(vam->sw_if_subif_table, sub, 1);
755
756         vec_validate(sub->interface_name, strlen((char *)s) + 1);
757         strncpy((char *)sub->interface_name, (char *)s,
758                 vec_len(sub->interface_name));
759         sub->sw_if_index = ntohl(mp->sw_if_index);
760         sub->sub_id = ntohl(mp->sub_id);
761
762         sub->sub_dot1ad = mp->sub_dot1ad;
763         sub->sub_number_of_tags = mp->sub_number_of_tags;
764         sub->sub_outer_vlan_id = ntohs(mp->sub_outer_vlan_id);
765         sub->sub_inner_vlan_id = ntohs(mp->sub_inner_vlan_id);
766         sub->sub_exact_match = mp->sub_exact_match;
767         sub->sub_default = mp->sub_default;
768         sub->sub_outer_vlan_id_any = mp->sub_outer_vlan_id_any;
769         sub->sub_inner_vlan_id_any = mp->sub_inner_vlan_id_any;
770
771         /* vlan tag rewrite */
772         sub->vtr_op = ntohl(mp->vtr_op);
773         sub->vtr_push_dot1q = ntohl(mp->vtr_push_dot1q);
774         sub->vtr_tag1 = ntohl(mp->vtr_tag1);
775         sub->vtr_tag2 = ntohl(mp->vtr_tag2);
776     }
777 }
778
779 static void vl_api_sw_interface_details_t_handler_json
780 (vl_api_sw_interface_details_t * mp)
781 {
782     vat_main_t * vam = &vat_main;
783     vat_json_node_t *node = NULL;
784
785     if (VAT_JSON_ARRAY != vam->json_tree.type) {
786         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
787         vat_json_init_array(&vam->json_tree);
788     }
789     node = vat_json_array_add(&vam->json_tree);
790
791     vat_json_init_object(node);
792     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
793     vat_json_object_add_uint(node, "sup_sw_if_index", ntohl(mp->sup_sw_if_index));
794     vat_json_object_add_uint(node, "l2_address_length", ntohl(mp->l2_address_length));
795     vat_json_object_add_bytes(node, "l2_address", mp->l2_address, sizeof(mp->l2_address));
796     vat_json_object_add_string_copy(node, "interface_name", mp->interface_name);
797     vat_json_object_add_uint(node, "admin_up_down", mp->admin_up_down);
798     vat_json_object_add_uint(node, "link_up_down", mp->link_up_down);
799     vat_json_object_add_uint(node, "link_duplex", mp->link_duplex);
800     vat_json_object_add_uint(node, "link_speed", mp->link_speed);
801     vat_json_object_add_uint(node, "mtu", ntohs(mp->link_mtu));
802     vat_json_object_add_uint(node, "sub_id", ntohl(mp->sub_id));
803     vat_json_object_add_uint(node, "sub_dot1ad", mp->sub_dot1ad);
804     vat_json_object_add_uint(node, "sub_number_of_tags", mp->sub_number_of_tags);
805     vat_json_object_add_uint(node, "sub_outer_vlan_id", ntohs(mp->sub_outer_vlan_id));
806     vat_json_object_add_uint(node, "sub_inner_vlan_id", ntohs(mp->sub_inner_vlan_id));
807     vat_json_object_add_uint(node, "sub_exact_match", mp->sub_exact_match);
808     vat_json_object_add_uint(node, "sub_default", mp->sub_default);
809     vat_json_object_add_uint(node, "sub_outer_vlan_id_any", mp->sub_outer_vlan_id_any);
810     vat_json_object_add_uint(node, "sub_inner_vlan_id_any", mp->sub_inner_vlan_id_any);
811     vat_json_object_add_uint(node, "vtr_op", ntohl(mp->vtr_op));
812     vat_json_object_add_uint(node, "vtr_push_dot1q", ntohl(mp->vtr_push_dot1q));
813     vat_json_object_add_uint(node, "vtr_tag1", ntohl(mp->vtr_tag1));
814     vat_json_object_add_uint(node, "vtr_tag2", ntohl(mp->vtr_tag2));
815 }
816
817 static void vl_api_sw_interface_set_flags_t_handler
818 (vl_api_sw_interface_set_flags_t * mp)
819 {
820     vat_main_t * vam = &vat_main;
821     if (vam->interface_event_display)
822         errmsg ("interface flags: sw_if_index %d %s %s\n",
823                 ntohl(mp->sw_if_index),
824                 mp->admin_up_down ? "admin-up" : "admin-down",
825                 mp->link_up_down  ? "link-up"  : "link-down");
826 }
827
828 static void vl_api_sw_interface_set_flags_t_handler_json
829 (vl_api_sw_interface_set_flags_t * mp)
830 {
831     /* JSON output not supported */
832 }
833
834 static void vl_api_cli_reply_t_handler
835 (vl_api_cli_reply_t * mp)
836 {
837     vat_main_t * vam = &vat_main;
838     i32 retval = ntohl(mp->retval);
839
840     vam->retval = retval;
841     vam->shmem_result = (u8 *) mp->reply_in_shmem;
842     vam->result_ready = 1;
843 }
844
845 static void vl_api_cli_reply_t_handler_json
846 (vl_api_cli_reply_t * mp)
847 {
848     vat_main_t * vam = &vat_main;
849     vat_json_node_t node;
850     api_main_t * am = &api_main;
851     void * oldheap;
852     u8 * reply;
853
854     vat_json_init_object(&node);
855     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
856     vat_json_object_add_uint(&node, "reply_in_shmem",
857                              ntohl(mp->reply_in_shmem));
858     /* Toss the shared-memory original... */
859     pthread_mutex_lock (&am->vlib_rp->mutex);
860     oldheap = svm_push_data_heap (am->vlib_rp);
861
862     reply = (u8 *)(mp->reply_in_shmem);
863     vec_free (reply);
864
865     svm_pop_heap (oldheap);
866     pthread_mutex_unlock (&am->vlib_rp->mutex);
867
868     vat_json_print(vam->ofp, &node);
869     vat_json_free(&node);
870
871     vam->retval = ntohl(mp->retval);
872     vam->result_ready = 1;
873 }
874
875 static void vl_api_classify_add_del_table_reply_t_handler
876 (vl_api_classify_add_del_table_reply_t * mp)
877 {
878     vat_main_t * vam = &vat_main;
879     i32 retval = ntohl(mp->retval);
880     if (vam->async_mode) {
881         vam->async_errors += (retval < 0);
882     } else {
883         vam->retval = retval;
884         if (retval == 0 &&
885             ((mp->new_table_index != 0xFFFFFFFF) ||
886              (mp->skip_n_vectors != 0xFFFFFFFF) ||
887              (mp->match_n_vectors != 0xFFFFFFFF)))
888             /*
889              * Note: this is just barely thread-safe, depends on
890              * the main thread spinning waiting for an answer...
891              */
892             errmsg ("new index %d, skip_n_vectors %d, match_n_vectors %d\n",
893                     ntohl(mp->new_table_index),
894                     ntohl(mp->skip_n_vectors), ntohl(mp->match_n_vectors));
895         vam->result_ready = 1;
896     }
897 }
898
899 static void vl_api_classify_add_del_table_reply_t_handler_json
900 (vl_api_classify_add_del_table_reply_t * mp)
901 {
902     vat_main_t * vam = &vat_main;
903     vat_json_node_t node;
904
905     vat_json_init_object(&node);
906     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
907     vat_json_object_add_uint(&node, "new_table_index", ntohl(mp->new_table_index));
908     vat_json_object_add_uint(&node, "skip_n_vectors", ntohl(mp->skip_n_vectors));
909     vat_json_object_add_uint(&node, "match_n_vectors", ntohl(mp->match_n_vectors));
910
911     vat_json_print(vam->ofp, &node);
912     vat_json_free(&node);
913
914     vam->retval = ntohl(mp->retval);
915     vam->result_ready = 1;
916 }
917
918 static void vl_api_get_node_index_reply_t_handler
919 (vl_api_get_node_index_reply_t * mp)
920 {
921     vat_main_t * vam = &vat_main;
922     i32 retval = ntohl(mp->retval);
923     if (vam->async_mode) {
924         vam->async_errors += (retval < 0);
925     } else {
926         vam->retval = retval;
927         if (retval == 0)
928             errmsg ("node index %d\n", ntohl(mp->node_index));
929         vam->result_ready = 1;
930     }
931 }
932
933 static void vl_api_get_node_index_reply_t_handler_json
934 (vl_api_get_node_index_reply_t * mp)
935 {
936     vat_main_t * vam = &vat_main;
937     vat_json_node_t node;
938
939     vat_json_init_object(&node);
940     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
941     vat_json_object_add_uint(&node, "node_index", ntohl(mp->node_index));
942
943     vat_json_print(vam->ofp, &node);
944     vat_json_free(&node);
945
946     vam->retval = ntohl(mp->retval);
947     vam->result_ready = 1;
948 }
949
950 static void vl_api_get_next_index_reply_t_handler
951 (vl_api_get_next_index_reply_t * mp)
952 {
953     vat_main_t * vam = &vat_main;
954     i32 retval = ntohl(mp->retval);
955     if (vam->async_mode) {
956         vam->async_errors += (retval < 0);
957     } else {
958         vam->retval = retval;
959         if (retval == 0)
960             errmsg ("next node index %d\n", ntohl(mp->next_index));
961         vam->result_ready = 1;
962     }
963 }
964
965 static void vl_api_get_next_index_reply_t_handler_json
966 (vl_api_get_next_index_reply_t * mp)
967 {
968     vat_main_t * vam = &vat_main;
969     vat_json_node_t node;
970
971     vat_json_init_object(&node);
972     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
973     vat_json_object_add_uint(&node, "next_index", ntohl(mp->next_index));
974
975     vat_json_print(vam->ofp, &node);
976     vat_json_free(&node);
977
978     vam->retval = ntohl(mp->retval);
979     vam->result_ready = 1;
980 }
981
982 static void vl_api_add_node_next_reply_t_handler
983 (vl_api_add_node_next_reply_t * mp)
984 {
985     vat_main_t * vam = &vat_main;
986     i32 retval = ntohl(mp->retval);
987     if (vam->async_mode) {
988         vam->async_errors += (retval < 0);
989     } else {
990         vam->retval = retval;
991         if (retval == 0)
992             errmsg ("next index %d\n", ntohl(mp->next_index));
993         vam->result_ready = 1;
994     }
995 }
996
997 static void vl_api_add_node_next_reply_t_handler_json
998 (vl_api_add_node_next_reply_t * mp)
999 {
1000     vat_main_t * vam = &vat_main;
1001     vat_json_node_t node;
1002
1003     vat_json_init_object(&node);
1004     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1005     vat_json_object_add_uint(&node, "next_index", ntohl(mp->next_index));
1006
1007     vat_json_print(vam->ofp, &node);
1008     vat_json_free(&node);
1009
1010     vam->retval = ntohl(mp->retval);
1011     vam->result_ready = 1;
1012 }
1013
1014 static void vl_api_mpls_gre_add_del_tunnel_reply_t_handler
1015 (vl_api_mpls_gre_add_del_tunnel_reply_t * mp)
1016 {
1017     vat_main_t * vam = &vat_main;
1018     i32 retval = ntohl(mp->retval);
1019     u32 sw_if_index = ntohl(mp->tunnel_sw_if_index);
1020
1021     if (retval >= 0 && sw_if_index != (u32)~0) {
1022         errmsg ("tunnel_sw_if_index %d\n", sw_if_index);
1023     }
1024     vam->retval = retval;
1025     vam->result_ready = 1;
1026 }
1027
1028 static void vl_api_mpls_gre_add_del_tunnel_reply_t_handler_json
1029 (vl_api_mpls_gre_add_del_tunnel_reply_t * mp)
1030 {
1031     vat_main_t * vam = &vat_main;
1032     vat_json_node_t node;
1033
1034     vat_json_init_object(&node);
1035     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1036     vat_json_object_add_uint(&node, "tunnel_sw_if_index", ntohl(mp->tunnel_sw_if_index));
1037
1038     vat_json_print(vam->ofp, &node);
1039     vat_json_free(&node);
1040
1041     vam->retval = ntohl(mp->retval);
1042     vam->result_ready = 1;
1043 }
1044
1045
1046 static void vl_api_show_version_reply_t_handler
1047 (vl_api_show_version_reply_t * mp)
1048 {
1049     vat_main_t * vam = &vat_main;
1050     i32 retval = ntohl(mp->retval);
1051
1052     if (retval >= 0) {
1053         errmsg ("        program: %s\n", mp->program);
1054         errmsg ("        version: %s\n", mp->version);
1055         errmsg ("     build date: %s\n", mp->build_date);
1056         errmsg ("build directory: %s\n", mp->build_directory);
1057     }
1058     vam->retval = retval;
1059     vam->result_ready = 1;
1060 }
1061
1062 static void vl_api_show_version_reply_t_handler_json
1063 (vl_api_show_version_reply_t * mp)
1064 {
1065     vat_main_t * vam = &vat_main;
1066     vat_json_node_t node;
1067
1068     vat_json_init_object(&node);
1069     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1070     vat_json_object_add_string_copy(&node, "program", mp->program);
1071     vat_json_object_add_string_copy(&node, "version", mp->version);
1072     vat_json_object_add_string_copy(&node, "build_date", mp->build_date);
1073     vat_json_object_add_string_copy(&node, "build_directory", mp->build_directory);
1074
1075     vat_json_print(vam->ofp, &node);
1076     vat_json_free(&node);
1077
1078     vam->retval = ntohl(mp->retval);
1079     vam->result_ready = 1;
1080 }
1081
1082 static void vl_api_ip4_arp_event_t_handler
1083 (vl_api_ip4_arp_event_t * mp)
1084 {
1085     vat_main_t * vam = &vat_main;
1086     errmsg ("arp event: address %U new mac %U sw_if_index %d\n",
1087             format_ip4_address, &mp->address,
1088             format_ethernet_address, mp->new_mac, mp->sw_if_index);
1089 }
1090
1091 static void vl_api_ip4_arp_event_t_handler_json
1092 (vl_api_ip4_arp_event_t * mp)
1093 {
1094     /* JSON output not supported */
1095 }
1096
1097 /*
1098  * Special-case: build the bridge domain table, maintain
1099  * the next bd id vbl.
1100  */
1101 static void vl_api_bridge_domain_details_t_handler
1102 (vl_api_bridge_domain_details_t * mp)
1103 {
1104     vat_main_t * vam = &vat_main;
1105     u32 n_sw_ifs =  ntohl (mp->n_sw_ifs);
1106
1107     fformat (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-3s\n",
1108              " ID", "LRN", "FWD", "FLD", "BVI", "#IF");
1109
1110     fformat (vam->ofp, "%3d %3d %3d %3d %3d %3d\n",
1111              ntohl (mp->bd_id), mp->learn, mp->forward,
1112              mp->flood, ntohl (mp->bvi_sw_if_index), n_sw_ifs);
1113
1114     if (n_sw_ifs)
1115         fformat (vam->ofp, "\n\n%s %s  %s\n", "sw_if_index", "SHG",
1116                  "Interface Name");
1117 }
1118
1119 static void vl_api_bridge_domain_details_t_handler_json
1120 (vl_api_bridge_domain_details_t * mp)
1121 {
1122     vat_main_t * vam = &vat_main;
1123     vat_json_node_t *node, *array = NULL;
1124
1125     if (VAT_JSON_ARRAY != vam->json_tree.type) {
1126         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
1127         vat_json_init_array(&vam->json_tree);
1128     }
1129     node = vat_json_array_add(&vam->json_tree);
1130
1131     vat_json_init_object(node);
1132     vat_json_object_add_uint(node, "bd_id", ntohl(mp->bd_id));
1133     vat_json_object_add_uint(node, "flood", mp->flood);
1134     vat_json_object_add_uint(node, "forward", mp->forward);
1135     vat_json_object_add_uint(node, "learn", mp->learn);
1136     vat_json_object_add_uint(node, "bvi_sw_if_index", ntohl(mp->bvi_sw_if_index));
1137     vat_json_object_add_uint(node, "n_sw_ifs", ntohl(mp->n_sw_ifs));
1138     array = vat_json_object_add(node, "sw_if");
1139     vat_json_init_array(array);
1140 }
1141
1142 /*
1143  * Special-case: build the bridge domain sw if table.
1144  */
1145 static void vl_api_bridge_domain_sw_if_details_t_handler
1146 (vl_api_bridge_domain_sw_if_details_t * mp)
1147 {
1148     vat_main_t * vam = &vat_main;
1149     hash_pair_t * p;
1150     u8 * sw_if_name = 0;
1151     u32 sw_if_index;
1152
1153     sw_if_index = ntohl (mp->sw_if_index);
1154     hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1155     ({
1156         if ((u32) p->value[0] == sw_if_index) {
1157             sw_if_name = (u8 *)(p->key);
1158             break;
1159         }
1160     }));
1161
1162     fformat (vam->ofp, "%7d     %3d  %s", sw_if_index,
1163              mp->shg, sw_if_name ? (char *)sw_if_name :
1164              "sw_if_index not found!");
1165 }
1166
1167 static void vl_api_bridge_domain_sw_if_details_t_handler_json
1168 (vl_api_bridge_domain_sw_if_details_t * mp)
1169 {
1170     vat_main_t * vam = &vat_main;
1171     vat_json_node_t *node = NULL;
1172     uword last_index = 0;
1173
1174     ASSERT(VAT_JSON_ARRAY == vam->json_tree.type);
1175     ASSERT(vec_len(vam->json_tree.array) >= 1);
1176     last_index = vec_len(vam->json_tree.array) - 1;
1177     node = &vam->json_tree.array[last_index];
1178     node = vat_json_object_get_element(node, "sw_if");
1179     ASSERT(NULL != node);
1180     node = vat_json_array_add(node);
1181
1182     vat_json_init_object(node);
1183     vat_json_object_add_uint(node, "bd_id", ntohl(mp->bd_id));
1184     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
1185     vat_json_object_add_uint(node, "shg", mp->shg);
1186 }
1187
1188 static void vl_api_control_ping_reply_t_handler
1189 (vl_api_control_ping_reply_t * mp)
1190 {
1191     vat_main_t * vam = &vat_main;
1192     i32 retval = ntohl(mp->retval);
1193     if (vam->async_mode) {
1194         vam->async_errors += (retval < 0);
1195     } else {
1196         vam->retval = retval;
1197         vam->result_ready = 1;
1198     }
1199 }
1200
1201 static void vl_api_control_ping_reply_t_handler_json
1202 (vl_api_control_ping_reply_t * mp)
1203 {
1204     vat_main_t * vam = &vat_main;
1205     i32 retval = ntohl(mp->retval);
1206
1207     if (VAT_JSON_NONE != vam->json_tree.type) {
1208         vat_json_print(vam->ofp, &vam->json_tree);
1209         vat_json_free(&vam->json_tree);
1210         vam->json_tree.type = VAT_JSON_NONE;
1211     } else {
1212         /* just print [] */
1213         vat_json_init_array(&vam->json_tree);
1214         vat_json_print(vam->ofp, &vam->json_tree);
1215         vam->json_tree.type = VAT_JSON_NONE;
1216     }
1217
1218     vam->retval = retval;
1219     vam->result_ready = 1;
1220 }
1221
1222 static void vl_api_noprint_control_ping_reply_t_handler
1223 (vl_api_noprint_control_ping_reply_t * mp)
1224 {
1225     vat_main_t * vam = &vat_main;
1226     i32 retval = ntohl(mp->retval);
1227     if (vam->async_mode) {
1228         vam->async_errors += (retval < 0);
1229     } else {
1230         vam->retval = retval;
1231         vam->result_ready = 1;
1232     }
1233 }
1234
1235 static void vl_api_noprint_control_ping_reply_t_handler_json
1236 (vl_api_noprint_control_ping_reply_t * mp)
1237 {
1238     vat_main_t * vam = &vat_main;
1239     i32 retval = ntohl(mp->retval);
1240
1241     if (vam->noprint_msg) {
1242       vam->retval = retval;
1243       vam->result_ready = 1;
1244       return;
1245     }
1246
1247     if (VAT_JSON_NONE != vam->json_tree.type) {
1248         vat_json_print(vam->ofp, &vam->json_tree);
1249         vat_json_free(&vam->json_tree);
1250         vam->json_tree.type = VAT_JSON_NONE;
1251     } else {
1252         /* just print [] */
1253         vat_json_init_array(&vam->json_tree);
1254         vat_json_print(vam->ofp, &vam->json_tree);
1255         vam->json_tree.type = VAT_JSON_NONE;
1256     }
1257
1258     vam->retval = retval;
1259     vam->result_ready = 1;
1260 }
1261
1262 static void vl_api_l2_flags_reply_t_handler
1263 (vl_api_l2_flags_reply_t * mp)
1264 {
1265     vat_main_t * vam = &vat_main;
1266     i32 retval = ntohl(mp->retval);
1267     if (vam->async_mode) {
1268         vam->async_errors += (retval < 0);
1269     } else {
1270         vam->retval = retval;
1271         vam->result_ready = 1;
1272     }
1273 }
1274
1275 static void vl_api_l2_flags_reply_t_handler_json
1276 (vl_api_l2_flags_reply_t * mp)
1277 {
1278     vat_main_t * vam = &vat_main;
1279     vat_json_node_t node;
1280
1281     vat_json_init_object(&node);
1282     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1283     vat_json_object_add_uint(&node, "resulting_feature_bitmap", ntohl(mp->resulting_feature_bitmap));
1284
1285     vat_json_print(vam->ofp, &node);
1286     vat_json_free(&node);
1287
1288     vam->retval = ntohl(mp->retval);
1289     vam->result_ready = 1;
1290 }
1291
1292 static void vl_api_bridge_flags_reply_t_handler
1293 (vl_api_bridge_flags_reply_t * mp)
1294 {
1295     vat_main_t * vam = &vat_main;
1296     i32 retval = ntohl(mp->retval);
1297     if (vam->async_mode) {
1298         vam->async_errors += (retval < 0);
1299     } else {
1300         vam->retval = retval;
1301         vam->result_ready = 1;
1302     }
1303 }
1304
1305 static void vl_api_bridge_flags_reply_t_handler_json
1306 (vl_api_bridge_flags_reply_t * mp)
1307 {
1308     vat_main_t * vam = &vat_main;
1309     vat_json_node_t node;
1310
1311     vat_json_init_object(&node);
1312     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1313     vat_json_object_add_uint(&node, "resulting_feature_bitmap", ntohl(mp->resulting_feature_bitmap));
1314
1315     vat_json_print(vam->ofp, &node);
1316     vat_json_free(&node);
1317
1318     vam->retval = ntohl(mp->retval);
1319     vam->result_ready = 1;
1320 }
1321
1322 static void vl_api_tap_connect_reply_t_handler
1323 (vl_api_tap_connect_reply_t * mp)
1324 {
1325     vat_main_t * vam = &vat_main;
1326     i32 retval = ntohl(mp->retval);
1327     if (vam->async_mode) {
1328         vam->async_errors += (retval < 0);
1329     } else {
1330         vam->retval = retval;
1331         vam->sw_if_index = ntohl (mp->sw_if_index);
1332         vam->result_ready = 1;
1333     }
1334
1335 }
1336
1337 static void vl_api_tap_connect_reply_t_handler_json
1338 (vl_api_tap_connect_reply_t * mp)
1339 {
1340     vat_main_t * vam = &vat_main;
1341     vat_json_node_t node;
1342
1343     vat_json_init_object(&node);
1344     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1345     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
1346
1347     vat_json_print(vam->ofp, &node);
1348     vat_json_free(&node);
1349
1350     vam->retval = ntohl(mp->retval);
1351     vam->result_ready = 1;
1352
1353 }
1354
1355 static void vl_api_tap_modify_reply_t_handler
1356 (vl_api_tap_modify_reply_t * mp)
1357 {
1358     vat_main_t * vam = &vat_main;
1359     i32 retval = ntohl(mp->retval);
1360     if (vam->async_mode) {
1361         vam->async_errors += (retval < 0);
1362     } else {
1363         vam->retval = retval;
1364         vam->sw_if_index = ntohl (mp->sw_if_index);
1365         vam->result_ready = 1;
1366     }
1367 }
1368
1369 static void vl_api_tap_modify_reply_t_handler_json
1370 (vl_api_tap_modify_reply_t * mp)
1371 {
1372     vat_main_t * vam = &vat_main;
1373     vat_json_node_t node;
1374
1375     vat_json_init_object(&node);
1376     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1377     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
1378
1379     vat_json_print(vam->ofp, &node);
1380     vat_json_free(&node);
1381
1382     vam->retval = ntohl(mp->retval);
1383     vam->result_ready = 1;
1384 }
1385
1386 static void vl_api_tap_delete_reply_t_handler
1387 (vl_api_tap_delete_reply_t * mp)
1388 {
1389     vat_main_t * vam = &vat_main;
1390     i32 retval = ntohl(mp->retval);
1391     if (vam->async_mode) {
1392         vam->async_errors += (retval < 0);
1393     } else {
1394         vam->retval = retval;
1395         vam->result_ready = 1;
1396     }
1397 }
1398
1399 static void vl_api_tap_delete_reply_t_handler_json
1400 (vl_api_tap_delete_reply_t * mp)
1401 {
1402     vat_main_t * vam = &vat_main;
1403     vat_json_node_t node;
1404
1405     vat_json_init_object(&node);
1406     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1407
1408     vat_json_print(vam->ofp, &node);
1409     vat_json_free(&node);
1410
1411     vam->retval = ntohl(mp->retval);
1412     vam->result_ready = 1;
1413 }
1414
1415 static void vl_api_mpls_ethernet_add_del_tunnel_reply_t_handler
1416 (vl_api_mpls_ethernet_add_del_tunnel_reply_t * mp)
1417 {
1418     vat_main_t * vam = &vat_main;
1419     i32 retval = ntohl(mp->retval);
1420     if (vam->async_mode) {
1421         vam->async_errors += (retval < 0);
1422     } else {
1423         vam->retval = retval;
1424         vam->result_ready = 1;
1425     }
1426 }
1427
1428 static void vl_api_mpls_ethernet_add_del_tunnel_reply_t_handler_json
1429 (vl_api_mpls_ethernet_add_del_tunnel_reply_t * mp)
1430 {
1431     vat_main_t * vam = &vat_main;
1432     vat_json_node_t node;
1433
1434     vat_json_init_object(&node);
1435     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1436     vat_json_object_add_uint(&node, "tunnel_sw_if_index", ntohl(mp->tunnel_sw_if_index));
1437
1438     vat_json_print(vam->ofp, &node);
1439     vat_json_free(&node);
1440
1441     vam->retval = ntohl(mp->retval);
1442     vam->result_ready = 1;
1443 }
1444
1445 static void vl_api_l2tpv3_create_tunnel_reply_t_handler
1446 (vl_api_l2tpv3_create_tunnel_reply_t * mp)
1447 {
1448     vat_main_t * vam = &vat_main;
1449     i32 retval = ntohl(mp->retval);
1450     if (vam->async_mode) {
1451         vam->async_errors += (retval < 0);
1452     } else {
1453         vam->retval = retval;
1454         vam->sw_if_index = ntohl (mp->sw_if_index);
1455         vam->result_ready = 1;
1456     }
1457 }
1458
1459 static void vl_api_l2tpv3_create_tunnel_reply_t_handler_json
1460 (vl_api_l2tpv3_create_tunnel_reply_t * mp)
1461 {
1462     vat_main_t * vam = &vat_main;
1463     vat_json_node_t node;
1464
1465     vat_json_init_object(&node);
1466     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1467     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
1468
1469     vat_json_print(vam->ofp, &node);
1470     vat_json_free(&node);
1471
1472     vam->retval = ntohl(mp->retval);
1473     vam->result_ready = 1;
1474 }
1475
1476 static void vl_api_vxlan_add_del_tunnel_reply_t_handler
1477 (vl_api_vxlan_add_del_tunnel_reply_t * mp)
1478 {
1479     vat_main_t * vam = &vat_main;
1480     i32 retval = ntohl(mp->retval);
1481     if (vam->async_mode) {
1482         vam->async_errors += (retval < 0);
1483     } else {
1484         vam->retval = retval;
1485         vam->sw_if_index = ntohl (mp->sw_if_index);
1486         vam->result_ready = 1;
1487     }
1488 }
1489
1490 static void vl_api_vxlan_add_del_tunnel_reply_t_handler_json
1491 (vl_api_vxlan_add_del_tunnel_reply_t * mp)
1492 {
1493     vat_main_t * vam = &vat_main;
1494     vat_json_node_t node;
1495
1496     vat_json_init_object(&node);
1497     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1498     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
1499
1500     vat_json_print(vam->ofp, &node);
1501     vat_json_free(&node);
1502
1503     vam->retval = ntohl(mp->retval);
1504     vam->result_ready = 1;
1505 }
1506
1507 static void vl_api_gre_add_del_tunnel_reply_t_handler
1508 (vl_api_gre_add_del_tunnel_reply_t * mp)
1509 {
1510     vat_main_t * vam = &vat_main;
1511     i32 retval = ntohl(mp->retval);
1512     if (vam->async_mode) {
1513         vam->async_errors += (retval < 0);
1514     } else {
1515         vam->retval = retval;
1516         vam->sw_if_index = ntohl (mp->sw_if_index);
1517         vam->result_ready = 1;
1518     }
1519 }
1520
1521 static void vl_api_gre_add_del_tunnel_reply_t_handler_json
1522 (vl_api_gre_add_del_tunnel_reply_t * mp)
1523 {
1524     vat_main_t * vam = &vat_main;
1525     vat_json_node_t node;
1526
1527     vat_json_init_object(&node);
1528     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1529     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
1530
1531     vat_json_print(vam->ofp, &node);
1532     vat_json_free(&node);
1533
1534     vam->retval = ntohl(mp->retval);
1535     vam->result_ready = 1;
1536 }
1537
1538 static void vl_api_create_vhost_user_if_reply_t_handler
1539 (vl_api_create_vhost_user_if_reply_t * mp)
1540 {
1541     vat_main_t * vam = &vat_main;
1542     i32 retval = ntohl(mp->retval);
1543     if (vam->async_mode) {
1544         vam->async_errors += (retval < 0);
1545     } else {
1546         vam->retval = retval;
1547         vam->sw_if_index = ntohl (mp->sw_if_index);
1548         vam->result_ready = 1;
1549     }
1550 }
1551
1552 static void vl_api_create_vhost_user_if_reply_t_handler_json
1553 (vl_api_create_vhost_user_if_reply_t * mp)
1554 {
1555     vat_main_t * vam = &vat_main;
1556     vat_json_node_t node;
1557
1558     vat_json_init_object(&node);
1559     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1560     vat_json_object_add_uint(&node, "sw_if_index", ntohl(mp->sw_if_index));
1561
1562     vat_json_print(vam->ofp, &node);
1563     vat_json_free(&node);
1564
1565     vam->retval = ntohl(mp->retval);
1566     vam->result_ready = 1;
1567 }
1568
1569 static void vl_api_ip_address_details_t_handler
1570 (vl_api_ip_address_details_t * mp)
1571 {
1572     vat_main_t * vam = &vat_main;
1573     static ip_address_details_t empty_ip_address_details = {{0}};
1574     ip_address_details_t * address = NULL;
1575     ip_details_t * current_ip_details = NULL;
1576     ip_details_t * details = NULL;
1577
1578     details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1579
1580     if (!details || vam->current_sw_if_index >= vec_len(details)
1581             || !details[vam->current_sw_if_index].present) {
1582         errmsg ("ip address details arrived but not stored\n");
1583         errmsg ("ip_dump should be called first\n");
1584         return;
1585     }
1586
1587     current_ip_details = vec_elt_at_index(details,
1588             vam->current_sw_if_index);
1589
1590 #define addresses (current_ip_details->addr)
1591
1592     vec_validate_init_empty(addresses, vec_len(addresses),
1593             empty_ip_address_details);
1594
1595     address = vec_elt_at_index(addresses, vec_len(addresses) - 1);
1596
1597     clib_memcpy(&address->ip, &mp->ip, sizeof(address->ip));
1598     address->prefix_length = mp->prefix_length;
1599 #undef addresses
1600 }
1601
1602 static void vl_api_ip_address_details_t_handler_json
1603 (vl_api_ip_address_details_t * mp)
1604 {
1605     vat_main_t * vam = &vat_main;
1606     vat_json_node_t *node = NULL;
1607     struct in6_addr ip6;
1608     struct in_addr ip4;
1609
1610     if (VAT_JSON_ARRAY != vam->json_tree.type) {
1611         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
1612         vat_json_init_array(&vam->json_tree);
1613     }
1614     node = vat_json_array_add(&vam->json_tree);
1615
1616     vat_json_init_object(node);
1617     if (vam->is_ipv6) {
1618         clib_memcpy(&ip6, mp->ip, sizeof(ip6));
1619         vat_json_object_add_ip6(node, "ip",  ip6);
1620     } else {
1621         clib_memcpy(&ip4, mp->ip, sizeof(ip4));
1622         vat_json_object_add_ip4(node, "ip", ip4);
1623     }
1624     vat_json_object_add_uint(node, "prefix_length", mp->prefix_length);
1625 }
1626
1627 static void vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
1628 {
1629     vat_main_t * vam = &vat_main;
1630     static ip_details_t empty_ip_details = {0};
1631     ip_details_t * ip = NULL;
1632     u32 sw_if_index = ~0;
1633
1634     sw_if_index = ntohl(mp->sw_if_index);
1635
1636     vec_validate_init_empty(vam->ip_details_by_sw_if_index[vam->is_ipv6],
1637             sw_if_index, empty_ip_details);
1638
1639     ip = vec_elt_at_index(vam->ip_details_by_sw_if_index[vam->is_ipv6],
1640             sw_if_index);
1641
1642     ip->present = 1;
1643 }
1644
1645 static void vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
1646 {
1647     vat_main_t * vam = &vat_main;
1648
1649     if (VAT_JSON_ARRAY != vam->json_tree.type) {
1650         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
1651         vat_json_init_array(&vam->json_tree);
1652     }
1653     vat_json_array_add_uint(&vam->json_tree, clib_net_to_host_u32(mp->sw_if_index));
1654 }
1655
1656 static void vl_api_map_domain_details_t_handler_json
1657 (vl_api_map_domain_details_t * mp)
1658 {
1659     vat_json_node_t * node = NULL;
1660     vat_main_t * vam = &vat_main;
1661     struct in6_addr ip6;
1662     struct in_addr ip4;
1663
1664     if (VAT_JSON_ARRAY != vam->json_tree.type) {
1665         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
1666         vat_json_init_array(&vam->json_tree);
1667     }
1668
1669     node = vat_json_array_add(&vam->json_tree);
1670     vat_json_init_object(node);
1671
1672     vat_json_object_add_uint(node, "domain_index", clib_net_to_host_u32(mp->domain_index));
1673     clib_memcpy(&ip6, mp->ip6_prefix, sizeof(ip6));
1674     vat_json_object_add_ip6(node, "ip6_prefix", ip6);
1675     clib_memcpy(&ip4, mp->ip4_prefix, sizeof(ip4));
1676     vat_json_object_add_ip4(node, "ip4_prefix", ip4);
1677     clib_memcpy(&ip6, mp->ip6_src, sizeof(ip6));
1678     vat_json_object_add_ip6(node, "ip6_src", ip6);
1679     vat_json_object_add_int(node, "ip6_prefix_len", mp->ip6_prefix_len);
1680     vat_json_object_add_int(node, "ip4_prefix_len", mp->ip4_prefix_len);
1681     vat_json_object_add_int(node, "ip6_src_len", mp->ip6_src_len);
1682     vat_json_object_add_int(node, "ea_bits_len", mp->ea_bits_len);
1683     vat_json_object_add_int(node, "psid_offset", mp->psid_offset);
1684     vat_json_object_add_int(node, "psid_length", mp->psid_length);
1685     vat_json_object_add_uint(node, "flags", mp->flags);
1686     vat_json_object_add_uint(node, "mtu", clib_net_to_host_u16(mp->mtu));
1687     vat_json_object_add_int(node, "is_translation", mp->is_translation);
1688 }
1689
1690 static void vl_api_map_domain_details_t_handler
1691 (vl_api_map_domain_details_t * mp)
1692 {
1693     vat_main_t * vam = &vat_main;
1694
1695     if (mp->is_translation) {
1696         fformat(vam->ofp,  "* %U/%d (ipv4-prefix) %U/%d (ipv6-prefix) %U/%d (ip6-src) index: %u\n",
1697                   format_ip4_address, mp->ip4_prefix, mp->ip4_prefix_len,
1698                   format_ip6_address, mp->ip6_prefix, mp->ip6_prefix_len,
1699                   format_ip6_address, mp->ip6_src, mp->ip6_src_len, clib_net_to_host_u32(mp->domain_index));
1700     } else {
1701         fformat(vam->ofp,  "* %U/%d (ipv4-prefix) %U/%d (ipv6-prefix) %U (ip6-src) index: %u\n",
1702                   format_ip4_address, mp->ip4_prefix, mp->ip4_prefix_len,
1703                   format_ip6_address, mp->ip6_prefix, mp->ip6_prefix_len,
1704                   format_ip6_address, mp->ip6_src, clib_net_to_host_u32(mp->domain_index));
1705     }
1706     fformat(vam->ofp, "  ea-len %d psid-offset %d psid-len %d mtu %d %s\n",
1707             mp->ea_bits_len, mp->psid_offset, mp->psid_length, mp->mtu, mp->is_translation? "map-t":"");
1708 }
1709
1710 static void vl_api_map_rule_details_t_handler_json
1711 (vl_api_map_rule_details_t * mp)
1712 {
1713     struct in6_addr ip6;
1714     vat_json_node_t * node = NULL;
1715     vat_main_t * vam = &vat_main;
1716
1717     if (VAT_JSON_ARRAY != vam->json_tree.type) {
1718         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
1719         vat_json_init_array(&vam->json_tree);
1720     }
1721
1722     node = vat_json_array_add(&vam->json_tree);
1723     vat_json_init_object(node);
1724
1725     vat_json_object_add_uint(node, "psid", clib_net_to_host_u16(mp->psid));
1726     clib_memcpy(&ip6, mp->ip6_dst, sizeof(ip6));
1727     vat_json_object_add_ip6(node, "ip6_dst", ip6);
1728 }
1729
1730 static void vl_api_map_rule_details_t_handler
1731 (vl_api_map_rule_details_t * mp)
1732 {
1733     vat_main_t * vam = &vat_main;
1734     fformat(vam->ofp, " %d (psid) %U (ip6-dst)\n", clib_net_to_host_u16(mp->psid),
1735             format_ip6_address, mp->ip6_dst);
1736 }
1737
1738 static void vl_api_dhcp_compl_event_t_handler
1739 (vl_api_dhcp_compl_event_t * mp)
1740 {
1741     vat_main_t * vam = &vat_main;
1742     errmsg ("DHCP compl event: pid %d %s hostname %s host_addr %U "
1743             "router_addr %U host_mac %U\n",
1744             mp->pid, mp->is_ipv6 ? "ipv6":"ipv4", mp->hostname,
1745             format_ip4_address, &mp->host_address,
1746             format_ip4_address, &mp->router_address,
1747             format_ethernet_address, mp->host_mac);
1748 }
1749
1750 static void vl_api_dhcp_compl_event_t_handler_json
1751 (vl_api_dhcp_compl_event_t * mp)
1752 {
1753     /* JSON output not supported */
1754 }
1755
1756 static void set_simple_interface_counter (u8 vnet_counter_type, u32 sw_if_index,
1757                                           u32 counter)
1758 {
1759     vat_main_t * vam = &vat_main;
1760     static u64 default_counter = 0;
1761
1762     vec_validate_init_empty(vam->simple_interface_counters, vnet_counter_type, NULL);
1763     vec_validate_init_empty(vam->simple_interface_counters[vnet_counter_type],
1764                             sw_if_index, default_counter);
1765     vam->simple_interface_counters[vnet_counter_type][sw_if_index] = counter;
1766 }
1767
1768 static void set_combined_interface_counter (u8 vnet_counter_type, u32 sw_if_index,
1769                                             interface_counter_t counter)
1770 {
1771     vat_main_t * vam = &vat_main;
1772     static interface_counter_t default_counter = {0, };
1773
1774     vec_validate_init_empty(vam->combined_interface_counters, vnet_counter_type, NULL);
1775     vec_validate_init_empty(vam->combined_interface_counters[vnet_counter_type],
1776                             sw_if_index, default_counter);
1777     vam->combined_interface_counters[vnet_counter_type][sw_if_index] = counter;
1778 }
1779
1780 static void vl_api_vnet_interface_counters_t_handler
1781 (vl_api_vnet_interface_counters_t *mp)
1782 {
1783     /* not supported */
1784 }
1785
1786 static void vl_api_vnet_interface_counters_t_handler_json
1787 (vl_api_vnet_interface_counters_t *mp)
1788 {
1789     interface_counter_t counter;
1790     vlib_counter_t *v;
1791     u64 *v_packets;
1792     u64 packets;
1793     u32 count;
1794     u32 first_sw_if_index;
1795     int i;
1796
1797     count = ntohl(mp->count);
1798     first_sw_if_index = ntohl(mp->first_sw_if_index);
1799
1800     if (!mp->is_combined) {
1801         v_packets = (u64*)&mp->data;
1802         for (i = 0; i < count; i++) {
1803             packets = clib_net_to_host_u64(clib_mem_unaligned(v_packets, u64));
1804             set_simple_interface_counter(mp->vnet_counter_type,
1805                     first_sw_if_index + i, packets);
1806             v_packets++;
1807         }
1808     } else {
1809         v = (vlib_counter_t*)&mp->data;
1810         for (i = 0; i < count; i++) {
1811             counter.packets = clib_net_to_host_u64(
1812                     clib_mem_unaligned(&v->packets, u64));
1813             counter.bytes = clib_net_to_host_u64(
1814                     clib_mem_unaligned(&v->bytes, u64));
1815             set_combined_interface_counter(mp->vnet_counter_type,
1816                     first_sw_if_index + i, counter);
1817             v++;
1818         }
1819     }
1820 }
1821
1822 static u32 ip4_fib_counters_get_vrf_index_by_vrf_id (u32 vrf_id)
1823 {
1824     vat_main_t * vam = &vat_main;
1825     u32 i;
1826
1827     for (i = 0; i < vec_len(vam->ip4_fib_counters_vrf_id_by_index); i++) {
1828         if (vam->ip4_fib_counters_vrf_id_by_index[i] == vrf_id) {
1829             return i;
1830         }
1831     }
1832     return ~0;
1833 }
1834
1835 static u32 ip6_fib_counters_get_vrf_index_by_vrf_id (u32 vrf_id)
1836 {
1837     vat_main_t * vam = &vat_main;
1838     u32 i;
1839
1840     for (i = 0; i < vec_len(vam->ip6_fib_counters_vrf_id_by_index); i++) {
1841         if (vam->ip6_fib_counters_vrf_id_by_index[i] == vrf_id) {
1842             return i;
1843         }
1844     }
1845     return ~0;
1846 }
1847
1848 static void vl_api_vnet_ip4_fib_counters_t_handler
1849 (vl_api_vnet_ip4_fib_counters_t *mp)
1850 {
1851     /* not supported */
1852 }
1853
1854 static void vl_api_vnet_ip4_fib_counters_t_handler_json
1855 (vl_api_vnet_ip4_fib_counters_t *mp)
1856 {
1857     vat_main_t * vam = &vat_main;
1858     vl_api_ip4_fib_counter_t *v;
1859     ip4_fib_counter_t *counter;
1860     struct in_addr ip4;
1861     u32 vrf_id;
1862     u32 vrf_index;
1863     u32 count;
1864     int i;
1865
1866     vrf_id = ntohl(mp->vrf_id);
1867     vrf_index = ip4_fib_counters_get_vrf_index_by_vrf_id(vrf_id);
1868     if (~0 == vrf_index) {
1869         vrf_index = vec_len(vam->ip4_fib_counters_vrf_id_by_index);
1870         vec_validate(vam->ip4_fib_counters_vrf_id_by_index, vrf_index);
1871         vam->ip4_fib_counters_vrf_id_by_index[vrf_index] = vrf_id;
1872         vec_validate(vam->ip4_fib_counters, vrf_index);
1873         vam->ip4_fib_counters[vrf_index] = NULL;
1874     }
1875
1876     vec_free(vam->ip4_fib_counters[vrf_index]);
1877     v = (vl_api_ip4_fib_counter_t*)&mp->c;
1878     count = ntohl(mp->count);
1879     for (i = 0; i < count; i++) {
1880         vec_validate(vam->ip4_fib_counters[vrf_index], i);
1881         counter = &vam->ip4_fib_counters[vrf_index][i];
1882         clib_memcpy(&ip4, &v->address, sizeof(ip4));
1883         counter->address = ip4;
1884         counter->address_length = v->address_length;
1885         counter->packets = clib_net_to_host_u64(v->packets);
1886         counter->bytes = clib_net_to_host_u64(v->bytes);
1887         v++;
1888     }
1889 }
1890
1891 static void vl_api_vnet_ip6_fib_counters_t_handler
1892 (vl_api_vnet_ip6_fib_counters_t *mp)
1893 {
1894     /* not supported */
1895 }
1896
1897 static void vl_api_vnet_ip6_fib_counters_t_handler_json
1898 (vl_api_vnet_ip6_fib_counters_t *mp)
1899 {
1900     vat_main_t * vam = &vat_main;
1901     vl_api_ip6_fib_counter_t *v;
1902     ip6_fib_counter_t *counter;
1903     struct in6_addr ip6;
1904     u32 vrf_id;
1905     u32 vrf_index;
1906     u32 count;
1907     int i;
1908
1909     vrf_id = ntohl(mp->vrf_id);
1910     vrf_index = ip6_fib_counters_get_vrf_index_by_vrf_id(vrf_id);
1911     if (~0 == vrf_index) {
1912         vrf_index = vec_len(vam->ip6_fib_counters_vrf_id_by_index);
1913         vec_validate(vam->ip6_fib_counters_vrf_id_by_index, vrf_index);
1914         vam->ip6_fib_counters_vrf_id_by_index[vrf_index] = vrf_id;
1915         vec_validate(vam->ip6_fib_counters, vrf_index);
1916         vam->ip6_fib_counters[vrf_index] = NULL;
1917     }
1918
1919     vec_free(vam->ip6_fib_counters[vrf_index]);
1920     v = (vl_api_ip6_fib_counter_t*)&mp->c;
1921     count = ntohl(mp->count);
1922     for (i = 0; i < count; i++) {
1923         vec_validate(vam->ip6_fib_counters[vrf_index], i);
1924         counter = &vam->ip6_fib_counters[vrf_index][i];
1925         clib_memcpy(&ip6, &v->address, sizeof(ip6));
1926         counter->address = ip6;
1927         counter->address_length = v->address_length;
1928         counter->packets = clib_net_to_host_u64(v->packets);
1929         counter->bytes = clib_net_to_host_u64(v->bytes);
1930         v++;
1931     }
1932 }
1933
1934 static void vl_api_get_first_msg_id_reply_t_handler
1935 (vl_api_get_first_msg_id_reply_t * mp)
1936 {
1937     vat_main_t * vam = &vat_main;
1938     i32 retval = ntohl(mp->retval);
1939
1940     if (vam->async_mode) {
1941         vam->async_errors += (retval < 0);
1942     } else {
1943         vam->retval = retval;
1944         vam->result_ready = 1;
1945     }
1946     if (retval >= 0) {
1947         errmsg ("first message id %d\n", ntohs(mp->first_msg_id));
1948     }
1949 }
1950
1951 static void vl_api_get_first_msg_id_reply_t_handler_json
1952 (vl_api_get_first_msg_id_reply_t * mp)
1953 {
1954     vat_main_t * vam = &vat_main;
1955     vat_json_node_t node;
1956
1957     vat_json_init_object(&node);
1958     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
1959     vat_json_object_add_uint(&node, "first_msg_id",
1960                              (uint) ntohs(mp->first_msg_id));
1961
1962     vat_json_print(vam->ofp, &node);
1963     vat_json_free(&node);
1964
1965     vam->retval = ntohl(mp->retval);
1966     vam->result_ready = 1;
1967 }
1968
1969 static void vl_api_get_node_graph_reply_t_handler
1970 (vl_api_get_node_graph_reply_t * mp)
1971 {
1972     vat_main_t * vam = &vat_main;
1973     api_main_t * am = &api_main;
1974     i32 retval = ntohl(mp->retval);
1975     u8 * pvt_copy, * reply;
1976     void * oldheap;
1977     vlib_node_t * node;
1978     int i;
1979
1980     if (vam->async_mode) {
1981         vam->async_errors += (retval < 0);
1982     } else {
1983         vam->retval = retval;
1984         vam->result_ready = 1;
1985     }
1986
1987     /* "Should never happen..." */
1988     if (retval != 0)
1989         return;
1990
1991     reply = (u8 *)(mp->reply_in_shmem);
1992     pvt_copy = vec_dup (reply);
1993
1994     /* Toss the shared-memory original... */
1995     pthread_mutex_lock (&am->vlib_rp->mutex);
1996     oldheap = svm_push_data_heap (am->vlib_rp);
1997
1998     vec_free (reply);
1999
2000     svm_pop_heap (oldheap);
2001     pthread_mutex_unlock (&am->vlib_rp->mutex);
2002
2003     if (vam->graph_nodes) {
2004         hash_free (vam->graph_node_index_by_name);
2005
2006         for (i = 0; i < vec_len (vam->graph_nodes); i++) {
2007             node = vam->graph_nodes[i];
2008             vec_free (node->name);
2009             vec_free (node->next_nodes);
2010             vec_free (node);
2011         }
2012         vec_free(vam->graph_nodes);
2013     }
2014
2015     vam->graph_node_index_by_name = hash_create_string (0, sizeof(uword));
2016     vam->graph_nodes = vlib_node_unserialize (pvt_copy);
2017     vec_free (pvt_copy);
2018
2019     for (i = 0; i < vec_len (vam->graph_nodes); i++) {
2020         node = vam->graph_nodes[i];
2021         hash_set_mem (vam->graph_node_index_by_name, node->name, i);
2022     }
2023 }
2024
2025 static void vl_api_get_node_graph_reply_t_handler_json
2026 (vl_api_get_node_graph_reply_t * mp)
2027 {
2028     vat_main_t * vam = &vat_main;
2029     api_main_t * am = &api_main;
2030     void * oldheap;
2031     vat_json_node_t node;
2032     u8 * reply;
2033
2034     /* $$$$ make this real? */
2035     vat_json_init_object(&node);
2036     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
2037     vat_json_object_add_uint(&node, "reply_in_shmem", mp->reply_in_shmem);
2038
2039     reply = (u8 *)(mp->reply_in_shmem);
2040
2041     /* Toss the shared-memory original... */
2042     pthread_mutex_lock (&am->vlib_rp->mutex);
2043     oldheap = svm_push_data_heap (am->vlib_rp);
2044
2045     vec_free (reply);
2046
2047     svm_pop_heap (oldheap);
2048     pthread_mutex_unlock (&am->vlib_rp->mutex);
2049
2050     vat_json_print(vam->ofp, &node);
2051     vat_json_free(&node);
2052
2053     vam->retval = ntohl(mp->retval);
2054     vam->result_ready = 1;
2055 }
2056
2057 static void
2058 vl_api_lisp_locator_details_t_handler (
2059     vl_api_lisp_locator_details_t *mp)
2060 {
2061     vat_main_t *vam = &vat_main;
2062     locator_msg_t loc;
2063     u8 * tmp_str = 0;
2064
2065     memset(&loc, 0, sizeof(loc));
2066     if (vam->noprint_msg) {
2067       loc.local = mp->local;
2068       loc.priority = mp->priority;
2069       loc.weight = mp->weight;
2070       if (loc.local) {
2071         loc.sw_if_index = ntohl(mp->sw_if_index);
2072       } else {
2073         loc.is_ipv6 = mp->is_ipv6;
2074         clib_memcpy(loc.ip_address, mp->ip_address, sizeof(loc.ip_address));
2075       }
2076       vec_add1(vam->locator_msg, loc);
2077     } else {
2078       if (mp->local) {
2079         tmp_str = format(tmp_str, "%=16d%=16d%=16d\n",
2080                          ntohl(mp->sw_if_index),
2081                          mp->priority,
2082                          mp->weight);
2083       } else {
2084         tmp_str = format(tmp_str, "%=16U%=16d%=16d\n",
2085                          mp->is_ipv6 ? format_ip6_address :
2086                          format_ip4_address,
2087                          mp->ip_address,
2088                          mp->priority,
2089                          mp->weight);
2090       }
2091
2092       fformat(vam->ofp, "%s", tmp_str);
2093
2094       vec_free(tmp_str);
2095     }
2096 }
2097
2098 static void
2099 vl_api_lisp_locator_details_t_handler_json (
2100     vl_api_lisp_locator_details_t *mp)
2101 {
2102     vat_main_t *vam = &vat_main;
2103     vat_json_node_t *node = NULL;
2104     locator_msg_t loc;
2105     struct in6_addr ip6;
2106     struct in_addr ip4;
2107
2108     memset(&loc, 0, sizeof(loc));
2109     if (vam->noprint_msg) {
2110         loc.local = mp->local;
2111         loc.priority = mp->priority;
2112         loc.weight = mp->weight;
2113         if (loc.local) {
2114             loc.sw_if_index = ntohl(mp->sw_if_index);
2115         } else {
2116             loc.is_ipv6 = mp->is_ipv6;
2117             clib_memcpy(loc.ip_address, mp->ip_address, sizeof(loc.ip_address));
2118         }
2119         vec_add1(vam->locator_msg, loc);
2120         return;
2121     }
2122
2123     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2124         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2125         vat_json_init_array(&vam->json_tree);
2126     }
2127     node = vat_json_array_add(&vam->json_tree);
2128
2129     vat_json_init_object(node);
2130
2131     if (mp->local) {
2132         vat_json_object_add_uint(node, "locator_index", ntohl(mp->sw_if_index));
2133     } else {
2134       if (mp->is_ipv6) {
2135         clib_memcpy(&ip6, mp->ip_address, sizeof(ip6));
2136         vat_json_object_add_ip6(node, "locator", ip6);
2137       } else {
2138         clib_memcpy(&ip4, mp->ip_address, sizeof(ip4));
2139         vat_json_object_add_ip4(node, "locator", ip4);
2140       }
2141     }
2142     vat_json_object_add_uint(node, "priority", mp->priority);
2143     vat_json_object_add_uint(node, "weight", mp->weight);
2144 }
2145
2146 static void
2147 vl_api_lisp_locator_set_details_t_handler (
2148     vl_api_lisp_locator_set_details_t *mp)
2149 {
2150     vat_main_t *vam = &vat_main;
2151     locator_set_msg_t ls;
2152
2153     ls.locator_set_index = ntohl(mp->locator_set_index);
2154     ls.locator_set_name = format(0, "%s", mp->locator_set_name);
2155     vec_add1(vam->locator_set_msg, ls);
2156 }
2157
2158 static void
2159 vl_api_lisp_locator_set_details_t_handler_json (
2160     vl_api_lisp_locator_set_details_t *mp)
2161 {
2162     vat_main_t *vam = &vat_main;
2163     locator_set_msg_t ls;
2164
2165     ls.locator_set_index = ntohl(mp->locator_set_index);
2166     ls.locator_set_name = format(0, "%s", mp->locator_set_name);
2167     vec_add1(vam->locator_set_msg, ls);
2168 }
2169
2170 static void
2171 vl_api_lisp_eid_table_details_t_handler (
2172     vl_api_lisp_eid_table_details_t * mp)
2173 {
2174     vat_main_t *vam = &vat_main;
2175     eid_table_t eid_table;
2176
2177     memset(&eid_table, 0, sizeof(eid_table));
2178     eid_table.is_local = mp->is_local;
2179     eid_table.locator_set_index = mp->locator_set_index;
2180     eid_table.eid_type = mp->eid_type;
2181     eid_table.vni = mp->vni;
2182     eid_table.eid_prefix_len = mp->eid_prefix_len;
2183     eid_table.ttl = mp->ttl;
2184     eid_table.authoritative = mp->authoritative;
2185     clib_memcpy(eid_table.eid, mp->eid, sizeof(eid_table.eid));
2186     vec_add1(vam->eid_tables, eid_table);
2187 }
2188
2189 static void
2190 vl_api_lisp_eid_table_details_t_handler_json (
2191     vl_api_lisp_eid_table_details_t * mp)
2192 {
2193     vat_main_t *vam = &vat_main;
2194     eid_table_t eid_table;
2195
2196     memset(&eid_table, 0, sizeof(eid_table));
2197     eid_table.is_local = mp->is_local;
2198     eid_table.locator_set_index = mp->locator_set_index;
2199     eid_table.eid_type = mp->eid_type;
2200     eid_table.vni = mp->vni;
2201     eid_table.eid_prefix_len = mp->eid_prefix_len;
2202     eid_table.ttl = mp->ttl;
2203     eid_table.authoritative = mp->authoritative;
2204     clib_memcpy(eid_table.eid, mp->eid, sizeof(eid_table.eid));
2205     vec_add1(vam->eid_tables, eid_table);
2206 }
2207
2208 static void
2209 vl_api_lisp_eid_table_map_details_t_handler (
2210     vl_api_lisp_eid_table_map_details_t *mp)
2211 {
2212     vat_main_t *vam = &vat_main;
2213
2214     u8 * line = format(0, "%=10d%=10d",
2215                        clib_net_to_host_u32 (mp->vni),
2216                        clib_net_to_host_u32 (mp->vrf));
2217     fformat(vam->ofp, "%v\n", line);
2218     vec_free(line);
2219 }
2220
2221 static void
2222 vl_api_lisp_eid_table_map_details_t_handler_json (
2223     vl_api_lisp_eid_table_map_details_t *mp)
2224 {
2225     vat_main_t *vam = &vat_main;
2226     vat_json_node_t *node = NULL;
2227
2228     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2229         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2230         vat_json_init_array(&vam->json_tree);
2231     }
2232     node = vat_json_array_add(&vam->json_tree);
2233     vat_json_init_object(node);
2234     vat_json_object_add_uint(node, "vrf", clib_net_to_host_u32 (mp->vrf));
2235     vat_json_object_add_uint(node, "vni", clib_net_to_host_u32 (mp->vni));
2236 }
2237
2238
2239
2240 static u8 *
2241 format_decap_next (u8 * s, va_list * args)
2242 {
2243   u32 next_index = va_arg (*args, u32);
2244
2245   switch (next_index)
2246     {
2247     case LISP_GPE_INPUT_NEXT_DROP:
2248       return format (s, "drop");
2249     case LISP_GPE_INPUT_NEXT_IP4_INPUT:
2250       return format (s, "ip4");
2251     case LISP_GPE_INPUT_NEXT_IP6_INPUT:
2252       return format (s, "ip6");
2253     default:
2254       return format (s, "unknown %d", next_index);
2255     }
2256   return s;
2257 }
2258
2259 static void
2260 vl_api_lisp_gpe_tunnel_details_t_handler (vl_api_lisp_gpe_tunnel_details_t *mp)
2261 {
2262     vat_main_t *vam = &vat_main;
2263     u8 *iid_str;
2264     u8 *flag_str = NULL;
2265
2266     iid_str = format(0, "%d (0x%x)", ntohl(mp->iid), ntohl(mp->iid));
2267
2268 #define _(n,v) if (mp->flags & v) flag_str = format (flag_str, "%s-bit ", #n);
2269   foreach_lisp_gpe_flag_bit;
2270 #undef _
2271
2272     fformat(vam->ofp, "%=20d%=30U%=16U%=16d%=16d%=16U"
2273             "%=16d%=16d%=16sd=16d%=16s%=16s\n",
2274             mp->tunnels,
2275             mp->is_ipv6 ? format_ip6_address : format_ip4_address,
2276             mp->source_ip,
2277             mp->is_ipv6 ? format_ip6_address : format_ip4_address,
2278             mp->destination_ip,
2279             ntohl(mp->encap_fib_id),
2280             ntohl(mp->decap_fib_id),
2281             format_decap_next, ntohl(mp->dcap_next),
2282             mp->ver_res >> 6,
2283             flag_str,
2284             mp->next_protocol,
2285             mp->ver_res,
2286             mp->res,
2287             iid_str);
2288
2289     vec_free(iid_str);
2290 }
2291
2292 static void
2293 vl_api_lisp_gpe_tunnel_details_t_handler_json (
2294     vl_api_lisp_gpe_tunnel_details_t *mp)
2295 {
2296     vat_main_t *vam = &vat_main;
2297     vat_json_node_t *node = NULL;
2298     struct in6_addr ip6;
2299     struct in_addr ip4;
2300     u8 *next_decap_str;
2301
2302     next_decap_str = format(0, "%U", format_decap_next, htonl(mp->dcap_next));
2303
2304     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2305         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2306         vat_json_init_array(&vam->json_tree);
2307     }
2308     node = vat_json_array_add(&vam->json_tree);
2309
2310     vat_json_init_object(node);
2311     vat_json_object_add_uint(node, "tunel", mp->tunnels);
2312     if (mp->is_ipv6) {
2313         clib_memcpy(&ip6, mp->source_ip, sizeof(ip6));
2314         vat_json_object_add_ip6(node, "source address", ip6);
2315         clib_memcpy(&ip6, mp->destination_ip, sizeof(ip6));
2316         vat_json_object_add_ip6(node, "destination address", ip6);
2317     } else {
2318         clib_memcpy(&ip4, mp->source_ip, sizeof(ip4));
2319         vat_json_object_add_ip4(node, "source address", ip4);
2320         clib_memcpy(&ip4, mp->destination_ip, sizeof(ip4));
2321         vat_json_object_add_ip4(node, "destination address", ip4);
2322     }
2323     vat_json_object_add_uint(node, "fib encap", ntohl(mp->encap_fib_id));
2324     vat_json_object_add_uint(node, "fib decap", ntohl(mp->decap_fib_id));
2325     vat_json_object_add_string_copy(node, "decap next", next_decap_str);
2326     vat_json_object_add_uint(node, "lisp version", mp->ver_res >> 6);
2327     vat_json_object_add_uint(node, "flags", mp->flags);
2328     vat_json_object_add_uint(node, "next protocol", mp->next_protocol);
2329     vat_json_object_add_uint(node, "ver_res", mp->ver_res);
2330     vat_json_object_add_uint(node, "res", mp->res);
2331     vat_json_object_add_uint(node, "iid", ntohl(mp->iid));
2332
2333     vec_free(next_decap_str);
2334 }
2335
2336 static void
2337 vl_api_lisp_map_resolver_details_t_handler (
2338     vl_api_lisp_map_resolver_details_t *mp)
2339 {
2340     vat_main_t *vam = &vat_main;
2341
2342     fformat(vam->ofp, "%=20U\n",
2343             mp->is_ipv6 ? format_ip6_address : format_ip4_address,
2344             mp->ip_address);
2345 }
2346
2347 static void
2348 vl_api_lisp_map_resolver_details_t_handler_json (
2349     vl_api_lisp_map_resolver_details_t *mp)
2350 {
2351     vat_main_t *vam = &vat_main;
2352     vat_json_node_t *node = NULL;
2353     struct in6_addr ip6;
2354     struct in_addr ip4;
2355
2356     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2357         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2358         vat_json_init_array(&vam->json_tree);
2359     }
2360     node = vat_json_array_add(&vam->json_tree);
2361
2362     vat_json_init_object(node);
2363     if (mp->is_ipv6) {
2364         clib_memcpy(&ip6, mp->ip_address, sizeof(ip6));
2365         vat_json_object_add_ip6(node, "map resolver", ip6);
2366     } else {
2367         clib_memcpy(&ip4, mp->ip_address, sizeof(ip4));
2368         vat_json_object_add_ip4(node, "map resolver", ip4);
2369     }
2370 }
2371
2372 static void
2373 vl_api_show_lisp_status_reply_t_handler
2374 (vl_api_show_lisp_status_reply_t * mp)
2375 {
2376     vat_main_t *vam = &vat_main;
2377     i32 retval = ntohl(mp->retval);
2378
2379     if (0 <= retval) {
2380       fformat(vam->ofp, "feature: %s\ngpe: %s\n",
2381               mp->feature_status ? "enabled" : "disabled",
2382               mp->gpe_status ? "enabled" : "disabled");
2383     }
2384
2385     vam->retval = retval;
2386     vam->result_ready = 1;
2387 }
2388
2389 static void
2390 vl_api_show_lisp_status_reply_t_handler_json
2391 (vl_api_show_lisp_status_reply_t *mp)
2392 {
2393     vat_main_t *vam = &vat_main;
2394     vat_json_node_t node;
2395     u8 * gpe_status = NULL;
2396     u8 * feature_status = NULL;
2397
2398     gpe_status = format (0, "%s", mp->gpe_status ? "enabled" : "disabled");
2399     feature_status = format (0, "%s",
2400                             mp->feature_status ? "enabled" : "disabled");
2401     vec_add1 (gpe_status, 0);
2402     vec_add1 (feature_status, 0);
2403
2404     vat_json_init_object(&node);
2405     vat_json_object_add_string_copy(&node, "gpe_status", gpe_status);
2406     vat_json_object_add_string_copy(&node, "feature_status", feature_status);
2407
2408     vec_free (gpe_status);
2409     vec_free (feature_status);
2410
2411     vat_json_print(vam->ofp, &node);
2412     vat_json_free(&node);
2413
2414     vam->retval = ntohl(mp->retval);
2415     vam->result_ready = 1;
2416 }
2417
2418 static void
2419 vl_api_lisp_get_map_request_itr_rlocs_reply_t_handler (
2420     vl_api_lisp_get_map_request_itr_rlocs_reply_t * mp)
2421 {
2422     vat_main_t * vam = &vat_main;
2423     i32 retval = ntohl(mp->retval);
2424
2425     if (retval >= 0) {
2426       fformat(vam->ofp, "%=20s\n",
2427               mp->locator_set_name);
2428     }
2429
2430     vam->retval = retval;
2431     vam->result_ready = 1;
2432 }
2433
2434 static void
2435 vl_api_lisp_get_map_request_itr_rlocs_reply_t_handler_json (
2436     vl_api_lisp_get_map_request_itr_rlocs_reply_t * mp)
2437 {
2438     vat_main_t * vam = &vat_main;
2439     vat_json_node_t * node = NULL;
2440
2441     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2442         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2443         vat_json_init_array(&vam->json_tree);
2444     }
2445     node = vat_json_array_add(&vam->json_tree);
2446
2447     vat_json_init_object(node);
2448     vat_json_object_add_string_copy(node, "itr-rlocs", mp->locator_set_name);
2449
2450     vat_json_print(vam->ofp, node);
2451     vat_json_free(node);
2452
2453     vam->retval = ntohl(mp->retval);
2454     vam->result_ready = 1;
2455 }
2456
2457 static void
2458 vl_api_show_lisp_pitr_reply_t_handler (vl_api_show_lisp_pitr_reply_t * mp)
2459 {
2460     vat_main_t *vam = &vat_main;
2461     i32 retval = ntohl(mp->retval);
2462
2463     if (0 <= retval) {
2464       fformat(vam->ofp, "%-20s%-16s\n",
2465               mp->status ? "enabled" : "disabled",
2466               mp->status ? (char *) mp->locator_set_name : "");
2467     }
2468
2469     vam->retval = retval;
2470     vam->result_ready = 1;
2471 }
2472
2473 static void
2474 vl_api_show_lisp_pitr_reply_t_handler_json (vl_api_show_lisp_pitr_reply_t * mp)
2475 {
2476     vat_main_t *vam = &vat_main;
2477     vat_json_node_t node;
2478     u8 * status = 0;
2479
2480     status = format (0, "%s", mp->status ? "enabled" : "disabled");
2481     vec_add1 (status, 0);
2482
2483     vat_json_init_object(&node);
2484     vat_json_object_add_string_copy(&node, "status", status);
2485     if (mp->status) {
2486       vat_json_object_add_string_copy(&node, "locator_set", mp->locator_set_name);
2487     }
2488
2489     vec_free (status);
2490
2491     vat_json_print(vam->ofp, &node);
2492     vat_json_free(&node);
2493
2494     vam->retval = ntohl(mp->retval);
2495     vam->result_ready = 1;
2496 }
2497
2498 static u8 * format_policer_type (u8 * s, va_list * va)
2499 {
2500     u32 i = va_arg (*va, u32);
2501
2502     if (i == SSE2_QOS_POLICER_TYPE_1R2C)
2503         s = format (s, "1r2c");
2504     else if (i == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
2505         s = format (s, "1r3c");
2506     else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698)
2507         s = format (s, "2r3c-2698");
2508     else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
2509         s = format (s, "2r3c-4115");
2510     else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
2511         s = format (s, "2r3c-mef5cf1");
2512     else
2513         s = format (s, "ILLEGAL");
2514     return s;
2515 }
2516
2517 static u8 * format_policer_rate_type (u8 * s, va_list * va)
2518 {
2519     u32 i = va_arg (*va, u32);
2520
2521     if (i == SSE2_QOS_RATE_KBPS)
2522         s = format (s, "kbps");
2523     else if (i == SSE2_QOS_RATE_PPS)
2524         s = format(s, "pps");
2525     else
2526         s = format (s, "ILLEGAL");
2527     return s;
2528 }
2529
2530 static u8 * format_policer_round_type (u8 * s, va_list * va)
2531 {
2532     u32 i = va_arg (*va, u32);
2533
2534     if (i == SSE2_QOS_ROUND_TO_CLOSEST)
2535         s = format(s, "closest");
2536     else if (i == SSE2_QOS_ROUND_TO_UP)
2537         s = format (s, "up");
2538     else if (i == SSE2_QOS_ROUND_TO_DOWN)
2539         s = format (s, "down");
2540     else
2541         s = format (s, "ILLEGAL");
2542   return s;
2543 }
2544
2545 static u8 * format_policer_action_type (u8 * s, va_list * va)
2546 {
2547     u32 i = va_arg (*va, u32);
2548
2549     if (i == SSE2_QOS_ACTION_DROP)
2550         s = format (s, "drop");
2551     else if (i == SSE2_QOS_ACTION_TRANSMIT)
2552         s = format (s, "transmit");
2553     else if (i == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
2554         s = format (s, "mark-and-transmit");
2555     else
2556         s = format (s, "ILLEGAL");
2557     return s;
2558 }
2559
2560 static u8 * format_dscp (u8 * s, va_list * va)
2561 {
2562   u32 i = va_arg (*va, u32);
2563   char * t = 0;
2564
2565   switch (i) {
2566   #define _(v,f,str) case VNET_DSCP_##f: t = str; break;
2567     foreach_vnet_dscp
2568   #undef _
2569     default:
2570       return format (s, "ILLEGAL");
2571   }
2572   s = format (s, "%s", t);
2573   return s;
2574 }
2575
2576 static void vl_api_policer_details_t_handler
2577 (vl_api_policer_details_t * mp)
2578 {
2579     vat_main_t * vam = &vat_main;
2580     u8 *conform_dscp_str, *exceed_dscp_str, *violate_dscp_str;
2581
2582     if (mp->conform_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
2583         conform_dscp_str = format(0, "%U", format_dscp, mp->conform_dscp);
2584     else
2585         conform_dscp_str = format(0, "");
2586
2587     if (mp->exceed_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
2588         exceed_dscp_str = format(0, "%U", format_dscp, mp->exceed_dscp);
2589     else
2590         exceed_dscp_str = format(0, "");
2591
2592     if (mp->violate_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT)
2593         violate_dscp_str = format(0, "%U", format_dscp, mp->violate_dscp);
2594     else
2595         violate_dscp_str = format(0, "");
2596
2597     fformat (vam->ofp, "Name \"%s\", type %U, cir %u, eir %u, cb %u, eb %u, "
2598              "rate type %U, round type %U, %s rate, %s color-aware, "
2599              "cir %u tok/period, pir %u tok/period, scale %u, cur lim %u, "
2600              "cur bkt %u, ext lim %u, ext bkt %u, last update %llu"
2601              "conform action %U%s, exceed action %U%s, violate action %U%s\n",
2602              mp->name,
2603              format_policer_type, mp->type,
2604              ntohl(mp->cir),
2605              ntohl(mp->eir),
2606              clib_net_to_host_u64(mp->cb),
2607              clib_net_to_host_u64(mp->eb),
2608              format_policer_rate_type, mp->rate_type,
2609              format_policer_round_type, mp->round_type,
2610              mp->single_rate ? "single" : "dual",
2611              mp->color_aware ? "is" : "not",
2612              ntohl(mp->cir_tokens_per_period),
2613              ntohl(mp->pir_tokens_per_period),
2614              ntohl(mp->scale),
2615              ntohl(mp->current_limit),
2616              ntohl(mp->current_bucket),
2617              ntohl(mp->extended_limit),
2618              ntohl(mp->extended_bucket),
2619              clib_net_to_host_u64(mp->last_update_time),
2620              format_policer_action_type, mp->conform_action_type,
2621              conform_dscp_str,
2622              format_policer_action_type, mp->exceed_action_type,
2623              exceed_dscp_str,
2624              format_policer_action_type, mp->violate_action_type,
2625              violate_dscp_str);
2626
2627     vec_free(conform_dscp_str);
2628     vec_free(exceed_dscp_str);
2629     vec_free(violate_dscp_str);
2630 }
2631
2632 static void vl_api_policer_details_t_handler_json
2633 (vl_api_policer_details_t * mp)
2634 {
2635     vat_main_t * vam = &vat_main;
2636     vat_json_node_t *node;
2637     u8 *rate_type_str, *round_type_str, *type_str;
2638     u8 *conform_action_str, *exceed_action_str, *violate_action_str;
2639
2640     rate_type_str = format(0, "%U", format_policer_rate_type, mp->rate_type);
2641     round_type_str = format(0, "%U", format_policer_round_type, mp->round_type);
2642     type_str = format(0, "%U", format_policer_type, mp->type);
2643     conform_action_str = format(0, "%U", format_policer_action_type,
2644                                 mp->conform_action_type);
2645     exceed_action_str = format(0, "%U", format_policer_action_type,
2646                                 mp->exceed_action_type);
2647     violate_action_str = format(0, "%U", format_policer_action_type,
2648                                 mp->violate_action_type);
2649
2650     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2651         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2652         vat_json_init_array(&vam->json_tree);
2653     }
2654     node = vat_json_array_add(&vam->json_tree);
2655
2656     vat_json_init_object(node);
2657     vat_json_object_add_string_copy(node, "name", mp->name);
2658     vat_json_object_add_uint(node, "cir", ntohl(mp->cir));
2659     vat_json_object_add_uint(node, "eir", ntohl(mp->eir));
2660     vat_json_object_add_uint(node, "cb", ntohl(mp->cb));
2661     vat_json_object_add_uint(node, "eb", ntohl(mp->eb));
2662     vat_json_object_add_string_copy(node, "rate_type", rate_type_str);
2663     vat_json_object_add_string_copy(node, "round_type", round_type_str);
2664     vat_json_object_add_string_copy(node, "type", type_str);
2665     vat_json_object_add_uint(node, "single_rate", mp->single_rate);
2666     vat_json_object_add_uint(node, "color_aware", mp->color_aware);
2667     vat_json_object_add_uint(node, "scale", ntohl(mp->scale));
2668     vat_json_object_add_uint(node, "cir_tokens_per_period",
2669                              ntohl(mp->cir_tokens_per_period));
2670     vat_json_object_add_uint(node, "eir_tokens_per_period",
2671                              ntohl(mp->pir_tokens_per_period));
2672     vat_json_object_add_uint(node, "current_limit", ntohl(mp->current_limit));
2673     vat_json_object_add_uint(node, "current_bucket", ntohl(mp->current_bucket));
2674     vat_json_object_add_uint(node, "extended_limit", ntohl(mp->extended_limit));
2675     vat_json_object_add_uint(node, "extended_bucket",
2676                              ntohl(mp->extended_bucket));
2677     vat_json_object_add_uint(node, "last_update_time",
2678                              ntohl(mp->last_update_time));
2679     vat_json_object_add_string_copy(node, "conform_action", conform_action_str);
2680     if (mp->conform_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) {
2681         u8 *dscp_str = format(0, "%U", format_dscp, mp->conform_dscp);
2682         vat_json_object_add_string_copy(node, "conform_dscp", dscp_str);
2683         vec_free(dscp_str);
2684     }
2685     vat_json_object_add_string_copy(node, "exceed_action", exceed_action_str);
2686     if (mp->exceed_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) {
2687         u8 *dscp_str = format(0, "%U", format_dscp, mp->exceed_dscp);
2688         vat_json_object_add_string_copy(node, "exceed_dscp", dscp_str);
2689         vec_free(dscp_str);
2690     }
2691     vat_json_object_add_string_copy(node, "violate_action", violate_action_str);
2692     if (mp->violate_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) {
2693         u8 *dscp_str = format(0, "%U", format_dscp, mp->violate_dscp);
2694         vat_json_object_add_string_copy(node, "violate_dscp", dscp_str);
2695         vec_free(dscp_str);
2696     }
2697
2698     vec_free(rate_type_str);
2699     vec_free(round_type_str);
2700     vec_free(type_str);
2701     vec_free(conform_action_str);
2702     vec_free(exceed_action_str);
2703     vec_free(violate_action_str);
2704 }
2705
2706 static void vl_api_classify_table_ids_reply_t_handler (vl_api_classify_table_ids_reply_t * mp)
2707 {
2708     vat_main_t * vam = &vat_main;
2709     int i, count = ntohl(mp->count);
2710
2711     if (count>0)
2712         fformat (vam->ofp, "classify table ids (%d) : ", count);
2713     for (i = 0; i < count; i++)
2714     {
2715         fformat (vam->ofp, "%d", ntohl(mp->ids[i]));
2716         fformat (vam->ofp, (i<count-1)?",":"\n");
2717     }
2718     vam->retval = ntohl(mp->retval);
2719     vam->result_ready = 1;
2720 }
2721
2722 static void vl_api_classify_table_ids_reply_t_handler_json (vl_api_classify_table_ids_reply_t * mp)
2723 {
2724     vat_main_t * vam = &vat_main;
2725     int i, count = ntohl(mp->count);
2726
2727     if (count>0) {
2728         vat_json_node_t node;
2729
2730         vat_json_init_object(&node);
2731             for (i = 0; i < count; i++)
2732             {
2733                 vat_json_object_add_uint(&node, "table_id", ntohl(mp->ids[i]));
2734             }
2735             vat_json_print(vam->ofp, &node);
2736             vat_json_free(&node);
2737     }
2738     vam->retval = ntohl(mp->retval);
2739     vam->result_ready = 1;
2740 }
2741
2742 static void vl_api_classify_table_by_interface_reply_t_handler (vl_api_classify_table_by_interface_reply_t * mp)
2743 {
2744     vat_main_t * vam = &vat_main;
2745     u32 table_id;
2746
2747     table_id = ntohl(mp->l2_table_id);
2748     if (table_id != ~0)
2749         fformat (vam->ofp, "l2 table id : %d\n", table_id);
2750     else
2751         fformat (vam->ofp, "l2 table id : No input ACL tables configured\n");
2752     table_id = ntohl(mp->ip4_table_id);
2753     if (table_id != ~0)
2754         fformat (vam->ofp, "ip4 table id : %d\n", table_id);
2755     else
2756         fformat (vam->ofp, "ip4 table id : No input ACL tables configured\n");
2757     table_id = ntohl(mp->ip6_table_id);
2758     if (table_id != ~0)
2759         fformat (vam->ofp, "ip6 table id : %d\n", table_id);
2760     else
2761         fformat (vam->ofp, "ip6 table id : No input ACL tables configured\n");
2762     vam->retval = ntohl(mp->retval);
2763     vam->result_ready = 1;
2764 }
2765
2766 static void vl_api_classify_table_by_interface_reply_t_handler_json (vl_api_classify_table_by_interface_reply_t * mp)
2767 {
2768     vat_main_t * vam = &vat_main;
2769     vat_json_node_t node;
2770
2771     vat_json_init_object(&node);
2772
2773     vat_json_object_add_int(&node, "l2_table_id", ntohl(mp->l2_table_id));
2774     vat_json_object_add_int(&node, "ip4_table_id", ntohl(mp->ip4_table_id));
2775     vat_json_object_add_int(&node, "ip6_table_id", ntohl(mp->ip6_table_id));
2776
2777     vat_json_print(vam->ofp, &node);
2778     vat_json_free(&node);
2779
2780     vam->retval = ntohl(mp->retval);
2781     vam->result_ready = 1;
2782 }
2783
2784 static void vl_api_policer_add_del_reply_t_handler
2785 (vl_api_policer_add_del_reply_t * mp)
2786 {
2787     vat_main_t * vam = &vat_main;
2788     i32 retval = ntohl(mp->retval);
2789     if (vam->async_mode) {
2790         vam->async_errors += (retval < 0);
2791     } else {
2792         vam->retval = retval;
2793         vam->result_ready = 1;
2794         if (retval == 0 && mp->policer_index != 0xFFFFFFFF)
2795             /*
2796              * Note: this is just barely thread-safe, depends on
2797              * the main thread spinning waiting for an answer...
2798              */
2799             errmsg ("policer index %d\n", ntohl(mp->policer_index));
2800     }
2801 }
2802
2803 static void vl_api_policer_add_del_reply_t_handler_json
2804 (vl_api_policer_add_del_reply_t * mp)
2805 {
2806     vat_main_t * vam = &vat_main;
2807     vat_json_node_t node;
2808
2809     vat_json_init_object(&node);
2810     vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
2811     vat_json_object_add_uint(&node, "policer_index", ntohl(mp->policer_index));
2812
2813     vat_json_print(vam->ofp, &node);
2814     vat_json_free(&node);
2815
2816     vam->retval = ntohl(mp->retval);
2817     vam->result_ready = 1;
2818 }
2819
2820 /* Format hex dump. */
2821 u8 * format_hex_bytes (u8 * s, va_list * va)
2822 {
2823     u8 * bytes = va_arg (*va, u8 *);
2824     int n_bytes = va_arg (*va, int);
2825     uword i;
2826
2827     /* Print short or long form depending on byte count. */
2828     uword short_form = n_bytes <= 32;
2829     uword indent = format_get_indent (s);
2830
2831     if (n_bytes == 0)
2832         return s;
2833
2834     for (i = 0; i < n_bytes; i++)
2835     {
2836         if (! short_form && (i % 32) == 0)
2837             s = format (s, "%08x: ", i);
2838         s = format (s, "%02x", bytes[i]);
2839         if (! short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
2840             s = format (s, "\n%U", format_white_space, indent);
2841     }
2842
2843     return s;
2844 }
2845
2846 static void vl_api_classify_table_info_reply_t_handler (vl_api_classify_table_info_reply_t * mp)
2847 {
2848     vat_main_t * vam = &vat_main;
2849     i32 retval = ntohl(mp->retval);
2850     if (retval == 0) {
2851         fformat (vam->ofp, "classify table info :\n");
2852         fformat (vam->ofp, "sessions: %d nexttbl: %d nextnode: %d\n", ntohl(mp->active_sessions), ntohl(mp->next_table_index), ntohl(mp->miss_next_index));
2853         fformat (vam->ofp, "nbuckets: %d skip: %d match: %d\n", ntohl(mp->nbuckets), ntohl(mp->skip_n_vectors), ntohl(mp->match_n_vectors));
2854         fformat (vam->ofp, "mask: %U\n", format_hex_bytes, mp->mask, ntohl(mp->mask_length));
2855     }
2856     vam->retval = retval;
2857     vam->result_ready = 1;
2858 }
2859
2860 static void vl_api_classify_table_info_reply_t_handler_json (vl_api_classify_table_info_reply_t * mp)
2861 {
2862     vat_main_t * vam = &vat_main;
2863     vat_json_node_t node;
2864
2865     i32 retval = ntohl(mp->retval);
2866     if (retval == 0) {
2867         vat_json_init_object(&node);
2868
2869         vat_json_object_add_int(&node, "sessions", ntohl(mp->active_sessions));
2870         vat_json_object_add_int(&node, "nexttbl", ntohl(mp->next_table_index));
2871         vat_json_object_add_int(&node, "nextnode", ntohl(mp->miss_next_index));
2872         vat_json_object_add_int(&node, "nbuckets", ntohl(mp->nbuckets));
2873         vat_json_object_add_int(&node, "skip", ntohl(mp->skip_n_vectors));
2874         vat_json_object_add_int(&node, "match", ntohl(mp->match_n_vectors));
2875         u8 * s = format (0, "%U%c",format_hex_bytes, mp->mask, ntohl(mp->mask_length), 0);
2876         vat_json_object_add_string_copy(&node, "mask", s);
2877
2878         vat_json_print(vam->ofp, &node);
2879         vat_json_free(&node);
2880     }
2881     vam->retval = ntohl(mp->retval);
2882     vam->result_ready = 1;
2883 }
2884
2885 static void vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t * mp)
2886 {
2887     vat_main_t * vam = &vat_main;
2888
2889     fformat (vam->ofp, "next_index: %d advance: %d opaque: %d ", ntohl(mp->hit_next_index), ntohl(mp->advance), ntohl(mp->opaque_index));
2890     fformat (vam->ofp, "mask: %U\n", format_hex_bytes, mp->match, ntohl(mp->match_length));
2891 }
2892
2893 static void vl_api_classify_session_details_t_handler_json (vl_api_classify_session_details_t * mp)
2894 {
2895     vat_main_t * vam = &vat_main;
2896     vat_json_node_t *node = NULL;
2897
2898     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2899         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2900         vat_json_init_array(&vam->json_tree);
2901     }
2902     node = vat_json_array_add(&vam->json_tree);
2903
2904     vat_json_init_object(node);
2905     vat_json_object_add_int(node, "next_index", ntohl(mp->hit_next_index));
2906     vat_json_object_add_int(node, "advance", ntohl(mp->advance));
2907     vat_json_object_add_int(node, "opaque", ntohl(mp->opaque_index));
2908     u8 * s = format (0, "%U%c",format_hex_bytes, mp->match, ntohl(mp->match_length), 0);
2909     vat_json_object_add_string_copy(node, "match", s);
2910 }
2911
2912 static void vl_api_pg_create_interface_reply_t_handler
2913 (vl_api_pg_create_interface_reply_t * mp)
2914 {
2915     vat_main_t * vam = &vat_main;
2916
2917     vam->retval = ntohl(mp->retval);
2918     vam->result_ready = 1;
2919 }
2920
2921 static void vl_api_pg_create_interface_reply_t_handler_json
2922 (vl_api_pg_create_interface_reply_t * mp)
2923 {
2924     vat_main_t * vam = &vat_main;
2925     vat_json_node_t node;
2926
2927     i32 retval = ntohl(mp->retval);
2928     if (retval == 0) {
2929         vat_json_init_object(&node);
2930
2931         vat_json_object_add_int(&node, "sw_if_index", ntohl(mp->sw_if_index));
2932
2933         vat_json_print(vam->ofp, &node);
2934         vat_json_free(&node);
2935     }
2936     vam->retval = ntohl(mp->retval);
2937     vam->result_ready = 1;
2938 }
2939
2940 static void vl_api_policer_classify_details_t_handler
2941 (vl_api_policer_classify_details_t * mp)
2942 {
2943     vat_main_t * vam = &vat_main;
2944
2945     fformat (vam->ofp, "%10d%20d\n", ntohl(mp->sw_if_index),
2946              ntohl(mp->table_index));
2947 }
2948
2949 static void vl_api_policer_classify_details_t_handler_json
2950 (vl_api_policer_classify_details_t * mp)
2951 {
2952     vat_main_t * vam = &vat_main;
2953     vat_json_node_t * node;
2954
2955     if (VAT_JSON_ARRAY != vam->json_tree.type) {
2956         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
2957         vat_json_init_array(&vam->json_tree);
2958     }
2959     node = vat_json_array_add(&vam->json_tree);
2960
2961     vat_json_init_object(node);
2962     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
2963     vat_json_object_add_uint(node, "table_index", ntohl(mp->table_index));
2964 }
2965
2966
2967 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
2968 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
2969 #define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
2970 #define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
2971
2972 /*
2973  * Generate boilerplate reply handlers, which
2974  * dig the return value out of the xxx_reply_t API message,
2975  * stick it into vam->retval, and set vam->result_ready
2976  *
2977  * Could also do this by pointing N message decode slots at
2978  * a single function, but that could break in subtle ways.
2979  */
2980
2981 #define foreach_standard_reply_retval_handler           \
2982 _(sw_interface_set_flags_reply)                         \
2983 _(sw_interface_add_del_address_reply)                   \
2984 _(sw_interface_set_table_reply)                         \
2985 _(sw_interface_set_vpath_reply)                         \
2986 _(sw_interface_set_l2_bridge_reply)                     \
2987 _(bridge_domain_add_del_reply)                          \
2988 _(sw_interface_set_l2_xconnect_reply)                   \
2989 _(l2fib_add_del_reply)                                  \
2990 _(ip_add_del_route_reply)                               \
2991 _(proxy_arp_add_del_reply)                              \
2992 _(proxy_arp_intfc_enable_disable_reply)                 \
2993 _(mpls_add_del_encap_reply)                             \
2994 _(mpls_add_del_decap_reply)                             \
2995 _(mpls_ethernet_add_del_tunnel_2_reply)                 \
2996 _(sw_interface_set_unnumbered_reply)                    \
2997 _(ip_neighbor_add_del_reply)                            \
2998 _(reset_vrf_reply)                                      \
2999 _(oam_add_del_reply)                                    \
3000 _(reset_fib_reply)                                      \
3001 _(dhcp_proxy_config_reply)                              \
3002 _(dhcp_proxy_config_2_reply)                            \
3003 _(dhcp_proxy_set_vss_reply)                             \
3004 _(dhcp_client_config_reply)                             \
3005 _(set_ip_flow_hash_reply)                               \
3006 _(sw_interface_ip6_enable_disable_reply)                \
3007 _(sw_interface_ip6_set_link_local_address_reply)        \
3008 _(sw_interface_ip6nd_ra_prefix_reply)                   \
3009 _(sw_interface_ip6nd_ra_config_reply)                   \
3010 _(set_arp_neighbor_limit_reply)                         \
3011 _(l2_patch_add_del_reply)                               \
3012 _(sr_tunnel_add_del_reply)                              \
3013 _(sr_policy_add_del_reply)                              \
3014 _(sr_multicast_map_add_del_reply)                       \
3015 _(classify_add_del_session_reply)                       \
3016 _(classify_set_interface_ip_table_reply)                \
3017 _(classify_set_interface_l2_tables_reply)               \
3018 _(l2tpv3_set_tunnel_cookies_reply)                      \
3019 _(l2tpv3_interface_enable_disable_reply)                \
3020 _(l2tpv3_set_lookup_key_reply)                          \
3021 _(l2_fib_clear_table_reply)                             \
3022 _(l2_interface_efp_filter_reply)                        \
3023 _(l2_interface_vlan_tag_rewrite_reply)                  \
3024 _(modify_vhost_user_if_reply)                           \
3025 _(delete_vhost_user_if_reply)                           \
3026 _(want_ip4_arp_events_reply)                            \
3027 _(input_acl_set_interface_reply)                        \
3028 _(ipsec_spd_add_del_reply)                              \
3029 _(ipsec_interface_add_del_spd_reply)                    \
3030 _(ipsec_spd_add_del_entry_reply)                        \
3031 _(ipsec_sad_add_del_entry_reply)                        \
3032 _(ipsec_sa_set_key_reply)                               \
3033 _(ikev2_profile_add_del_reply)                          \
3034 _(ikev2_profile_set_auth_reply)                         \
3035 _(ikev2_profile_set_id_reply)                           \
3036 _(ikev2_profile_set_ts_reply)                           \
3037 _(ikev2_set_local_key_reply)                            \
3038 _(delete_loopback_reply)                                \
3039 _(bd_ip_mac_add_del_reply)                              \
3040 _(map_del_domain_reply)                                 \
3041 _(map_add_del_rule_reply)                               \
3042 _(want_interface_events_reply)                          \
3043 _(want_stats_reply)                                     \
3044 _(cop_interface_enable_disable_reply)                   \
3045 _(cop_whitelist_enable_disable_reply)                   \
3046 _(sw_interface_clear_stats_reply)                       \
3047 _(trace_profile_add_reply)                              \
3048 _(trace_profile_apply_reply)                            \
3049 _(trace_profile_del_reply)                              \
3050 _(lisp_add_del_locator_set_reply)                       \
3051 _(lisp_add_del_locator_reply)                           \
3052 _(lisp_add_del_local_eid_reply)                         \
3053 _(lisp_add_del_remote_mapping_reply)                    \
3054 _(lisp_add_del_adjacency_reply)                         \
3055 _(lisp_gpe_add_del_fwd_entry_reply)                     \
3056 _(lisp_add_del_map_resolver_reply)                      \
3057 _(lisp_gpe_enable_disable_reply)                        \
3058 _(lisp_gpe_add_del_iface_reply)                         \
3059 _(lisp_enable_disable_reply)                            \
3060 _(lisp_pitr_set_locator_set_reply)                      \
3061 _(lisp_add_del_map_request_itr_rlocs_reply)             \
3062 _(lisp_eid_table_add_del_map_reply)                     \
3063 _(vxlan_gpe_add_del_tunnel_reply)                       \
3064 _(af_packet_delete_reply)                               \
3065 _(policer_classify_set_interface_reply)                 \
3066 _(netmap_create_reply)                                  \
3067 _(netmap_delete_reply)                                  \
3068 _(ipfix_enable_reply)                                   \
3069 _(pg_capture_reply)                                     \
3070 _(pg_enable_disable_reply)                              \
3071 _(ip_source_and_port_range_check_add_del_reply)         \
3072 _(ip_source_and_port_range_check_interface_add_del_reply)
3073
3074 #define _(n)                                    \
3075     static void vl_api_##n##_t_handler          \
3076     (vl_api_##n##_t * mp)                       \
3077     {                                           \
3078         vat_main_t * vam = &vat_main;           \
3079         i32 retval = ntohl(mp->retval);         \
3080         if (vam->async_mode) {                  \
3081             vam->async_errors += (retval < 0);  \
3082         } else {                                \
3083             vam->retval = retval;               \
3084             vam->result_ready = 1;              \
3085         }                                       \
3086     }
3087 foreach_standard_reply_retval_handler;
3088 #undef _
3089
3090 #define _(n)                                    \
3091     static void vl_api_##n##_t_handler_json     \
3092     (vl_api_##n##_t * mp)                       \
3093     {                                           \
3094         vat_main_t * vam = &vat_main;           \
3095         vat_json_node_t node;                   \
3096         vat_json_init_object(&node);            \
3097         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
3098         vat_json_print(vam->ofp, &node);        \
3099         vam->retval = ntohl(mp->retval);        \
3100         vam->result_ready = 1;                  \
3101     }
3102 foreach_standard_reply_retval_handler;
3103 #undef _
3104
3105 /*
3106  * Table of message reply handlers, must include boilerplate handlers
3107  * we just generated
3108  */
3109
3110 #define foreach_vpe_api_reply_msg                                       \
3111 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
3112 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
3113 _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags)                       \
3114 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
3115 _(CONTROL_PING_REPLY, control_ping_reply)                               \
3116 _(NOPRINT_CONTROL_PING_REPLY, noprint_control_ping_reply)               \
3117 _(CLI_REPLY, cli_reply)                                                 \
3118 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
3119   sw_interface_add_del_address_reply)                                   \
3120 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
3121 _(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply)           \
3122 _(SW_INTERFACE_SET_L2_XCONNECT_REPLY,                                   \
3123   sw_interface_set_l2_xconnect_reply)                                   \
3124 _(SW_INTERFACE_SET_L2_BRIDGE_REPLY,                                     \
3125   sw_interface_set_l2_bridge_reply)                                     \
3126 _(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply)             \
3127 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
3128 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
3129 _(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply)                             \
3130 _(L2_FLAGS_REPLY, l2_flags_reply)                                       \
3131 _(BRIDGE_FLAGS_REPLY, bridge_flags_reply)                               \
3132 _(TAP_CONNECT_REPLY, tap_connect_reply)                                 \
3133 _(TAP_MODIFY_REPLY, tap_modify_reply)                                   \
3134 _(TAP_DELETE_REPLY, tap_delete_reply)                                   \
3135 _(SW_INTERFACE_TAP_DETAILS, sw_interface_tap_details)                   \
3136 _(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply)                       \
3137 _(PROXY_ARP_ADD_DEL_REPLY, proxy_arp_add_del_reply)                     \
3138 _(PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY,                                 \
3139   proxy_arp_intfc_enable_disable_reply)                                 \
3140 _(MPLS_ADD_DEL_ENCAP_REPLY, mpls_add_del_encap_reply)                   \
3141 _(MPLS_ADD_DEL_DECAP_REPLY, mpls_add_del_decap_reply)                   \
3142 _(MPLS_GRE_ADD_DEL_TUNNEL_REPLY, mpls_gre_add_del_tunnel_reply)         \
3143 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,                                   \
3144   mpls_ethernet_add_del_tunnel_reply)                                   \
3145 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY,                                 \
3146   mpls_ethernet_add_del_tunnel_2_reply)                                 \
3147 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
3148   sw_interface_set_unnumbered_reply)                                    \
3149 _(IP_NEIGHBOR_ADD_DEL_REPLY, ip_neighbor_add_del_reply)                 \
3150 _(RESET_VRF_REPLY, reset_vrf_reply)                                     \
3151 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
3152 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
3153 _(OAM_ADD_DEL_REPLY, oam_add_del_reply)                                 \
3154 _(RESET_FIB_REPLY, reset_fib_reply)                                     \
3155 _(DHCP_PROXY_CONFIG_REPLY, dhcp_proxy_config_reply)                     \
3156 _(DHCP_PROXY_CONFIG_2_REPLY, dhcp_proxy_config_2_reply)                 \
3157 _(DHCP_PROXY_SET_VSS_REPLY, dhcp_proxy_set_vss_reply)                   \
3158 _(DHCP_CLIENT_CONFIG_REPLY, dhcp_client_config_reply)                   \
3159 _(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply)                       \
3160 _(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY,                                \
3161   sw_interface_ip6_enable_disable_reply)                                \
3162 _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY,                        \
3163   sw_interface_ip6_set_link_local_address_reply)                        \
3164 _(SW_INTERFACE_IP6ND_RA_PREFIX_REPLY,                                   \
3165   sw_interface_ip6nd_ra_prefix_reply)                                   \
3166 _(SW_INTERFACE_IP6ND_RA_CONFIG_REPLY,                                   \
3167   sw_interface_ip6nd_ra_config_reply)                                   \
3168 _(SET_ARP_NEIGHBOR_LIMIT_REPLY, set_arp_neighbor_limit_reply)           \
3169 _(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply)                       \
3170 _(SR_TUNNEL_ADD_DEL_REPLY, sr_tunnel_add_del_reply)                     \
3171 _(SR_POLICY_ADD_DEL_REPLY, sr_policy_add_del_reply)                     \
3172 _(SR_MULTICAST_MAP_ADD_DEL_REPLY, sr_multicast_map_add_del_reply)                     \
3173 _(CLASSIFY_ADD_DEL_TABLE_REPLY, classify_add_del_table_reply)           \
3174 _(CLASSIFY_ADD_DEL_SESSION_REPLY, classify_add_del_session_reply)       \
3175 _(CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY,                                \
3176 classify_set_interface_ip_table_reply)                                  \
3177 _(CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY,                               \
3178   classify_set_interface_l2_tables_reply)                               \
3179 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
3180 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
3181 _(L2TPV3_CREATE_TUNNEL_REPLY, l2tpv3_create_tunnel_reply)               \
3182 _(L2TPV3_SET_TUNNEL_COOKIES_REPLY, l2tpv3_set_tunnel_cookies_reply)     \
3183 _(L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY,                                \
3184   l2tpv3_interface_enable_disable_reply)                                \
3185 _(L2TPV3_SET_LOOKUP_KEY_REPLY, l2tpv3_set_lookup_key_reply)             \
3186 _(SW_IF_L2TPV3_TUNNEL_DETAILS, sw_if_l2tpv3_tunnel_details)             \
3187 _(VXLAN_ADD_DEL_TUNNEL_REPLY, vxlan_add_del_tunnel_reply)               \
3188 _(VXLAN_TUNNEL_DETAILS, vxlan_tunnel_details)                           \
3189 _(GRE_ADD_DEL_TUNNEL_REPLY, gre_add_del_tunnel_reply)                   \
3190 _(GRE_TUNNEL_DETAILS, gre_tunnel_details)                               \
3191 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
3192 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
3193 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
3194 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
3195 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
3196 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
3197 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
3198 _(SHOW_VERSION_REPLY, show_version_reply)                               \
3199 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
3200 _(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply)           \
3201 _(VXLAN_GPE_TUNNEL_DETAILS, vxlan_gpe_tunnel_details)                   \
3202 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
3203 _(WANT_IP4_ARP_EVENTS_REPLY, want_ip4_arp_events_reply)                 \
3204 _(IP4_ARP_EVENT, ip4_arp_event)                                         \
3205 _(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply)         \
3206 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
3207 _(IP_DETAILS, ip_details)                                               \
3208 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
3209 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
3210 _(IPSEC_SPD_ADD_DEL_ENTRY_REPLY, ipsec_spd_add_del_entry_reply)         \
3211 _(IPSEC_SAD_ADD_DEL_ENTRY_REPLY, ipsec_sad_add_del_entry_reply)         \
3212 _(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply)                       \
3213 _(IKEV2_PROFILE_ADD_DEL_REPLY, ikev2_profile_add_del_reply)             \
3214 _(IKEV2_PROFILE_SET_AUTH_REPLY, ikev2_profile_set_auth_reply)           \
3215 _(IKEV2_PROFILE_SET_ID_REPLY, ikev2_profile_set_id_reply)               \
3216 _(IKEV2_PROFILE_SET_TS_REPLY, ikev2_profile_set_ts_reply)               \
3217 _(IKEV2_SET_LOCAL_KEY_REPLY, ikev2_set_local_key_reply)                 \
3218 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
3219 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
3220 _(DHCP_COMPL_EVENT, dhcp_compl_event)                                   \
3221 _(VNET_INTERFACE_COUNTERS, vnet_interface_counters)                     \
3222 _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters)                         \
3223 _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters)                         \
3224 _(MAP_ADD_DOMAIN_REPLY, map_add_domain_reply)                           \
3225 _(MAP_DEL_DOMAIN_REPLY, map_del_domain_reply)                           \
3226 _(MAP_ADD_DEL_RULE_REPLY, map_add_del_rule_reply)                       \
3227 _(MAP_DOMAIN_DETAILS, map_domain_details)                               \
3228 _(MAP_RULE_DETAILS, map_rule_details)                                   \
3229 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
3230 _(WANT_STATS_REPLY, want_stats_reply)                                   \
3231 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
3232 _(COP_INTERFACE_ENABLE_DISABLE_REPLY, cop_interface_enable_disable_reply) \
3233 _(COP_WHITELIST_ENABLE_DISABLE_REPLY, cop_whitelist_enable_disable_reply) \
3234 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
3235 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
3236 _(TRACE_PROFILE_ADD_REPLY, trace_profile_add_reply)                   \
3237 _(TRACE_PROFILE_APPLY_REPLY, trace_profile_apply_reply)               \
3238 _(TRACE_PROFILE_DEL_REPLY, trace_profile_del_reply)                     \
3239 _(LISP_ADD_DEL_LOCATOR_SET_REPLY, lisp_add_del_locator_set_reply)       \
3240 _(LISP_ADD_DEL_LOCATOR_REPLY, lisp_add_del_locator_reply)               \
3241 _(LISP_ADD_DEL_LOCAL_EID_REPLY, lisp_add_del_local_eid_reply)           \
3242 _(LISP_ADD_DEL_REMOTE_MAPPING_REPLY, lisp_add_del_remote_mapping_reply) \
3243 _(LISP_ADD_DEL_ADJACENCY_REPLY, lisp_add_del_adjacency_reply)           \
3244 _(LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY, lisp_gpe_add_del_fwd_entry_reply)   \
3245 _(LISP_ADD_DEL_MAP_RESOLVER_REPLY, lisp_add_del_map_resolver_reply)     \
3246 _(LISP_GPE_ENABLE_DISABLE_REPLY, lisp_gpe_enable_disable_reply)         \
3247 _(LISP_ENABLE_DISABLE_REPLY, lisp_enable_disable_reply)                 \
3248 _(LISP_PITR_SET_LOCATOR_SET_REPLY, lisp_pitr_set_locator_set_reply)     \
3249 _(LISP_EID_TABLE_ADD_DEL_MAP_REPLY, lisp_eid_table_add_del_map_reply)   \
3250 _(LISP_GPE_ADD_DEL_IFACE_REPLY, lisp_gpe_add_del_iface_reply)           \
3251 _(LISP_LOCATOR_SET_DETAILS, lisp_locator_set_details)                   \
3252 _(LISP_LOCATOR_DETAILS, lisp_locator_details)                           \
3253 _(LISP_EID_TABLE_DETAILS, lisp_eid_table_details)                       \
3254 _(LISP_EID_TABLE_MAP_DETAILS, lisp_eid_table_map_details)               \
3255 _(LISP_GPE_TUNNEL_DETAILS, lisp_gpe_tunnel_details)                     \
3256 _(LISP_MAP_RESOLVER_DETAILS, lisp_map_resolver_details)                 \
3257 _(SHOW_LISP_STATUS_REPLY, show_lisp_status_reply)                       \
3258 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY,                             \
3259   lisp_add_del_map_request_itr_rlocs_reply)                             \
3260 _(LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,                                 \
3261   lisp_get_map_request_itr_rlocs_reply)                                 \
3262 _(SHOW_LISP_PITR_REPLY, show_lisp_pitr_reply)                           \
3263 _(AF_PACKET_CREATE_REPLY, af_packet_create_reply)                       \
3264 _(AF_PACKET_DELETE_REPLY, af_packet_delete_reply)                       \
3265 _(POLICER_ADD_DEL_REPLY, policer_add_del_reply)                         \
3266 _(POLICER_DETAILS, policer_details)                                     \
3267 _(POLICER_CLASSIFY_SET_INTERFACE_REPLY, policer_classify_set_interface_reply) \
3268 _(POLICER_CLASSIFY_DETAILS, policer_classify_details)                   \
3269 _(NETMAP_CREATE_REPLY, netmap_create_reply)                             \
3270 _(NETMAP_DELETE_REPLY, netmap_delete_reply)                             \
3271 _(MPLS_GRE_TUNNEL_DETAILS, mpls_gre_tunnel_details)                     \
3272 _(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details)                     \
3273 _(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details)                       \
3274 _(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details)                       \
3275 _(CLASSIFY_TABLE_IDS_REPLY, classify_table_ids_reply)                   \
3276 _(CLASSIFY_TABLE_BY_INTERFACE_REPLY, classify_table_by_interface_reply) \
3277 _(CLASSIFY_TABLE_INFO_REPLY, classify_table_info_reply)                 \
3278 _(CLASSIFY_SESSION_DETAILS, classify_session_details)                   \
3279 _(IPFIX_ENABLE_REPLY, ipfix_enable_reply)                               \
3280 _(IPFIX_DETAILS, ipfix_details)                                         \
3281 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
3282 _(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply)                 \
3283 _(PG_CAPTURE_REPLY, pg_capture_reply)                                   \
3284 _(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply)                     \
3285 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY,                         \
3286  ip_source_and_port_range_check_add_del_reply)                          \
3287 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY,               \
3288  ip_source_and_port_range_check_interface_add_del_reply)
3289
3290 /* M: construct, but don't yet send a message */
3291
3292 #define M(T,t)                                  \
3293 do {                                            \
3294     vam->result_ready = 0;                      \
3295     mp = vl_msg_api_alloc(sizeof(*mp));         \
3296     memset (mp, 0, sizeof (*mp));               \
3297     mp->_vl_msg_id = ntohs (VL_API_##T);        \
3298     mp->client_index = vam->my_client_index;    \
3299 } while(0);
3300
3301 #define M2(T,t,n)                               \
3302 do {                                            \
3303     vam->result_ready = 0;                      \
3304     mp = vl_msg_api_alloc(sizeof(*mp)+(n));     \
3305     memset (mp, 0, sizeof (*mp));               \
3306     mp->_vl_msg_id = ntohs (VL_API_##T);        \
3307     mp->client_index = vam->my_client_index;    \
3308 } while(0);
3309
3310
3311 /* S: send a message */
3312 #define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp))
3313
3314 /* W: wait for results, with timeout */
3315 #define W                                       \
3316 do {                                            \
3317     timeout = vat_time_now (vam) + 1.0;         \
3318                                                 \
3319     while (vat_time_now (vam) < timeout) {      \
3320         if (vam->result_ready == 1) {           \
3321             return (vam->retval);               \
3322         }                                       \
3323     }                                           \
3324     return -99;                                 \
3325 } while(0);
3326
3327 /* W2: wait for results, with timeout */
3328 #define W2(body)                                \
3329 do {                                            \
3330     timeout = vat_time_now (vam) + 1.0;         \
3331                                                 \
3332     while (vat_time_now (vam) < timeout) {      \
3333         if (vam->result_ready == 1) {           \
3334           (body);                               \
3335           return (vam->retval);                 \
3336         }                                       \
3337     }                                           \
3338     return -99;                                 \
3339 } while(0);
3340
3341 /* W_L: wait for results, with timeout */
3342 #define W_L(body)                               \
3343 do {                                            \
3344     timeout = vat_time_now (vam) + 1.0;         \
3345                                                 \
3346     while (vat_time_now (vam) < timeout) {      \
3347         if (vam->result_ready == 1) {           \
3348           (body);                               \
3349           return (vam->retval);                 \
3350         }                                       \
3351     }                                           \
3352     vam->noprint_msg = 0;     \
3353     return -99;                                 \
3354 } while(0);
3355
3356 typedef struct {
3357     u8 * name;
3358     u32 value;
3359 } name_sort_t;
3360
3361
3362 #define STR_VTR_OP_CASE(op)     \
3363     case L2_VTR_ ## op:         \
3364         return "" # op;
3365
3366 static const char *str_vtr_op(u32 vtr_op)
3367 {
3368     switch(vtr_op) {
3369         STR_VTR_OP_CASE(DISABLED);
3370         STR_VTR_OP_CASE(PUSH_1);
3371         STR_VTR_OP_CASE(PUSH_2);
3372         STR_VTR_OP_CASE(POP_1);
3373         STR_VTR_OP_CASE(POP_2);
3374         STR_VTR_OP_CASE(TRANSLATE_1_1);
3375         STR_VTR_OP_CASE(TRANSLATE_1_2);
3376         STR_VTR_OP_CASE(TRANSLATE_2_1);
3377         STR_VTR_OP_CASE(TRANSLATE_2_2);
3378     }
3379
3380     return "UNKNOWN";
3381 }
3382
3383 static int dump_sub_interface_table (vat_main_t * vam)
3384 {
3385     const sw_interface_subif_t * sub = NULL;
3386
3387     if (vam->json_output) {
3388         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
3389         return -99;
3390     }
3391
3392     fformat (vam->ofp,
3393              "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s\n",
3394              "Interface", "sw_if_index",
3395              "sub id", "dot1ad", "tags", "outer id",
3396              "inner id", "exact", "default",
3397              "outer any", "inner any");
3398
3399     vec_foreach (sub, vam->sw_if_subif_table) {
3400         fformat (vam->ofp,
3401                  "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d\n",
3402                  sub->interface_name,
3403                  sub->sw_if_index,
3404                  sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
3405                  sub->sub_number_of_tags, sub->sub_outer_vlan_id,
3406                  sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
3407                  sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
3408         if (sub->vtr_op != L2_VTR_DISABLED) {
3409             fformat (vam->ofp,
3410                      "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
3411                      "tag1: %d tag2: %d ]\n",
3412                      str_vtr_op(sub->vtr_op), sub->vtr_push_dot1q,
3413                      sub->vtr_tag1, sub->vtr_tag2);
3414         }
3415     }
3416
3417     return 0;
3418 }
3419
3420 static int name_sort_cmp (void * a1, void * a2)
3421 {
3422   name_sort_t * n1 = a1;
3423   name_sort_t * n2 = a2;
3424
3425   return strcmp ((char *)n1->name, (char *)n2->name);
3426 }
3427
3428 static int dump_interface_table (vat_main_t * vam)
3429 {
3430     hash_pair_t * p;
3431     name_sort_t * nses = 0, * ns;
3432
3433     if (vam->json_output) {
3434         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
3435         return -99;
3436     }
3437
3438     hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3439     ({
3440         vec_add2 (nses, ns, 1);
3441         ns->name = (u8 *)(p->key);
3442         ns->value = (u32) p->value[0];
3443     }));
3444
3445     vec_sort_with_function (nses, name_sort_cmp);
3446
3447     fformat (vam->ofp, "%-25s%-15s\n", "Interface", "sw_if_index");
3448     vec_foreach (ns, nses) {
3449         fformat (vam->ofp, "%-25s%-15d\n", ns->name, ns->value);
3450     }
3451     vec_free (nses);
3452     return 0;
3453 }
3454
3455 static int dump_ip_table (vat_main_t * vam, int is_ipv6)
3456 {
3457     const ip_details_t * det = NULL;
3458     const ip_address_details_t * address = NULL;
3459     u32 i = ~0;
3460
3461     fformat (vam->ofp,
3462              "%-12s\n",
3463              "sw_if_index");
3464
3465     if (0 == vam) {
3466         return 0;
3467     }
3468
3469     vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6]) {
3470         i++;
3471         if (!det->present) {
3472             continue;
3473         }
3474         fformat (vam->ofp,
3475                  "%-12d\n",
3476                  i);
3477         fformat (vam->ofp,
3478                  "            %-30s%-13s\n",
3479                  "Address", "Prefix length");
3480         if (!det->addr) {
3481             continue;
3482         }
3483         vec_foreach (address, det->addr) {
3484             fformat (vam->ofp,
3485                      "            %-30U%-13d\n",
3486                      is_ipv6 ? format_ip6_address : format_ip4_address,
3487                      address->ip,
3488                      address->prefix_length);
3489         }
3490     }
3491
3492     return 0;
3493 }
3494
3495 static int dump_ipv4_table (vat_main_t * vam)
3496 {
3497     if (vam->json_output) {
3498         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
3499         return -99;
3500     }
3501
3502     return dump_ip_table (vam, 0);
3503 }
3504
3505 static int dump_ipv6_table (vat_main_t * vam)
3506 {
3507     if (vam->json_output) {
3508         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
3509         return -99;
3510     }
3511
3512     return dump_ip_table (vam, 1);
3513 }
3514
3515 static char* counter_type_to_str (u8 counter_type, u8 is_combined)
3516 {
3517     if (!is_combined) {
3518         switch(counter_type) {
3519         case VNET_INTERFACE_COUNTER_DROP:
3520             return "drop";
3521         case VNET_INTERFACE_COUNTER_PUNT:
3522             return "punt";
3523         case VNET_INTERFACE_COUNTER_IP4:
3524             return "ip4";
3525         case VNET_INTERFACE_COUNTER_IP6:
3526             return "ip6";
3527         case VNET_INTERFACE_COUNTER_RX_NO_BUF:
3528             return "rx-no-buf";
3529         case VNET_INTERFACE_COUNTER_RX_MISS:
3530             return "rx-miss";
3531         case VNET_INTERFACE_COUNTER_RX_ERROR:
3532             return "rx-error";
3533         case VNET_INTERFACE_COUNTER_TX_ERROR:
3534             return "tx-error";
3535         default:
3536             return "INVALID-COUNTER-TYPE";
3537         }
3538     } else {
3539         switch(counter_type) {
3540         case VNET_INTERFACE_COUNTER_RX:
3541             return "rx";
3542         case VNET_INTERFACE_COUNTER_TX:
3543             return "tx";
3544         default:
3545             return "INVALID-COUNTER-TYPE";
3546         }
3547     }
3548 }
3549
3550 static int dump_stats_table (vat_main_t * vam)
3551 {
3552     vat_json_node_t node;
3553     vat_json_node_t *msg_array;
3554     vat_json_node_t *msg;
3555     vat_json_node_t *counter_array;
3556     vat_json_node_t *counter;
3557     interface_counter_t c;
3558     u64 packets;
3559     ip4_fib_counter_t *c4;
3560     ip6_fib_counter_t *c6;
3561     int i, j;
3562
3563     if (!vam->json_output) {
3564         clib_warning ("dump_stats_table supported only in JSON format");
3565         return -99;
3566     }
3567
3568     vat_json_init_object(&node);
3569
3570     /* interface counters */
3571     msg_array = vat_json_object_add(&node, "interface_counters");
3572     vat_json_init_array(msg_array);
3573     for (i = 0; i < vec_len(vam->simple_interface_counters); i++) {
3574         msg = vat_json_array_add(msg_array);
3575         vat_json_init_object(msg);
3576         vat_json_object_add_string_copy(msg, "vnet_counter_type",
3577                 (u8*)counter_type_to_str(i, 0));
3578         vat_json_object_add_int(msg, "is_combined", 0);
3579         counter_array = vat_json_object_add(msg, "data");
3580         vat_json_init_array(counter_array);
3581         for (j = 0; j < vec_len(vam->simple_interface_counters[i]); j++) {
3582             packets = vam->simple_interface_counters[i][j];
3583             vat_json_array_add_uint(counter_array, packets);
3584         }
3585     }
3586     for (i = 0; i < vec_len(vam->combined_interface_counters); i++) {
3587         msg = vat_json_array_add(msg_array);
3588         vat_json_init_object(msg);
3589         vat_json_object_add_string_copy(msg, "vnet_counter_type",
3590                 (u8*)counter_type_to_str(i, 1));
3591         vat_json_object_add_int(msg, "is_combined", 1);
3592         counter_array = vat_json_object_add(msg, "data");
3593         vat_json_init_array(counter_array);
3594         for (j = 0; j < vec_len(vam->combined_interface_counters[i]); j++) {
3595             c = vam->combined_interface_counters[i][j];
3596             counter = vat_json_array_add(counter_array);
3597             vat_json_init_object(counter);
3598             vat_json_object_add_uint(counter, "packets", c.packets);
3599             vat_json_object_add_uint(counter, "bytes", c.bytes);
3600         }
3601     }
3602
3603     /* ip4 fib counters */
3604     msg_array = vat_json_object_add(&node, "ip4_fib_counters");
3605     vat_json_init_array(msg_array);
3606     for (i = 0; i < vec_len(vam->ip4_fib_counters); i++) {
3607         msg = vat_json_array_add(msg_array);
3608         vat_json_init_object(msg);
3609         vat_json_object_add_uint(msg, "vrf_id", vam->ip4_fib_counters_vrf_id_by_index[i]);
3610         counter_array = vat_json_object_add(msg, "c");
3611         vat_json_init_array(counter_array);
3612         for (j = 0; j < vec_len(vam->ip4_fib_counters[i]); j++) {
3613             counter = vat_json_array_add(counter_array);
3614             vat_json_init_object(counter);
3615             c4 = &vam->ip4_fib_counters[i][j];
3616             vat_json_object_add_ip4(counter, "address", c4->address);
3617             vat_json_object_add_uint(counter, "address_length", c4->address_length);
3618             vat_json_object_add_uint(counter, "packets", c4->packets);
3619             vat_json_object_add_uint(counter, "bytes", c4->bytes);
3620         }
3621     }
3622
3623     /* ip6 fib counters */
3624     msg_array = vat_json_object_add(&node, "ip6_fib_counters");
3625     vat_json_init_array(msg_array);
3626     for (i = 0; i < vec_len(vam->ip6_fib_counters); i++) {
3627         msg = vat_json_array_add(msg_array);
3628         vat_json_init_object(msg);
3629         vat_json_object_add_uint(msg, "vrf_id", vam->ip6_fib_counters_vrf_id_by_index[i]);
3630         counter_array = vat_json_object_add(msg, "c");
3631         vat_json_init_array(counter_array);
3632         for (j = 0; j < vec_len(vam->ip6_fib_counters[i]); j++) {
3633             counter = vat_json_array_add(counter_array);
3634             vat_json_init_object(counter);
3635             c6 = &vam->ip6_fib_counters[i][j];
3636             vat_json_object_add_ip6(counter, "address", c6->address);
3637             vat_json_object_add_uint(counter, "address_length", c6->address_length);
3638             vat_json_object_add_uint(counter, "packets", c6->packets);
3639             vat_json_object_add_uint(counter, "bytes", c6->bytes);
3640         }
3641     }
3642
3643     vat_json_print(vam->ofp, &node);
3644     vat_json_free(&node);
3645
3646     return 0;
3647 }
3648
3649 int exec (vat_main_t * vam)
3650 {
3651     api_main_t * am = &api_main;
3652     vl_api_cli_request_t *mp;
3653     f64 timeout;
3654     void * oldheap;
3655     u8 * cmd = 0;
3656     unformat_input_t * i = vam->input;
3657
3658     if (vec_len(i->buffer) == 0)
3659         return -1;
3660
3661     if (vam->exec_mode == 0 && unformat (i, "mode")) {
3662         vam->exec_mode = 1;
3663         return 0;
3664     }
3665     if (vam->exec_mode == 1 &&
3666         (unformat (i, "exit") || unformat (i, "quit"))) {
3667         vam->exec_mode = 0;
3668         return 0;
3669     }
3670
3671
3672     M(CLI_REQUEST, cli_request);
3673
3674     /*
3675      * Copy cmd into shared memory.
3676      * In order for the CLI command to work, it
3677      * must be a vector ending in \n, not a C-string ending
3678      * in \n\0.
3679      */
3680     pthread_mutex_lock (&am->vlib_rp->mutex);
3681     oldheap = svm_push_data_heap (am->vlib_rp);
3682
3683     vec_validate (cmd, vec_len(vam->input->buffer)-1);
3684     clib_memcpy (cmd, vam->input->buffer, vec_len(vam->input->buffer));
3685
3686     svm_pop_heap (oldheap);
3687     pthread_mutex_unlock (&am->vlib_rp->mutex);
3688
3689     mp->cmd_in_shmem = (u64) cmd;
3690     S;
3691     timeout = vat_time_now (vam) + 10.0;
3692
3693     while (vat_time_now (vam) < timeout) {
3694         if (vam->result_ready == 1) {
3695             u8 * free_me;
3696             if (vam->shmem_result != NULL)
3697                 fformat (vam->ofp, "%s", vam->shmem_result);
3698             pthread_mutex_lock (&am->vlib_rp->mutex);
3699             oldheap = svm_push_data_heap (am->vlib_rp);
3700
3701             free_me = (u8 *)vam->shmem_result;
3702             vec_free (free_me);
3703
3704             svm_pop_heap (oldheap);
3705             pthread_mutex_unlock (&am->vlib_rp->mutex);
3706             return 0;
3707         }
3708     }
3709     return -99;
3710 }
3711
3712 static int api_create_loopback (vat_main_t * vam)
3713 {
3714     unformat_input_t * i = vam->input;
3715     vl_api_create_loopback_t *mp;
3716     f64 timeout;
3717     u8 mac_address[6];
3718     u8 mac_set = 0;
3719
3720     memset (mac_address, 0, sizeof (mac_address));
3721
3722     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3723       {
3724         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
3725             mac_set = 1;
3726         else
3727           break;
3728       }
3729
3730     /* Construct the API message */
3731     M(CREATE_LOOPBACK, create_loopback);
3732     if (mac_set)
3733         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
3734
3735     S; W;
3736 }
3737
3738 static int api_delete_loopback (vat_main_t * vam)
3739 {
3740     unformat_input_t * i = vam->input;
3741     vl_api_delete_loopback_t *mp;
3742     f64 timeout;
3743     u32 sw_if_index = ~0;
3744
3745     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3746       {
3747         if (unformat (i, "sw_if_index %d", &sw_if_index))
3748           ;
3749         else
3750           break;
3751       }
3752
3753     if (sw_if_index == ~0)
3754       {
3755         errmsg ("missing sw_if_index\n");
3756         return -99;
3757       }
3758
3759     /* Construct the API message */
3760     M(DELETE_LOOPBACK, delete_loopback);
3761     mp->sw_if_index = ntohl (sw_if_index);
3762
3763     S; W;
3764 }
3765
3766 static int api_want_stats (vat_main_t * vam)
3767 {
3768     unformat_input_t * i = vam->input;
3769     vl_api_want_stats_t * mp;
3770     f64 timeout;
3771     int enable = -1;
3772
3773     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3774       {
3775         if (unformat (i, "enable"))
3776           enable = 1;
3777         else if (unformat (i, "disable"))
3778           enable = 0;
3779         else
3780           break;
3781       }
3782
3783     if (enable == -1)
3784       {
3785         errmsg ("missing enable|disable\n");
3786         return -99;
3787       }
3788
3789     M(WANT_STATS, want_stats);
3790     mp->enable_disable = enable;
3791
3792     S; W;
3793 }
3794
3795 static int api_want_interface_events (vat_main_t * vam)
3796 {
3797     unformat_input_t * i = vam->input;
3798     vl_api_want_interface_events_t * mp;
3799     f64 timeout;
3800     int enable = -1;
3801
3802     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3803       {
3804         if (unformat (i, "enable"))
3805           enable = 1;
3806         else if (unformat (i, "disable"))
3807           enable = 0;
3808         else
3809           break;
3810       }
3811
3812     if (enable == -1)
3813       {
3814         errmsg ("missing enable|disable\n");
3815         return -99;
3816       }
3817
3818     M(WANT_INTERFACE_EVENTS, want_interface_events);
3819     mp->enable_disable = enable;
3820
3821     vam->interface_event_display = enable;
3822
3823     S; W;
3824 }
3825
3826
3827 /* Note: non-static, called once to set up the initial intfc table */
3828 int api_sw_interface_dump (vat_main_t * vam)
3829 {
3830     vl_api_sw_interface_dump_t *mp;
3831     f64 timeout;
3832     hash_pair_t * p;
3833     name_sort_t * nses = 0, * ns;
3834     sw_interface_subif_t * sub = NULL;
3835
3836     /* Toss the old name table */
3837     hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
3838     ({
3839         vec_add2 (nses, ns, 1);
3840         ns->name = (u8 *)(p->key);
3841         ns->value = (u32) p->value[0];
3842     }));
3843
3844     hash_free (vam->sw_if_index_by_interface_name);
3845
3846     vec_foreach (ns, nses)
3847         vec_free (ns->name);
3848
3849     vec_free (nses);
3850
3851     vec_foreach (sub, vam->sw_if_subif_table) {
3852         vec_free (sub->interface_name);
3853     }
3854     vec_free (vam->sw_if_subif_table);
3855
3856     /* recreate the interface name hash table */
3857     vam->sw_if_index_by_interface_name
3858         = hash_create_string (0, sizeof(uword));
3859
3860     /* Get list of ethernets */
3861     M(SW_INTERFACE_DUMP, sw_interface_dump);
3862     mp->name_filter_valid = 1;
3863     strncpy ((char *) mp->name_filter, "Ether", sizeof(mp->name_filter)-1);
3864     S;
3865
3866     /* and local / loopback interfaces */
3867     M(SW_INTERFACE_DUMP, sw_interface_dump);
3868     mp->name_filter_valid = 1;
3869     strncpy ((char *) mp->name_filter, "lo", sizeof(mp->name_filter)-1);
3870     S;
3871
3872
3873     /* and vxlan-gpe tunnel interfaces */
3874     M(SW_INTERFACE_DUMP, sw_interface_dump);
3875     mp->name_filter_valid = 1;
3876     strncpy ((char *) mp->name_filter, "vxlan_gpe", sizeof(mp->name_filter)-1);
3877     S;
3878
3879     /* and vxlan tunnel interfaces */
3880     M(SW_INTERFACE_DUMP, sw_interface_dump);
3881     mp->name_filter_valid = 1;
3882     strncpy ((char *) mp->name_filter, "vxlan", sizeof(mp->name_filter)-1);
3883     S;
3884
3885     /* and host (af_packet) interfaces */
3886     M(SW_INTERFACE_DUMP, sw_interface_dump);
3887     mp->name_filter_valid = 1;
3888     strncpy ((char *) mp->name_filter, "host", sizeof(mp->name_filter)-1);
3889     S;
3890
3891     /* and l2tpv3 tunnel interfaces */
3892     M(SW_INTERFACE_DUMP, sw_interface_dump);
3893     mp->name_filter_valid = 1;
3894     strncpy ((char *) mp->name_filter, "l2tpv3_tunnel", sizeof(mp->name_filter)-1);
3895     S;
3896
3897     /* and GRE tunnel interfaces */
3898     M(SW_INTERFACE_DUMP, sw_interface_dump);
3899     mp->name_filter_valid = 1;
3900     strncpy ((char *) mp->name_filter, "gre", sizeof(mp->name_filter)-1);
3901     S;
3902
3903     /* Use a control ping for synchronization */
3904     {
3905         vl_api_control_ping_t * mp;
3906         M(CONTROL_PING, control_ping);
3907         S;
3908     }
3909     W;
3910 }
3911
3912 static int api_sw_interface_set_flags (vat_main_t * vam)
3913 {
3914     unformat_input_t * i = vam->input;
3915     vl_api_sw_interface_set_flags_t *mp;
3916     f64 timeout;
3917     u32 sw_if_index;
3918     u8 sw_if_index_set = 0;
3919     u8 admin_up = 0, link_up = 0;
3920
3921     /* Parse args required to build the message */
3922     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3923         if (unformat (i, "admin-up"))
3924             admin_up = 1;
3925         else if (unformat (i, "admin-down"))
3926             admin_up = 0;
3927         else if (unformat (i, "link-up"))
3928             link_up = 1;
3929         else if (unformat (i, "link-down"))
3930             link_up = 0;
3931         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3932             sw_if_index_set = 1;
3933         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3934             sw_if_index_set = 1;
3935         else
3936             break;
3937     }
3938
3939     if (sw_if_index_set == 0) {
3940         errmsg ("missing interface name or sw_if_index\n");
3941         return -99;
3942     }
3943
3944     /* Construct the API message */
3945     M(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags);
3946     mp->sw_if_index = ntohl (sw_if_index);
3947     mp->admin_up_down = admin_up;
3948     mp->link_up_down = link_up;
3949
3950     /* send it... */
3951     S;
3952
3953     /* Wait for a reply, return the good/bad news... */
3954     W;
3955 }
3956
3957 static int api_sw_interface_clear_stats (vat_main_t * vam)
3958 {
3959     unformat_input_t * i = vam->input;
3960     vl_api_sw_interface_clear_stats_t *mp;
3961     f64 timeout;
3962     u32 sw_if_index;
3963     u8 sw_if_index_set = 0;
3964
3965     /* Parse args required to build the message */
3966     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3967         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3968             sw_if_index_set = 1;
3969         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3970             sw_if_index_set = 1;
3971         else
3972             break;
3973     }
3974
3975     /* Construct the API message */
3976     M(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats);
3977
3978     if (sw_if_index_set == 1)
3979         mp->sw_if_index = ntohl (sw_if_index);
3980     else
3981         mp->sw_if_index = ~0;
3982
3983     /* send it... */
3984     S;
3985
3986     /* Wait for a reply, return the good/bad news... */
3987     W;
3988 }
3989
3990 static int api_sw_interface_add_del_address (vat_main_t * vam)
3991 {
3992     unformat_input_t * i = vam->input;
3993     vl_api_sw_interface_add_del_address_t *mp;
3994     f64 timeout;
3995     u32 sw_if_index;
3996     u8 sw_if_index_set = 0;
3997     u8 is_add = 1, del_all = 0;
3998     u32 address_length = 0;
3999     u8 v4_address_set = 0;
4000     u8 v6_address_set = 0;
4001     ip4_address_t v4address;
4002     ip6_address_t v6address;
4003
4004     /* Parse args required to build the message */
4005     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4006         if (unformat (i, "del-all"))
4007             del_all = 1;
4008         else if (unformat (i, "del"))
4009             is_add = 0;
4010         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4011             sw_if_index_set = 1;
4012         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4013             sw_if_index_set = 1;
4014         else if (unformat (i, "%U/%d",
4015                            unformat_ip4_address, &v4address,
4016                            &address_length))
4017             v4_address_set = 1;
4018         else if (unformat (i, "%U/%d",
4019                            unformat_ip6_address, &v6address,
4020                            &address_length))
4021             v6_address_set = 1;
4022         else
4023             break;
4024     }
4025
4026     if (sw_if_index_set == 0) {
4027         errmsg ("missing interface name or sw_if_index\n");
4028         return -99;
4029     }
4030     if (v4_address_set && v6_address_set) {
4031         errmsg ("both v4 and v6 addresses set\n");
4032         return -99;
4033     }
4034     if (!v4_address_set && !v6_address_set && !del_all) {
4035         errmsg ("no addresses set\n");
4036         return -99;
4037     }
4038
4039     /* Construct the API message */
4040     M(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address);
4041
4042     mp->sw_if_index = ntohl (sw_if_index);
4043     mp->is_add = is_add;
4044     mp->del_all = del_all;
4045     if (v6_address_set) {
4046         mp->is_ipv6 = 1;
4047         clib_memcpy (mp->address, &v6address, sizeof (v6address));
4048     } else {
4049         clib_memcpy (mp->address, &v4address, sizeof (v4address));
4050     }
4051     mp->address_length = address_length;
4052
4053     /* send it... */
4054     S;
4055
4056     /* Wait for a reply, return good/bad news  */
4057     W;
4058 }
4059
4060 static int api_sw_interface_set_table (vat_main_t * vam)
4061 {
4062     unformat_input_t * i = vam->input;
4063     vl_api_sw_interface_set_table_t *mp;
4064     f64 timeout;
4065     u32 sw_if_index, vrf_id = 0;
4066     u8 sw_if_index_set = 0;
4067     u8 is_ipv6 = 0;
4068
4069     /* Parse args required to build the message */
4070     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4071         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4072             sw_if_index_set = 1;
4073         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4074             sw_if_index_set = 1;
4075         else if (unformat (i, "vrf %d", &vrf_id))
4076             ;
4077         else if (unformat (i, "ipv6"))
4078             is_ipv6 = 1;
4079         else
4080             break;
4081     }
4082
4083     if (sw_if_index_set == 0) {
4084         errmsg ("missing interface name or sw_if_index\n");
4085         return -99;
4086     }
4087
4088     /* Construct the API message */
4089     M(SW_INTERFACE_SET_TABLE, sw_interface_set_table);
4090
4091     mp->sw_if_index = ntohl (sw_if_index);
4092     mp->is_ipv6 = is_ipv6;
4093     mp->vrf_id = ntohl (vrf_id);
4094
4095     /* send it... */
4096     S;
4097
4098     /* Wait for a reply... */
4099     W;
4100 }
4101
4102 static int api_sw_interface_set_vpath (vat_main_t * vam)
4103 {
4104     unformat_input_t * i = vam->input;
4105     vl_api_sw_interface_set_vpath_t *mp;
4106     f64 timeout;
4107     u32 sw_if_index = 0;
4108     u8 sw_if_index_set = 0;
4109     u8 is_enable = 0;
4110
4111     /* Parse args required to build the message */
4112     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4113         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4114             sw_if_index_set = 1;
4115         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4116             sw_if_index_set = 1;
4117         else if (unformat (i, "enable"))
4118             is_enable = 1;
4119         else if (unformat (i, "disable"))
4120             is_enable = 0;
4121         else
4122             break;
4123     }
4124
4125     if (sw_if_index_set == 0) {
4126         errmsg ("missing interface name or sw_if_index\n");
4127         return -99;
4128     }
4129
4130     /* Construct the API message */
4131     M(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath);
4132
4133     mp->sw_if_index = ntohl (sw_if_index);
4134     mp->enable = is_enable;
4135
4136     /* send it... */
4137     S;
4138
4139     /* Wait for a reply... */
4140     W;
4141 }
4142
4143 static int api_sw_interface_set_l2_xconnect (vat_main_t * vam)
4144 {
4145     unformat_input_t * i = vam->input;
4146     vl_api_sw_interface_set_l2_xconnect_t *mp;
4147     f64 timeout;
4148     u32 rx_sw_if_index;
4149     u8 rx_sw_if_index_set = 0;
4150     u32 tx_sw_if_index;
4151     u8 tx_sw_if_index_set = 0;
4152     u8 enable = 1;
4153
4154     /* Parse args required to build the message */
4155     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4156         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4157             rx_sw_if_index_set = 1;
4158         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4159             tx_sw_if_index_set = 1;
4160         else if (unformat (i, "rx")) {
4161             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4162                 if (unformat (i, "%U", unformat_sw_if_index, vam,
4163                               &rx_sw_if_index))
4164                     rx_sw_if_index_set = 1;
4165             } else
4166                 break;
4167         } else if (unformat (i, "tx")) {
4168             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4169                 if (unformat (i, "%U", unformat_sw_if_index, vam,
4170                               &tx_sw_if_index))
4171                     tx_sw_if_index_set = 1;
4172             } else
4173                 break;
4174         } else if (unformat (i, "enable"))
4175             enable = 1;
4176         else if (unformat (i, "disable"))
4177             enable = 0;
4178         else
4179             break;
4180     }
4181
4182     if (rx_sw_if_index_set == 0) {
4183         errmsg ("missing rx interface name or rx_sw_if_index\n");
4184         return -99;
4185     }
4186
4187     if (enable && (tx_sw_if_index_set == 0)) {
4188         errmsg ("missing tx interface name or tx_sw_if_index\n");
4189         return -99;
4190     }
4191
4192     M(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect);
4193
4194     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
4195     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
4196     mp->enable = enable;
4197
4198     S; W;
4199     /* NOTREACHED */
4200     return 0;
4201 }
4202
4203 static int api_sw_interface_set_l2_bridge (vat_main_t * vam)
4204 {
4205     unformat_input_t * i = vam->input;
4206     vl_api_sw_interface_set_l2_bridge_t *mp;
4207     f64 timeout;
4208     u32 rx_sw_if_index;
4209     u8 rx_sw_if_index_set = 0;
4210     u32 bd_id;
4211     u8 bd_id_set = 0;
4212     u8 bvi = 0;
4213     u32 shg = 0;
4214     u8 enable = 1;
4215
4216     /* Parse args required to build the message */
4217     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4218         if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
4219             rx_sw_if_index_set = 1;
4220         else if (unformat (i, "bd_id %d", &bd_id))
4221             bd_id_set = 1;
4222         else if (unformat (i, "%U", unformat_sw_if_index, vam,
4223                            &rx_sw_if_index))
4224             rx_sw_if_index_set = 1;
4225         else if (unformat (i, "shg %d", &shg))
4226             ;
4227         else if (unformat (i, "bvi"))
4228             bvi = 1;
4229         else if (unformat (i, "enable"))
4230             enable = 1;
4231         else if (unformat (i, "disable"))
4232             enable = 0;
4233         else
4234             break;
4235     }
4236
4237     if (rx_sw_if_index_set == 0) {
4238         errmsg ("missing rx interface name or sw_if_index\n");
4239         return -99;
4240     }
4241
4242     if (enable && (bd_id_set == 0)) {
4243         errmsg ("missing bridge domain\n");
4244         return -99;
4245     }
4246
4247     M(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge);
4248
4249     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
4250     mp->bd_id = ntohl(bd_id);
4251     mp->shg = (u8)shg;
4252     mp->bvi = bvi;
4253     mp->enable = enable;
4254
4255     S; W;
4256     /* NOTREACHED */
4257     return 0;
4258 }
4259
4260 static int api_bridge_domain_dump (vat_main_t * vam)
4261 {
4262     unformat_input_t * i = vam->input;
4263     vl_api_bridge_domain_dump_t *mp;
4264     f64 timeout;
4265     u32 bd_id = ~0;
4266
4267     /* Parse args required to build the message */
4268     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4269         if (unformat (i, "bd_id %d", &bd_id))
4270             ;
4271         else
4272             break;
4273     }
4274
4275     M(BRIDGE_DOMAIN_DUMP, bridge_domain_dump);
4276     mp->bd_id = ntohl(bd_id);
4277     S;
4278
4279     /* Use a control ping for synchronization */
4280     {
4281         vl_api_control_ping_t * mp;
4282         M(CONTROL_PING, control_ping);
4283         S;
4284     }
4285
4286     W;
4287     /* NOTREACHED */
4288     return 0;
4289 }
4290
4291 static int api_bridge_domain_add_del (vat_main_t * vam)
4292 {
4293     unformat_input_t * i = vam->input;
4294     vl_api_bridge_domain_add_del_t *mp;
4295     f64 timeout;
4296     u32 bd_id = ~0;
4297     u8 is_add = 1;
4298     u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
4299
4300     /* Parse args required to build the message */
4301     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4302         if (unformat (i, "bd_id %d", &bd_id))
4303             ;
4304         else if (unformat (i, "flood %d", &flood))
4305              ;
4306         else if (unformat (i, "uu-flood %d", &uu_flood))
4307              ;
4308         else if (unformat (i, "forward %d", &forward))
4309              ;
4310         else if (unformat (i, "learn %d", &learn))
4311              ;
4312         else if (unformat (i, "arp-term %d", &arp_term))
4313              ;
4314         else if (unformat (i, "del")) {
4315              is_add = 0;
4316              flood = uu_flood = forward = learn = 0;
4317         }
4318         else
4319             break;
4320     }
4321
4322     if (bd_id == ~0) {
4323         errmsg ("missing bridge domain\n");
4324         return -99;
4325     }
4326
4327     M(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del);
4328
4329     mp->bd_id = ntohl(bd_id);
4330     mp->flood = flood;
4331     mp->uu_flood = uu_flood;
4332     mp->forward = forward;
4333     mp->learn = learn;
4334     mp->arp_term = arp_term;
4335     mp->is_add = is_add;
4336
4337     S; W;
4338     /* NOTREACHED */
4339     return 0;
4340 }
4341
4342 static int api_l2fib_add_del (vat_main_t * vam)
4343 {
4344     unformat_input_t * i = vam->input;
4345     vl_api_l2fib_add_del_t *mp;
4346     f64 timeout;
4347     u64 mac = 0;
4348     u8 mac_set = 0;
4349     u32 bd_id;
4350     u8 bd_id_set = 0;
4351     u32 sw_if_index;
4352     u8 sw_if_index_set = 0;
4353     u8 is_add = 1;
4354     u8 static_mac = 0;
4355     u8 filter_mac = 0;
4356     u8 bvi_mac = 0;
4357     int count = 1;
4358     f64 before = 0;
4359     int j;
4360
4361     /* Parse args required to build the message */
4362     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4363         if (unformat (i, "mac %U", unformat_ethernet_address, &mac))
4364             mac_set = 1;
4365         else if (unformat (i, "bd_id %d", &bd_id))
4366             bd_id_set = 1;
4367         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4368             sw_if_index_set = 1;
4369         else if (unformat (i, "sw_if")) {
4370             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4371                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4372                     sw_if_index_set = 1;
4373             } else
4374                 break;
4375         } else if (unformat (i, "static"))
4376             static_mac = 1;
4377         else if (unformat (i, "filter")) {
4378             filter_mac = 1;
4379             static_mac = 1;
4380         } else if (unformat (i, "bvi")) {
4381             bvi_mac = 1;
4382             static_mac = 1;
4383         } else if (unformat (i, "del"))
4384             is_add = 0;
4385         else if (unformat (i, "count %d", &count))
4386             ;
4387         else
4388             break;
4389     }
4390
4391     if (mac_set == 0) {
4392         errmsg ("missing mac address\n");
4393         return -99;
4394     }
4395
4396     if (bd_id_set == 0) {
4397         errmsg ("missing bridge domain\n");
4398         return -99;
4399     }
4400
4401     if (is_add && (sw_if_index_set == 0)) {
4402         errmsg ("missing interface name or sw_if_index\n");
4403         return -99;
4404     }
4405
4406     if (count > 1) {
4407         /* Turn on async mode */
4408         vam->async_mode = 1;
4409         vam->async_errors = 0;
4410         before = vat_time_now(vam);
4411     }
4412
4413     for (j = 0; j < count; j++) {
4414         M(L2FIB_ADD_DEL, l2fib_add_del);
4415
4416         mp->mac = mac;
4417         mp->bd_id = ntohl(bd_id);
4418         mp->is_add = is_add;
4419
4420         if (is_add) {
4421             mp->sw_if_index = ntohl(sw_if_index);
4422             mp->static_mac = static_mac;
4423             mp->filter_mac = filter_mac;
4424             mp->bvi_mac = bvi_mac;
4425         }
4426         increment_mac_address (&mac);
4427         /* send it... */
4428         S;
4429     }
4430
4431     if (count > 1) {
4432         vl_api_control_ping_t * mp;
4433         f64 after;
4434
4435         /* Shut off async mode */
4436         vam->async_mode = 0;
4437
4438         M(CONTROL_PING, control_ping);
4439         S;
4440
4441         timeout = vat_time_now(vam) + 1.0;
4442         while (vat_time_now (vam) < timeout)
4443             if (vam->result_ready == 1)
4444                 goto out;
4445         vam->retval = -99;
4446
4447     out:
4448         if (vam->retval == -99)
4449             errmsg ("timeout\n");
4450
4451         if (vam->async_errors > 0) {
4452             errmsg ("%d asynchronous errors\n", vam->async_errors);
4453             vam->retval = -98;
4454         }
4455         vam->async_errors = 0;
4456         after = vat_time_now(vam);
4457
4458         fformat(vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
4459                 count, after - before, count / (after - before));
4460     } else {
4461         /* Wait for a reply... */
4462         W;
4463     }
4464     /* Return the good/bad news */
4465     return (vam->retval);
4466 }
4467
4468 static int api_l2_flags (vat_main_t * vam)
4469 {
4470     unformat_input_t * i = vam->input;
4471     vl_api_l2_flags_t *mp;
4472     f64 timeout;
4473     u32 sw_if_index;
4474     u32 feature_bitmap = 0;
4475     u8 sw_if_index_set = 0;
4476
4477     /* Parse args required to build the message */
4478     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4479         if (unformat (i, "sw_if_index %d", &sw_if_index))
4480             sw_if_index_set = 1;
4481         else if (unformat (i, "sw_if")) {
4482             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4483                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4484                     sw_if_index_set = 1;
4485             } else
4486                 break;
4487         } else if (unformat (i, "learn"))
4488             feature_bitmap |= L2INPUT_FEAT_LEARN;
4489         else if (unformat (i, "forward"))
4490             feature_bitmap |= L2INPUT_FEAT_FWD;
4491         else if (unformat (i, "flood"))
4492             feature_bitmap |= L2INPUT_FEAT_FLOOD;
4493         else if (unformat (i, "uu-flood"))
4494             feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
4495         else
4496             break;
4497     }
4498
4499     if (sw_if_index_set == 0) {
4500         errmsg ("missing interface name or sw_if_index\n");
4501         return -99;
4502     }
4503
4504     M(L2_FLAGS, l2_flags);
4505
4506     mp->sw_if_index = ntohl(sw_if_index);
4507     mp->feature_bitmap = ntohl(feature_bitmap);
4508
4509     S; W;
4510     /* NOTREACHED */
4511     return 0;
4512 }
4513
4514 static int api_bridge_flags (vat_main_t * vam)
4515 {
4516     unformat_input_t * i = vam->input;
4517     vl_api_bridge_flags_t *mp;
4518     f64 timeout;
4519     u32 bd_id;
4520     u8 bd_id_set = 0;
4521     u8 is_set = 1;
4522     u32 flags = 0;
4523
4524     /* Parse args required to build the message */
4525     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4526         if (unformat (i, "bd_id %d", &bd_id))
4527             bd_id_set = 1;
4528         else if (unformat (i, "learn"))
4529             flags |= L2_LEARN;
4530         else if (unformat (i, "forward"))
4531             flags |= L2_FWD;
4532         else if (unformat (i, "flood"))
4533             flags |= L2_FLOOD;
4534         else if (unformat (i, "uu-flood"))
4535             flags |= L2_UU_FLOOD;
4536         else if (unformat (i, "arp-term"))
4537             flags |= L2_ARP_TERM;
4538         else if (unformat (i, "off"))
4539             is_set = 0;
4540         else if (unformat (i, "disable"))
4541             is_set = 0;
4542         else
4543             break;
4544     }
4545
4546     if (bd_id_set == 0) {
4547         errmsg ("missing bridge domain\n");
4548         return -99;
4549     }
4550
4551     M(BRIDGE_FLAGS, bridge_flags);
4552
4553     mp->bd_id = ntohl(bd_id);
4554     mp->feature_bitmap = ntohl(flags);
4555     mp->is_set = is_set;
4556
4557     S; W;
4558     /* NOTREACHED */
4559     return 0;
4560 }
4561
4562 static int api_bd_ip_mac_add_del (vat_main_t * vam)
4563 {
4564     unformat_input_t * i = vam->input;
4565     vl_api_bd_ip_mac_add_del_t *mp;
4566     f64 timeout;
4567     u32 bd_id;
4568     u8 is_ipv6 = 0;
4569     u8 is_add = 1;
4570     u8 bd_id_set = 0;
4571     u8 ip_set = 0;
4572     u8 mac_set = 0;
4573     ip4_address_t v4addr;
4574     ip6_address_t v6addr;
4575     u8 macaddr[6];
4576
4577
4578     /* Parse args required to build the message */
4579     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4580         if (unformat (i, "bd_id %d", &bd_id)) {
4581             bd_id_set++;
4582         } else if (unformat (i, "%U", unformat_ip4_address, &v4addr)) {
4583             ip_set++;
4584         } else if (unformat (i, "%U", unformat_ip6_address, &v6addr)) {
4585             ip_set++;
4586             is_ipv6++;
4587         } else if (unformat (i, "%U", unformat_ethernet_address, macaddr)) {
4588             mac_set++;
4589         } else if (unformat (i, "del"))
4590             is_add = 0;
4591         else
4592             break;
4593     }
4594
4595     if (bd_id_set == 0) {
4596         errmsg ("missing bridge domain\n");
4597         return -99;
4598     } else if (ip_set == 0) {
4599         errmsg ("missing IP address\n");
4600         return -99;
4601     } else if (mac_set == 0) {
4602         errmsg ("missing MAC address\n");
4603         return -99;
4604     }
4605
4606     M(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del);
4607
4608     mp->bd_id = ntohl(bd_id);
4609     mp->is_ipv6 = is_ipv6;
4610     mp->is_add = is_add;
4611     if (is_ipv6)
4612          clib_memcpy (mp->ip_address, &v6addr, sizeof (v6addr));
4613     else clib_memcpy (mp->ip_address, &v4addr, sizeof (v4addr));
4614     clib_memcpy (mp->mac_address, macaddr, 6);
4615     S; W;
4616     /* NOTREACHED */
4617     return 0;
4618 }
4619
4620 static int api_tap_connect (vat_main_t * vam)
4621 {
4622     unformat_input_t * i = vam->input;
4623     vl_api_tap_connect_t *mp;
4624     f64 timeout;
4625     u8 mac_address[6];
4626     u8 random_mac = 1;
4627     u8 name_set = 0;
4628     u8 * tap_name;
4629
4630     memset (mac_address, 0, sizeof (mac_address));
4631
4632     /* Parse args required to build the message */
4633     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4634         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
4635             random_mac = 0;
4636         }
4637         else if (unformat (i, "random-mac"))
4638             random_mac = 1;
4639         else if (unformat (i, "tapname %s", &tap_name))
4640             name_set = 1;
4641         else
4642             break;
4643     }
4644
4645     if (name_set == 0) {
4646         errmsg ("missing tap name\n");
4647         return -99;
4648     }
4649     if (vec_len (tap_name) > 63) {
4650         errmsg ("tap name too long\n");
4651     }
4652     vec_add1 (tap_name, 0);
4653
4654     /* Construct the API message */
4655     M(TAP_CONNECT, tap_connect);
4656
4657     mp->use_random_mac = random_mac;
4658     clib_memcpy (mp->mac_address, mac_address, 6);
4659     clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name));
4660     vec_free (tap_name);
4661
4662     /* send it... */
4663     S;
4664
4665     /* Wait for a reply... */
4666     W;
4667 }
4668
4669 static int api_tap_modify (vat_main_t * vam)
4670 {
4671     unformat_input_t * i = vam->input;
4672     vl_api_tap_modify_t *mp;
4673     f64 timeout;
4674     u8 mac_address[6];
4675     u8 random_mac = 1;
4676     u8 name_set = 0;
4677     u8 * tap_name;
4678     u32 sw_if_index = ~0;
4679     u8 sw_if_index_set = 0;
4680
4681     memset (mac_address, 0, sizeof (mac_address));
4682
4683     /* Parse args required to build the message */
4684     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4685         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4686             sw_if_index_set = 1;
4687         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4688             sw_if_index_set = 1;
4689         else if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
4690             random_mac = 0;
4691         }
4692         else if (unformat (i, "random-mac"))
4693             random_mac = 1;
4694         else if (unformat (i, "tapname %s", &tap_name))
4695             name_set = 1;
4696         else
4697             break;
4698     }
4699
4700     if (sw_if_index_set == 0) {
4701         errmsg ("missing vpp interface name");
4702         return -99;
4703     }
4704     if (name_set == 0) {
4705         errmsg ("missing tap name\n");
4706         return -99;
4707     }
4708     if (vec_len (tap_name) > 63) {
4709         errmsg ("tap name too long\n");
4710     }
4711     vec_add1 (tap_name, 0);
4712
4713     /* Construct the API message */
4714     M(TAP_MODIFY, tap_modify);
4715
4716     mp->use_random_mac = random_mac;
4717     mp->sw_if_index = ntohl(sw_if_index);
4718     clib_memcpy (mp->mac_address, mac_address, 6);
4719     clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name));
4720     vec_free (tap_name);
4721
4722     /* send it... */
4723     S;
4724
4725     /* Wait for a reply... */
4726     W;
4727 }
4728
4729 static int api_tap_delete (vat_main_t * vam)
4730 {
4731     unformat_input_t * i = vam->input;
4732     vl_api_tap_delete_t *mp;
4733     f64 timeout;
4734     u32 sw_if_index = ~0;
4735     u8 sw_if_index_set = 0;
4736
4737     /* Parse args required to build the message */
4738     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4739         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4740             sw_if_index_set = 1;
4741         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4742             sw_if_index_set = 1;
4743         else
4744             break;
4745     }
4746
4747     if (sw_if_index_set == 0) {
4748         errmsg ("missing vpp interface name");
4749         return -99;
4750     }
4751
4752     /* Construct the API message */
4753     M(TAP_DELETE, tap_delete);
4754
4755     mp->sw_if_index = ntohl(sw_if_index);
4756
4757     /* send it... */
4758     S;
4759
4760     /* Wait for a reply... */
4761     W;
4762 }
4763
4764 static int api_ip_add_del_route (vat_main_t * vam)
4765 {
4766     unformat_input_t * i = vam->input;
4767     vl_api_ip_add_del_route_t *mp;
4768     f64 timeout;
4769     u32 sw_if_index = ~0, vrf_id = 0;
4770     u8 sw_if_index_set = 0;
4771     u8 is_ipv6 = 0;
4772     u8 is_local = 0, is_drop = 0;
4773     u8 create_vrf_if_needed = 0;
4774     u8 is_add = 1;
4775     u8 next_hop_weight = 1;
4776     u8 not_last = 0;
4777     u8 is_multipath = 0;
4778     u8 address_set = 0;
4779     u8 address_length_set = 0;
4780     u32 lookup_in_vrf = 0;
4781     u32 resolve_attempts = 0;
4782     u32 dst_address_length = 0;
4783     u8 next_hop_set = 0;
4784     ip4_address_t v4_dst_address, v4_next_hop_address;
4785     ip6_address_t v6_dst_address, v6_next_hop_address;
4786     int count = 1;
4787     int j;
4788     f64 before = 0;
4789     u32 random_add_del = 0;
4790     u32 * random_vector = 0;
4791     uword * random_hash;
4792     u32 random_seed = 0xdeaddabe;
4793     u32 classify_table_index = ~0;
4794     u8 is_classify = 0;
4795
4796     /* Parse args required to build the message */
4797     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4798         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4799             sw_if_index_set = 1;
4800         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4801             sw_if_index_set = 1;
4802         else if (unformat (i, "%U", unformat_ip4_address,
4803                            &v4_dst_address)) {
4804             address_set = 1;
4805             is_ipv6 = 0;
4806         }
4807         else if (unformat (i, "%U", unformat_ip6_address, &v6_dst_address)) {
4808             address_set = 1;
4809             is_ipv6 = 1;
4810         }
4811         else if (unformat (i, "/%d", &dst_address_length)) {
4812             address_length_set = 1;
4813         }
4814
4815         else if (is_ipv6 == 0 && unformat (i, "via %U", unformat_ip4_address,
4816                                            &v4_next_hop_address)) {
4817             next_hop_set = 1;
4818         }
4819         else if (is_ipv6 == 1 && unformat (i, "via %U", unformat_ip6_address,
4820                                            &v6_next_hop_address)) {
4821             next_hop_set = 1;
4822         }
4823         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
4824             ;
4825         else if (unformat (i, "weight %d", &next_hop_weight))
4826             ;
4827         else if (unformat (i, "drop")) {
4828             is_drop = 1;
4829         } else if (unformat (i, "local")) {
4830             is_local = 1;
4831         } else if (unformat (i, "classify %d", &classify_table_index)) {
4832             is_classify = 1;
4833         } else if (unformat (i, "del"))
4834             is_add = 0;
4835         else if (unformat (i, "add"))
4836             is_add = 1;
4837         else if (unformat (i, "not-last"))
4838             not_last = 1;
4839         else if (unformat (i, "multipath"))
4840             is_multipath = 1;
4841         else if (unformat (i, "vrf %d", &vrf_id))
4842             ;
4843         else if (unformat (i, "create-vrf"))
4844             create_vrf_if_needed = 1;
4845         else if (unformat (i, "count %d", &count))
4846             ;
4847         else if (unformat (i, "lookup-in-vrf %d", &lookup_in_vrf))
4848             ;
4849         else if (unformat (i, "random"))
4850             random_add_del = 1;
4851         else if (unformat (i, "seed %d", &random_seed))
4852             ;
4853         else {
4854             clib_warning ("parse error '%U'", format_unformat_error, i);
4855             return -99;
4856         }
4857     }
4858
4859     if (resolve_attempts > 0 && sw_if_index_set == 0) {
4860         errmsg ("ARP resolution needs explicit interface or sw_if_index\n");
4861         return -99;
4862     }
4863
4864     if (!next_hop_set && !is_drop && !is_local && !is_classify) {
4865         errmsg ("next hop / local / drop / classify not set\n");
4866         return -99;
4867     }
4868
4869     if (address_set == 0) {
4870         errmsg ("missing addresses\n");
4871         return -99;
4872     }
4873
4874     if (address_length_set == 0) {
4875         errmsg ("missing address length\n");
4876         return -99;
4877     }
4878
4879     /* Generate a pile of unique, random routes */
4880     if (random_add_del) {
4881         u32 this_random_address;
4882         random_hash = hash_create (count, sizeof(uword));
4883
4884         hash_set (random_hash, v4_next_hop_address.as_u32, 1);
4885         for (j = 0; j <= count; j++) {
4886             do {
4887                 this_random_address = random_u32 (&random_seed);
4888                 this_random_address =
4889                     clib_host_to_net_u32 (this_random_address);
4890             } while (hash_get (random_hash, this_random_address));
4891             vec_add1 (random_vector, this_random_address);
4892             hash_set (random_hash, this_random_address, 1);
4893         }
4894         hash_free (random_hash);
4895         v4_dst_address.as_u32 = random_vector[0];
4896     }
4897
4898     if (count > 1) {
4899         /* Turn on async mode */
4900         vam->async_mode = 1;
4901         vam->async_errors = 0;
4902         before = vat_time_now(vam);
4903     }
4904
4905     for (j = 0; j < count; j++) {
4906         /* Construct the API message */
4907         M(IP_ADD_DEL_ROUTE, ip_add_del_route);
4908
4909         mp->next_hop_sw_if_index = ntohl (sw_if_index);
4910         mp->vrf_id = ntohl (vrf_id);
4911         if (resolve_attempts > 0) {
4912             mp->resolve_attempts = ntohl (resolve_attempts);
4913             mp->resolve_if_needed = 1;
4914         }
4915         mp->create_vrf_if_needed = create_vrf_if_needed;
4916
4917         mp->is_add = is_add;
4918         mp->is_drop = is_drop;
4919         mp->is_ipv6 = is_ipv6;
4920         mp->is_local = is_local;
4921         mp->is_classify = is_classify;
4922         mp->is_multipath = is_multipath;
4923         mp->not_last = not_last;
4924         mp->next_hop_weight = next_hop_weight;
4925         mp->dst_address_length = dst_address_length;
4926         mp->lookup_in_vrf = ntohl(lookup_in_vrf);
4927         mp->classify_table_index = ntohl(classify_table_index);
4928
4929         if (is_ipv6){
4930             clib_memcpy (mp->dst_address, &v6_dst_address, sizeof (v6_dst_address));
4931             if (next_hop_set)
4932                 clib_memcpy (mp->next_hop_address, &v6_next_hop_address,
4933                         sizeof (v6_next_hop_address));
4934             increment_v6_address (&v6_dst_address);
4935         } else {
4936             clib_memcpy (mp->dst_address, &v4_dst_address, sizeof (v4_dst_address));
4937             if (next_hop_set)
4938                 clib_memcpy (mp->next_hop_address, &v4_next_hop_address,
4939                         sizeof (v4_next_hop_address));
4940             if (random_add_del)
4941                 v4_dst_address.as_u32 = random_vector[j+1];
4942             else
4943                 increment_v4_address (&v4_dst_address);
4944         }
4945         /* send it... */
4946         S;
4947     }
4948
4949     /* When testing multiple add/del ops, use a control-ping to sync */
4950     if (count > 1) {
4951         vl_api_control_ping_t * mp;
4952         f64 after;
4953
4954         /* Shut off async mode */
4955         vam->async_mode = 0;
4956
4957         M(CONTROL_PING, control_ping);
4958         S;
4959
4960         timeout = vat_time_now(vam) + 1.0;
4961         while (vat_time_now (vam) < timeout)
4962             if (vam->result_ready == 1)
4963                 goto out;
4964         vam->retval = -99;
4965
4966     out:
4967         if (vam->retval == -99)
4968             errmsg ("timeout\n");
4969
4970         if (vam->async_errors > 0) {
4971             errmsg ("%d asynchronous errors\n", vam->async_errors);
4972             vam->retval = -98;
4973         }
4974         vam->async_errors = 0;
4975         after = vat_time_now(vam);
4976
4977         fformat(vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
4978                 count, after - before, count / (after - before));
4979     } else {
4980         /* Wait for a reply... */
4981         W;
4982     }
4983
4984     /* Return the good/bad news */
4985     return (vam->retval);
4986 }
4987
4988 static int api_proxy_arp_add_del (vat_main_t * vam)
4989 {
4990     unformat_input_t * i = vam->input;
4991     vl_api_proxy_arp_add_del_t *mp;
4992     f64 timeout;
4993     u32 vrf_id = 0;
4994     u8 is_add = 1;
4995     ip4_address_t lo, hi;
4996     u8 range_set = 0;
4997
4998     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4999         if (unformat (i, "vrf %d", &vrf_id))
5000             ;
5001         else if (unformat (i, "%U - %U", unformat_ip4_address, &lo,
5002                            unformat_ip4_address, &hi))
5003             range_set = 1;
5004         else if (unformat (i, "del"))
5005             is_add = 0;
5006         else {
5007             clib_warning ("parse error '%U'", format_unformat_error, i);
5008             return -99;
5009         }
5010     }
5011
5012     if (range_set == 0) {
5013         errmsg ("address range not set\n");
5014         return -99;
5015     }
5016
5017     M(PROXY_ARP_ADD_DEL, proxy_arp_add_del);
5018
5019     mp->vrf_id = ntohl(vrf_id);
5020     mp->is_add = is_add;
5021     clib_memcpy(mp->low_address, &lo, sizeof (mp->low_address));
5022     clib_memcpy(mp->hi_address, &hi, sizeof (mp->hi_address));
5023
5024     S; W;
5025     /* NOTREACHED */
5026     return 0;
5027 }
5028
5029 static int api_proxy_arp_intfc_enable_disable (vat_main_t * vam)
5030 {
5031     unformat_input_t * i = vam->input;
5032     vl_api_proxy_arp_intfc_enable_disable_t *mp;
5033     f64 timeout;
5034     u32 sw_if_index;
5035     u8 enable = 1;
5036     u8 sw_if_index_set = 0;
5037
5038     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5039         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5040             sw_if_index_set = 1;
5041         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5042             sw_if_index_set = 1;
5043         else if (unformat (i, "enable"))
5044             enable = 1;
5045         else if (unformat (i, "disable"))
5046             enable = 0;
5047         else {
5048             clib_warning ("parse error '%U'", format_unformat_error, i);
5049             return -99;
5050         }
5051     }
5052
5053     if (sw_if_index_set == 0) {
5054         errmsg ("missing interface name or sw_if_index\n");
5055         return -99;
5056     }
5057
5058     M(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable);
5059
5060     mp->sw_if_index = ntohl(sw_if_index);
5061     mp->enable_disable = enable;
5062
5063     S; W;
5064     /* NOTREACHED */
5065     return 0;
5066 }
5067
5068 static int api_mpls_add_del_decap (vat_main_t * vam)
5069 {
5070     unformat_input_t * i = vam->input;
5071     vl_api_mpls_add_del_decap_t *mp;
5072     f64 timeout;
5073     u32 rx_vrf_id = 0;
5074     u32 tx_vrf_id = 0;
5075     u32 label = 0;
5076     u8 is_add = 1;
5077     u8 s_bit = 1;
5078     u32 next_index = 1;
5079
5080     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5081         if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
5082             ;
5083         else if (unformat (i, "tx_vrf_id %d", &tx_vrf_id))
5084             ;
5085         else if (unformat (i, "label %d", &label))
5086             ;
5087         else if (unformat (i, "next-index %d", &next_index))
5088             ;
5089         else if (unformat (i, "del"))
5090             is_add = 0;
5091         else if (unformat (i, "s-bit-clear"))
5092             s_bit = 0;
5093         else {
5094             clib_warning ("parse error '%U'", format_unformat_error, i);
5095             return -99;
5096         }
5097     }
5098
5099     M(MPLS_ADD_DEL_DECAP, mpls_add_del_decap);
5100
5101     mp->rx_vrf_id = ntohl(rx_vrf_id);
5102     mp->tx_vrf_id = ntohl(tx_vrf_id);
5103     mp->label = ntohl(label);
5104     mp->next_index = ntohl(next_index);
5105     mp->s_bit = s_bit;
5106     mp->is_add = is_add;
5107
5108     S; W;
5109     /* NOTREACHED */
5110     return 0;
5111 }
5112
5113 static int api_mpls_add_del_encap (vat_main_t * vam)
5114 {
5115     unformat_input_t * i = vam->input;
5116     vl_api_mpls_add_del_encap_t *mp;
5117     f64 timeout;
5118     u32 vrf_id = 0;
5119     u32 *labels = 0;
5120     u32 label;
5121     ip4_address_t dst_address;
5122     u8 is_add = 1;
5123
5124     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5125         if (unformat (i, "vrf %d", &vrf_id))
5126             ;
5127         else if (unformat (i, "label %d", &label))
5128             vec_add1 (labels, ntohl(label));
5129         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
5130             ;
5131         else if (unformat (i, "del"))
5132             is_add = 0;
5133         else {
5134             clib_warning ("parse error '%U'", format_unformat_error, i);
5135             return -99;
5136         }
5137     }
5138
5139     if (vec_len (labels) == 0) {
5140         errmsg ("missing encap label stack\n");
5141         return -99;
5142     }
5143
5144     M2(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap,
5145        sizeof (u32) * vec_len (labels));
5146
5147     mp->vrf_id = ntohl(vrf_id);
5148     clib_memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
5149     mp->is_add = is_add;
5150     mp->nlabels = vec_len (labels);
5151     clib_memcpy(mp->labels, labels, sizeof(u32)*mp->nlabels);
5152
5153     vec_free(labels);
5154
5155     S; W;
5156     /* NOTREACHED */
5157     return 0;
5158 }
5159
5160 static int api_mpls_gre_add_del_tunnel (vat_main_t * vam)
5161 {
5162     unformat_input_t * i = vam->input;
5163     vl_api_mpls_gre_add_del_tunnel_t *mp;
5164     f64 timeout;
5165     u32 inner_vrf_id = 0;
5166     u32 outer_vrf_id = 0;
5167     ip4_address_t src_address;
5168     ip4_address_t dst_address;
5169     ip4_address_t intfc_address;
5170     u32 tmp;
5171     u8 intfc_address_length = 0;
5172     u8 is_add = 1;
5173     u8 l2_only = 0;
5174
5175     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5176         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
5177             ;
5178         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
5179             ;
5180         else if (unformat (i, "src %U", unformat_ip4_address, &src_address))
5181             ;
5182         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
5183             ;
5184         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
5185                            &intfc_address, &tmp))
5186             intfc_address_length = tmp;
5187         else if (unformat (i, "l2-only"))
5188             l2_only = 1;
5189         else if (unformat (i, "del"))
5190             is_add = 0;
5191         else {
5192             clib_warning ("parse error '%U'", format_unformat_error, i);
5193             return -99;
5194         }
5195     }
5196
5197     M(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel);
5198
5199     mp->inner_vrf_id = ntohl(inner_vrf_id);
5200     mp->outer_vrf_id = ntohl(outer_vrf_id);
5201     clib_memcpy(mp->src_address, &src_address, sizeof (src_address));
5202     clib_memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
5203     clib_memcpy(mp->intfc_address, &intfc_address, sizeof (intfc_address));
5204     mp->intfc_address_length = intfc_address_length;
5205     mp->l2_only = l2_only;
5206     mp->is_add = is_add;
5207
5208     S; W;
5209     /* NOTREACHED */
5210     return 0;
5211 }
5212
5213 static int api_mpls_ethernet_add_del_tunnel (vat_main_t * vam)
5214 {
5215     unformat_input_t * i = vam->input;
5216     vl_api_mpls_ethernet_add_del_tunnel_t *mp;
5217     f64 timeout;
5218     u32 inner_vrf_id = 0;
5219     ip4_address_t intfc_address;
5220     u8 dst_mac_address[6];
5221     int dst_set = 1;
5222     u32 tmp;
5223     u8 intfc_address_length = 0;
5224     u8 is_add = 1;
5225     u8 l2_only = 0;
5226     u32 tx_sw_if_index;
5227     int tx_sw_if_index_set = 0;
5228
5229     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5230         if (unformat (i, "vrf %d", &inner_vrf_id))
5231             ;
5232         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
5233                            &intfc_address, &tmp))
5234             intfc_address_length = tmp;
5235         else if (unformat (i, "%U",
5236                            unformat_sw_if_index, vam, &tx_sw_if_index))
5237             tx_sw_if_index_set = 1;
5238         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
5239             tx_sw_if_index_set = 1;
5240         else if (unformat (i, "dst %U", unformat_ethernet_address,
5241                            dst_mac_address))
5242             dst_set = 1;
5243         else if (unformat (i, "l2-only"))
5244             l2_only = 1;
5245         else if (unformat (i, "del"))
5246             is_add = 0;
5247         else {
5248             clib_warning ("parse error '%U'", format_unformat_error, i);
5249             return -99;
5250         }
5251     }
5252
5253     if (!dst_set) {
5254         errmsg ("dst (mac address) not set\n");
5255         return -99;
5256     }
5257     if (!tx_sw_if_index_set) {
5258         errmsg ("tx-intfc not set\n");
5259         return -99;
5260     }
5261
5262     M(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel);
5263
5264     mp->vrf_id = ntohl(inner_vrf_id);
5265     clib_memcpy (mp->adj_address, &intfc_address, sizeof (intfc_address));
5266     mp->adj_address_length = intfc_address_length;
5267     clib_memcpy (mp->dst_mac_address, dst_mac_address, sizeof (dst_mac_address));
5268     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
5269     mp->l2_only = l2_only;
5270     mp->is_add = is_add;
5271
5272     S; W;
5273     /* NOTREACHED */
5274     return 0;
5275 }
5276
5277 static int api_mpls_ethernet_add_del_tunnel_2 (vat_main_t * vam)
5278 {
5279     unformat_input_t * i = vam->input;
5280     vl_api_mpls_ethernet_add_del_tunnel_2_t *mp;
5281     f64 timeout;
5282     u32 inner_vrf_id = 0;
5283     u32 outer_vrf_id = 0;
5284     ip4_address_t adj_address;
5285     int adj_address_set = 0;
5286     ip4_address_t next_hop_address;
5287     int next_hop_address_set = 0;
5288     u32 tmp;
5289     u8 adj_address_length = 0;
5290     u8 l2_only = 0;
5291     u8 is_add = 1;
5292     u32 resolve_attempts = 5;
5293     u8 resolve_if_needed = 1;
5294
5295     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5296         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
5297             ;
5298         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
5299             ;
5300         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
5301                            &adj_address, &tmp)) {
5302             adj_address_length = tmp;
5303             adj_address_set = 1;
5304         }
5305         else if (unformat (i, "next-hop %U", unformat_ip4_address,
5306                            &next_hop_address))
5307             next_hop_address_set = 1;
5308         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
5309             ;
5310         else if (unformat (i, "resolve-if-needed %d", &tmp))
5311             resolve_if_needed = tmp;
5312         else if (unformat (i, "l2-only"))
5313             l2_only = 1;
5314         else if (unformat (i, "del"))
5315             is_add = 0;
5316         else {
5317             clib_warning ("parse error '%U'", format_unformat_error, i);
5318             return -99;
5319         }
5320     }
5321
5322     if (!adj_address_set) {
5323         errmsg ("adjacency address/mask not set\n");
5324         return -99;
5325     }
5326     if (!next_hop_address_set) {
5327         errmsg ("ip4 next hop address (in outer fib) not set\n");
5328         return -99;
5329     }
5330
5331     M(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2);
5332
5333     mp->inner_vrf_id = ntohl(inner_vrf_id);
5334     mp->outer_vrf_id = ntohl(outer_vrf_id);
5335     mp->resolve_attempts = ntohl(resolve_attempts);
5336     mp->resolve_if_needed = resolve_if_needed;
5337     mp->is_add = is_add;
5338     mp->l2_only = l2_only;
5339     clib_memcpy (mp->adj_address, &adj_address, sizeof (adj_address));
5340     mp->adj_address_length = adj_address_length;
5341     clib_memcpy (mp->next_hop_ip4_address_in_outer_vrf, &next_hop_address,
5342             sizeof (next_hop_address));
5343
5344     S; W;
5345     /* NOTREACHED */
5346     return 0;
5347 }
5348
5349 static int api_sw_interface_set_unnumbered (vat_main_t * vam)
5350 {
5351     unformat_input_t * i = vam->input;
5352     vl_api_sw_interface_set_unnumbered_t *mp;
5353     f64 timeout;
5354     u32 sw_if_index;
5355     u32 unnum_sw_index;
5356     u8  is_add = 1;
5357     u8 sw_if_index_set = 0;
5358
5359     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5360         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5361             sw_if_index_set = 1;
5362         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5363             sw_if_index_set = 1;
5364         else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
5365             ;
5366         else if (unformat (i, "del"))
5367             is_add = 0;
5368         else {
5369             clib_warning ("parse error '%U'", format_unformat_error, i);
5370             return -99;
5371         }
5372     }
5373
5374     if (sw_if_index_set == 0) {
5375         errmsg ("missing interface name or sw_if_index\n");
5376         return -99;
5377     }
5378
5379     M(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered);
5380
5381     mp->sw_if_index = ntohl(sw_if_index);
5382     mp->unnumbered_sw_if_index = ntohl(unnum_sw_index);
5383     mp->is_add = is_add;
5384
5385     S; W;
5386     /* NOTREACHED */
5387     return 0;
5388 }
5389
5390 static int api_ip_neighbor_add_del (vat_main_t * vam)
5391 {
5392     unformat_input_t * i = vam->input;
5393     vl_api_ip_neighbor_add_del_t *mp;
5394     f64 timeout;
5395     u32 sw_if_index;
5396     u8 sw_if_index_set = 0;
5397     u32 vrf_id = 0;
5398     u8 is_add = 1;
5399     u8 is_static = 0;
5400     u8 mac_address[6];
5401     u8 mac_set = 0;
5402     u8 v4_address_set = 0;
5403     u8 v6_address_set = 0;
5404     ip4_address_t v4address;
5405     ip6_address_t v6address;
5406
5407     memset (mac_address, 0, sizeof (mac_address));
5408
5409     /* Parse args required to build the message */
5410     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5411         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
5412             mac_set = 1;
5413         }
5414         else if (unformat (i, "del"))
5415             is_add = 0;
5416         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5417             sw_if_index_set = 1;
5418         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5419             sw_if_index_set = 1;
5420         else if (unformat (i, "is_static"))
5421             is_static = 1;
5422         else if (unformat (i, "vrf %d", &vrf_id))
5423             ;
5424         else if (unformat (i, "dst %U",
5425                            unformat_ip4_address, &v4address))
5426                 v4_address_set = 1;
5427         else if (unformat (i, "dst %U",
5428                            unformat_ip6_address, &v6address))
5429                 v6_address_set = 1;
5430         else {
5431             clib_warning ("parse error '%U'", format_unformat_error, i);
5432             return -99;
5433         }
5434     }
5435
5436     if (sw_if_index_set == 0) {
5437         errmsg ("missing interface name or sw_if_index\n");
5438         return -99;
5439     }
5440     if (v4_address_set && v6_address_set) {
5441         errmsg ("both v4 and v6 addresses set\n");
5442         return -99;
5443     }
5444     if (!v4_address_set && !v6_address_set) {
5445         errmsg ("no address set\n");
5446         return -99;
5447     }
5448
5449     /* Construct the API message */
5450     M(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del);
5451
5452     mp->sw_if_index = ntohl (sw_if_index);
5453     mp->is_add = is_add;
5454     mp->vrf_id = ntohl (vrf_id);
5455     mp->is_static = is_static;
5456     if (mac_set)
5457         clib_memcpy (mp->mac_address, mac_address, 6);
5458     if (v6_address_set) {
5459         mp->is_ipv6 = 1;
5460         clib_memcpy (mp->dst_address, &v6address, sizeof (v6address));
5461     } else {
5462         /* mp->is_ipv6 = 0; via memset in M macro above */
5463         clib_memcpy (mp->dst_address, &v4address, sizeof (v4address));
5464     }
5465
5466     /* send it... */
5467     S;
5468
5469     /* Wait for a reply, return good/bad news  */
5470     W;
5471
5472     /* NOTREACHED */
5473     return 0;
5474 }
5475
5476 static int api_reset_vrf (vat_main_t * vam)
5477 {
5478     unformat_input_t * i = vam->input;
5479     vl_api_reset_vrf_t *mp;
5480     f64 timeout;
5481     u32 vrf_id = 0;
5482     u8 is_ipv6 = 0;
5483     u8 vrf_id_set = 0;
5484
5485     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5486         if (unformat (i, "vrf %d", &vrf_id))
5487             vrf_id_set = 1;
5488         else if (unformat (i, "ipv6"))
5489             is_ipv6 = 1;
5490         else {
5491             clib_warning ("parse error '%U'", format_unformat_error, i);
5492             return -99;
5493         }
5494     }
5495
5496     if (vrf_id_set == 0) {
5497         errmsg ("missing vrf id\n");
5498         return -99;
5499     }
5500
5501     M(RESET_VRF, reset_vrf);
5502
5503     mp->vrf_id = ntohl(vrf_id);
5504     mp->is_ipv6 = is_ipv6;
5505
5506     S; W;
5507     /* NOTREACHED */
5508     return 0;
5509 }
5510
5511 static int api_create_vlan_subif (vat_main_t * vam)
5512 {
5513     unformat_input_t * i = vam->input;
5514     vl_api_create_vlan_subif_t *mp;
5515     f64 timeout;
5516     u32 sw_if_index;
5517     u8  sw_if_index_set = 0;
5518     u32 vlan_id;
5519     u8  vlan_id_set = 0;
5520
5521     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5522         if (unformat (i, "sw_if_index %d", &sw_if_index))
5523             sw_if_index_set = 1;
5524         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5525             sw_if_index_set = 1;
5526         else if (unformat (i, "vlan %d", &vlan_id))
5527             vlan_id_set = 1;
5528         else {
5529             clib_warning ("parse error '%U'", format_unformat_error, i);
5530             return -99;
5531         }
5532     }
5533
5534     if (sw_if_index_set == 0) {
5535         errmsg ("missing interface name or sw_if_index\n");
5536         return -99;
5537     }
5538
5539     if (vlan_id_set == 0) {
5540         errmsg ("missing vlan_id\n");
5541         return -99;
5542     }
5543     M(CREATE_VLAN_SUBIF, create_vlan_subif);
5544
5545     mp->sw_if_index = ntohl(sw_if_index);
5546     mp->vlan_id = ntohl(vlan_id);
5547
5548     S; W;
5549     /* NOTREACHED */
5550     return 0;
5551 }
5552
5553 #define foreach_create_subif_bit                \
5554 _(no_tags)                                      \
5555 _(one_tag)                                      \
5556 _(two_tags)                                     \
5557 _(dot1ad)                                       \
5558 _(exact_match)                                  \
5559 _(default_sub)                                  \
5560 _(outer_vlan_id_any)                            \
5561 _(inner_vlan_id_any)
5562
5563 static int api_create_subif (vat_main_t * vam)
5564 {
5565     unformat_input_t * i = vam->input;
5566     vl_api_create_subif_t *mp;
5567     f64 timeout;
5568     u32 sw_if_index;
5569     u8  sw_if_index_set = 0;
5570     u32 sub_id;
5571     u8  sub_id_set = 0;
5572     u32 no_tags = 0;
5573     u32 one_tag = 0;
5574     u32 two_tags = 0;
5575     u32 dot1ad = 0;
5576     u32 exact_match = 0;
5577     u32 default_sub = 0;
5578     u32 outer_vlan_id_any = 0;
5579     u32 inner_vlan_id_any = 0;
5580     u32 tmp;
5581     u16 outer_vlan_id = 0;
5582     u16 inner_vlan_id = 0;
5583
5584     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5585         if (unformat (i, "sw_if_index %d", &sw_if_index))
5586             sw_if_index_set = 1;
5587         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5588             sw_if_index_set = 1;
5589         else if (unformat (i, "sub_id %d", &sub_id))
5590             sub_id_set = 1;
5591         else if (unformat (i, "outer_vlan_id %d", &tmp))
5592             outer_vlan_id = tmp;
5593         else if (unformat (i, "inner_vlan_id %d", &tmp))
5594             inner_vlan_id = tmp;
5595
5596 #define _(a) else if (unformat (i, #a)) a = 1 ;
5597         foreach_create_subif_bit
5598 #undef _
5599
5600         else {
5601             clib_warning ("parse error '%U'", format_unformat_error, i);
5602             return -99;
5603         }
5604     }
5605
5606     if (sw_if_index_set == 0) {
5607         errmsg ("missing interface name or sw_if_index\n");
5608         return -99;
5609     }
5610
5611     if (sub_id_set == 0) {
5612         errmsg ("missing sub_id\n");
5613         return -99;
5614     }
5615     M(CREATE_SUBIF, create_subif);
5616
5617     mp->sw_if_index = ntohl(sw_if_index);
5618     mp->sub_id = ntohl(sub_id);
5619
5620 #define _(a) mp->a = a;
5621     foreach_create_subif_bit;
5622 #undef _
5623
5624     mp->outer_vlan_id = ntohs (outer_vlan_id);
5625     mp->inner_vlan_id = ntohs (inner_vlan_id);
5626
5627     S; W;
5628     /* NOTREACHED */
5629     return 0;
5630 }
5631
5632 static int api_oam_add_del (vat_main_t * vam)
5633 {
5634     unformat_input_t * i = vam->input;
5635     vl_api_oam_add_del_t *mp;
5636     f64 timeout;
5637     u32 vrf_id = 0;
5638     u8 is_add = 1;
5639     ip4_address_t src, dst;
5640     u8 src_set = 0;
5641     u8 dst_set = 0;
5642
5643     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5644         if (unformat (i, "vrf %d", &vrf_id))
5645             ;
5646         else if (unformat (i, "src %U", unformat_ip4_address, &src))
5647             src_set = 1;
5648         else if (unformat (i, "dst %U", unformat_ip4_address, &dst))
5649             dst_set = 1;
5650         else if (unformat (i, "del"))
5651             is_add = 0;
5652         else {
5653             clib_warning ("parse error '%U'", format_unformat_error, i);
5654             return -99;
5655         }
5656     }
5657
5658     if (src_set == 0) {
5659         errmsg ("missing src addr\n");
5660         return -99;
5661     }
5662
5663     if (dst_set == 0) {
5664         errmsg ("missing dst addr\n");
5665         return -99;
5666     }
5667
5668     M(OAM_ADD_DEL, oam_add_del);
5669
5670     mp->vrf_id = ntohl(vrf_id);
5671     mp->is_add = is_add;
5672     clib_memcpy(mp->src_address, &src, sizeof (mp->src_address));
5673     clib_memcpy(mp->dst_address, &dst, sizeof (mp->dst_address));
5674
5675     S; W;
5676     /* NOTREACHED */
5677     return 0;
5678 }
5679
5680 static int api_reset_fib (vat_main_t * vam)
5681 {
5682     unformat_input_t * i = vam->input;
5683     vl_api_reset_fib_t *mp;
5684     f64 timeout;
5685     u32 vrf_id = 0;
5686     u8 is_ipv6 = 0;
5687     u8 vrf_id_set = 0;
5688
5689     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5690         if (unformat (i, "vrf %d", &vrf_id))
5691             vrf_id_set = 1;
5692         else if (unformat (i, "ipv6"))
5693             is_ipv6 = 1;
5694         else {
5695             clib_warning ("parse error '%U'", format_unformat_error, i);
5696             return -99;
5697         }
5698     }
5699
5700     if (vrf_id_set == 0) {
5701         errmsg ("missing vrf id\n");
5702         return -99;
5703     }
5704
5705     M(RESET_FIB, reset_fib);
5706
5707     mp->vrf_id = ntohl(vrf_id);
5708     mp->is_ipv6 = is_ipv6;
5709
5710     S; W;
5711     /* NOTREACHED */
5712     return 0;
5713 }
5714
5715 static int api_dhcp_proxy_config (vat_main_t * vam)
5716 {
5717     unformat_input_t * i = vam->input;
5718     vl_api_dhcp_proxy_config_t *mp;
5719     f64 timeout;
5720     u32 vrf_id = 0;
5721     u8 is_add = 1;
5722     u8 insert_cid = 1;
5723     u8 v4_address_set = 0;
5724     u8 v6_address_set = 0;
5725     ip4_address_t v4address;
5726     ip6_address_t v6address;
5727     u8 v4_src_address_set = 0;
5728     u8 v6_src_address_set = 0;
5729     ip4_address_t v4srcaddress;
5730     ip6_address_t v6srcaddress;
5731
5732     /* Parse args required to build the message */
5733     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5734         if (unformat (i, "del"))
5735             is_add = 0;
5736         else if (unformat (i, "vrf %d", &vrf_id))
5737             ;
5738         else if (unformat (i, "insert-cid %d", &insert_cid))
5739             ;
5740         else if (unformat (i, "svr %U",
5741                            unformat_ip4_address, &v4address))
5742                 v4_address_set = 1;
5743         else if (unformat (i, "svr %U",
5744                            unformat_ip6_address, &v6address))
5745                 v6_address_set = 1;
5746         else if (unformat (i, "src %U",
5747                            unformat_ip4_address, &v4srcaddress))
5748                 v4_src_address_set = 1;
5749         else if (unformat (i, "src %U",
5750                            unformat_ip6_address, &v6srcaddress))
5751                 v6_src_address_set = 1;
5752         else
5753             break;
5754     }
5755
5756     if (v4_address_set && v6_address_set) {
5757         errmsg ("both v4 and v6 server addresses set\n");
5758         return -99;
5759     }
5760     if (!v4_address_set && !v6_address_set) {
5761         errmsg ("no server addresses set\n");
5762         return -99;
5763     }
5764
5765     if (v4_src_address_set && v6_src_address_set) {
5766         errmsg ("both v4 and v6  src addresses set\n");
5767         return -99;
5768     }
5769     if (!v4_src_address_set && !v6_src_address_set) {
5770         errmsg ("no src addresses set\n");
5771         return -99;
5772     }
5773
5774     if (!(v4_src_address_set && v4_address_set) &&
5775         !(v6_src_address_set && v6_address_set)) {
5776         errmsg ("no matching server and src addresses set\n");
5777         return -99;
5778     }
5779
5780     /* Construct the API message */
5781     M(DHCP_PROXY_CONFIG, dhcp_proxy_config);
5782
5783     mp->insert_circuit_id = insert_cid;
5784     mp->is_add = is_add;
5785     mp->vrf_id = ntohl (vrf_id);
5786     if (v6_address_set) {
5787         mp->is_ipv6 = 1;
5788         clib_memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
5789         clib_memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
5790     } else {
5791         clib_memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
5792         clib_memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
5793     }
5794
5795     /* send it... */
5796     S;
5797
5798     /* Wait for a reply, return good/bad news  */
5799     W;
5800     /* NOTREACHED */
5801     return 0;
5802 }
5803
5804 static int api_dhcp_proxy_config_2 (vat_main_t * vam)
5805 {
5806     unformat_input_t * i = vam->input;
5807     vl_api_dhcp_proxy_config_2_t *mp;
5808     f64 timeout;
5809     u32 rx_vrf_id = 0;
5810     u32 server_vrf_id = 0;
5811     u8 is_add = 1;
5812     u8 insert_cid = 1;
5813     u8 v4_address_set = 0;
5814     u8 v6_address_set = 0;
5815     ip4_address_t v4address;
5816     ip6_address_t v6address;
5817     u8 v4_src_address_set = 0;
5818     u8 v6_src_address_set = 0;
5819     ip4_address_t v4srcaddress;
5820     ip6_address_t v6srcaddress;
5821
5822     /* Parse args required to build the message */
5823     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5824         if (unformat (i, "del"))
5825             is_add = 0;
5826         else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
5827             ;
5828         else if (unformat (i, "server_vrf_id %d", &server_vrf_id))
5829             ;
5830         else if (unformat (i, "insert-cid %d", &insert_cid))
5831             ;
5832         else if (unformat (i, "svr %U",
5833                            unformat_ip4_address, &v4address))
5834                 v4_address_set = 1;
5835         else if (unformat (i, "svr %U",
5836                            unformat_ip6_address, &v6address))
5837                 v6_address_set = 1;
5838         else if (unformat (i, "src %U",
5839                            unformat_ip4_address, &v4srcaddress))
5840                 v4_src_address_set = 1;
5841         else if (unformat (i, "src %U",
5842                            unformat_ip6_address, &v6srcaddress))
5843                 v6_src_address_set = 1;
5844         else
5845             break;
5846     }
5847
5848     if (v4_address_set && v6_address_set) {
5849         errmsg ("both v4 and v6 server addresses set\n");
5850         return -99;
5851     }
5852     if (!v4_address_set && !v6_address_set) {
5853         errmsg ("no server addresses set\n");
5854         return -99;
5855     }
5856
5857     if (v4_src_address_set && v6_src_address_set) {
5858         errmsg ("both v4 and v6  src addresses set\n");
5859         return -99;
5860     }
5861     if (!v4_src_address_set && !v6_src_address_set) {
5862         errmsg ("no src addresses set\n");
5863         return -99;
5864     }
5865
5866     if (!(v4_src_address_set && v4_address_set) &&
5867         !(v6_src_address_set && v6_address_set)) {
5868         errmsg ("no matching server and src addresses set\n");
5869         return -99;
5870     }
5871
5872     /* Construct the API message */
5873     M(DHCP_PROXY_CONFIG_2, dhcp_proxy_config_2);
5874
5875     mp->insert_circuit_id = insert_cid;
5876     mp->is_add = is_add;
5877     mp->rx_vrf_id = ntohl (rx_vrf_id);
5878     mp->server_vrf_id = ntohl (server_vrf_id);
5879     if (v6_address_set) {
5880         mp->is_ipv6 = 1;
5881         clib_memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
5882         clib_memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
5883     } else {
5884         clib_memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
5885         clib_memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
5886     }
5887
5888     /* send it... */
5889     S;
5890
5891     /* Wait for a reply, return good/bad news  */
5892     W;
5893     /* NOTREACHED */
5894     return 0;
5895 }
5896
5897 static int api_dhcp_proxy_set_vss (vat_main_t * vam)
5898 {
5899     unformat_input_t * i = vam->input;
5900     vl_api_dhcp_proxy_set_vss_t *mp;
5901     f64 timeout;
5902     u8  is_ipv6 = 0;
5903     u8  is_add = 1;
5904     u32 tbl_id;
5905     u8  tbl_id_set = 0;
5906     u32 oui;
5907     u8  oui_set = 0;
5908     u32 fib_id;
5909     u8  fib_id_set = 0;
5910
5911     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5912         if (unformat (i, "tbl_id %d", &tbl_id))
5913             tbl_id_set = 1;
5914         if (unformat (i, "fib_id %d", &fib_id))
5915             fib_id_set = 1;
5916         if (unformat (i, "oui %d", &oui))
5917             oui_set = 1;
5918         else if (unformat (i, "ipv6"))
5919             is_ipv6 = 1;
5920         else if (unformat (i, "del"))
5921             is_add = 0;
5922         else {
5923             clib_warning ("parse error '%U'", format_unformat_error, i);
5924             return -99;
5925         }
5926     }
5927
5928     if (tbl_id_set == 0) {
5929         errmsg ("missing tbl id\n");
5930         return -99;
5931     }
5932
5933     if (fib_id_set == 0) {
5934         errmsg ("missing fib id\n");
5935         return -99;
5936     }
5937     if (oui_set == 0) {
5938         errmsg ("missing oui\n");
5939         return -99;
5940     }
5941
5942     M(DHCP_PROXY_SET_VSS, dhcp_proxy_set_vss);
5943     mp->tbl_id = ntohl(tbl_id);
5944     mp->fib_id = ntohl(fib_id);
5945     mp->oui = ntohl(oui);
5946     mp->is_ipv6 = is_ipv6;
5947     mp->is_add = is_add;
5948
5949     S; W;
5950     /* NOTREACHED */
5951     return 0;
5952 }
5953
5954 static int api_dhcp_client_config (vat_main_t * vam)
5955 {
5956     unformat_input_t * i = vam->input;
5957     vl_api_dhcp_client_config_t *mp;
5958     f64 timeout;
5959     u32 sw_if_index;
5960     u8 sw_if_index_set = 0;
5961     u8 is_add = 1;
5962     u8 * hostname = 0;
5963     u8 disable_event = 0;
5964
5965     /* Parse args required to build the message */
5966     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5967         if (unformat (i, "del"))
5968             is_add = 0;
5969         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5970             sw_if_index_set = 1;
5971         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5972             sw_if_index_set = 1;
5973         else if (unformat (i, "hostname %s", &hostname))
5974             ;
5975         else if (unformat (i, "disable_event"))
5976             disable_event = 1;
5977         else
5978             break;
5979     }
5980
5981     if (sw_if_index_set == 0) {
5982         errmsg ("missing interface name or sw_if_index\n");
5983         return -99;
5984     }
5985
5986     if (vec_len (hostname) > 63) {
5987         errmsg ("hostname too long\n");
5988     }
5989     vec_add1 (hostname, 0);
5990
5991     /* Construct the API message */
5992     M(DHCP_CLIENT_CONFIG, dhcp_client_config);
5993
5994     mp->sw_if_index = ntohl (sw_if_index);
5995     clib_memcpy (mp->hostname, hostname, vec_len (hostname));
5996     vec_free (hostname);
5997     mp->is_add = is_add;
5998     mp->want_dhcp_event = disable_event ? 0 : 1;
5999     mp->pid = getpid();
6000
6001     /* send it... */
6002     S;
6003
6004     /* Wait for a reply, return good/bad news  */
6005     W;
6006     /* NOTREACHED */
6007     return 0;
6008 }
6009
6010 static int api_set_ip_flow_hash (vat_main_t * vam)
6011 {
6012     unformat_input_t * i = vam->input;
6013     vl_api_set_ip_flow_hash_t *mp;
6014     f64 timeout;
6015     u32 vrf_id = 0;
6016     u8 is_ipv6 = 0;
6017     u8 vrf_id_set = 0;
6018     u8 src = 0;
6019     u8 dst = 0;
6020     u8 sport = 0;
6021     u8 dport = 0;
6022     u8 proto = 0;
6023     u8 reverse = 0;
6024
6025     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6026         if (unformat (i, "vrf %d", &vrf_id))
6027             vrf_id_set = 1;
6028         else if (unformat (i, "ipv6"))
6029             is_ipv6 = 1;
6030         else if (unformat (i, "src"))
6031             src = 1;
6032         else if (unformat (i, "dst"))
6033             dst = 1;
6034         else if (unformat (i, "sport"))
6035             sport = 1;
6036         else if (unformat (i, "dport"))
6037             dport = 1;
6038         else if (unformat (i, "proto"))
6039             proto = 1;
6040         else if (unformat (i, "reverse"))
6041             reverse = 1;
6042
6043         else {
6044             clib_warning ("parse error '%U'", format_unformat_error, i);
6045             return -99;
6046         }
6047     }
6048
6049     if (vrf_id_set == 0) {
6050         errmsg ("missing vrf id\n");
6051         return -99;
6052     }
6053
6054     M(SET_IP_FLOW_HASH, set_ip_flow_hash);
6055     mp->src = src;
6056     mp->dst = dst;
6057     mp->sport = sport;
6058     mp->dport = dport;
6059     mp->proto = proto;
6060     mp->reverse = reverse;
6061     mp->vrf_id = ntohl(vrf_id);
6062     mp->is_ipv6 = is_ipv6;
6063
6064     S; W;
6065     /* NOTREACHED */
6066     return 0;
6067 }
6068
6069 static int api_sw_interface_ip6_enable_disable (vat_main_t * vam)
6070 {
6071     unformat_input_t * i = vam->input;
6072     vl_api_sw_interface_ip6_enable_disable_t *mp;
6073     f64 timeout;
6074     u32 sw_if_index;
6075     u8  sw_if_index_set = 0;
6076     u8  enable = 0;
6077
6078     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6079         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6080             sw_if_index_set = 1;
6081         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6082             sw_if_index_set = 1;
6083         else if (unformat (i, "enable"))
6084             enable = 1;
6085         else if (unformat (i, "disable"))
6086             enable = 0;
6087         else {
6088             clib_warning ("parse error '%U'", format_unformat_error, i);
6089             return -99;
6090         }
6091     }
6092
6093     if (sw_if_index_set == 0) {
6094         errmsg ("missing interface name or sw_if_index\n");
6095         return -99;
6096     }
6097
6098     M(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable);
6099
6100     mp->sw_if_index = ntohl(sw_if_index);
6101     mp->enable = enable;
6102
6103     S; W;
6104     /* NOTREACHED */
6105     return 0;
6106 }
6107
6108 static int api_sw_interface_ip6_set_link_local_address (vat_main_t * vam)
6109 {
6110     unformat_input_t * i = vam->input;
6111     vl_api_sw_interface_ip6_set_link_local_address_t *mp;
6112     f64 timeout;
6113     u32 sw_if_index;
6114     u8 sw_if_index_set = 0;
6115     u32 address_length = 0;
6116     u8 v6_address_set = 0;
6117     ip6_address_t v6address;
6118
6119     /* Parse args required to build the message */
6120     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6121         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6122             sw_if_index_set = 1;
6123         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6124             sw_if_index_set = 1;
6125         else if (unformat (i, "%U/%d",
6126                            unformat_ip6_address, &v6address,
6127                            &address_length))
6128             v6_address_set = 1;
6129         else
6130             break;
6131     }
6132
6133     if (sw_if_index_set == 0) {
6134         errmsg ("missing interface name or sw_if_index\n");
6135         return -99;
6136     }
6137     if (!v6_address_set) {
6138         errmsg ("no address set\n");
6139         return -99;
6140     }
6141
6142     /* Construct the API message */
6143     M(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
6144       sw_interface_ip6_set_link_local_address);
6145
6146     mp->sw_if_index = ntohl (sw_if_index);
6147     clib_memcpy (mp->address, &v6address, sizeof (v6address));
6148     mp->address_length = address_length;
6149
6150     /* send it... */
6151     S;
6152
6153     /* Wait for a reply, return good/bad news  */
6154     W;
6155
6156     /* NOTREACHED */
6157     return 0;
6158 }
6159
6160
6161 static int api_sw_interface_ip6nd_ra_prefix (vat_main_t * vam)
6162 {
6163     unformat_input_t * i = vam->input;
6164     vl_api_sw_interface_ip6nd_ra_prefix_t *mp;
6165     f64 timeout;
6166     u32 sw_if_index;
6167     u8 sw_if_index_set = 0;
6168     u32 address_length = 0;
6169     u8 v6_address_set = 0;
6170     ip6_address_t v6address;
6171     u8 use_default = 0;
6172     u8 no_advertise = 0;
6173     u8 off_link = 0;
6174     u8 no_autoconfig = 0;
6175     u8 no_onlink = 0;
6176     u8 is_no = 0;
6177     u32 val_lifetime = 0;
6178     u32 pref_lifetime = 0;
6179
6180     /* Parse args required to build the message */
6181     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6182         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6183             sw_if_index_set = 1;
6184         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6185             sw_if_index_set = 1;
6186         else if (unformat (i, "%U/%d",
6187                            unformat_ip6_address, &v6address,
6188                            &address_length))
6189             v6_address_set = 1;
6190         else if (unformat (i, "val_life %d", &val_lifetime))
6191             ;
6192         else if (unformat (i, "pref_life %d", &pref_lifetime))
6193             ;
6194         else if (unformat (i, "def"))
6195             use_default = 1;
6196         else if (unformat (i, "noadv"))
6197             no_advertise = 1;
6198         else if (unformat (i, "offl"))
6199             off_link = 1;
6200         else if (unformat (i, "noauto"))
6201             no_autoconfig = 1;
6202         else if (unformat (i, "nolink"))
6203             no_onlink = 1;
6204         else if (unformat (i, "isno"))
6205             is_no = 1;
6206         else {
6207             clib_warning ("parse error '%U'", format_unformat_error, i);
6208             return -99;
6209         }
6210     }
6211
6212     if (sw_if_index_set == 0) {
6213         errmsg ("missing interface name or sw_if_index\n");
6214         return -99;
6215     }
6216     if (!v6_address_set) {
6217         errmsg ("no address set\n");
6218         return -99;
6219     }
6220
6221     /* Construct the API message */
6222     M(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix);
6223
6224     mp->sw_if_index = ntohl (sw_if_index);
6225     clib_memcpy (mp->address, &v6address, sizeof (v6address));
6226     mp->address_length = address_length;
6227     mp->use_default = use_default;
6228     mp->no_advertise = no_advertise;
6229     mp->off_link = off_link;
6230     mp->no_autoconfig = no_autoconfig;
6231     mp->no_onlink = no_onlink;
6232     mp->is_no = is_no;
6233     mp->val_lifetime = ntohl(val_lifetime);
6234     mp->pref_lifetime = ntohl(pref_lifetime);
6235
6236     /* send it... */
6237     S;
6238
6239     /* Wait for a reply, return good/bad news  */
6240     W;
6241
6242     /* NOTREACHED */
6243     return 0;
6244 }
6245
6246 static int api_sw_interface_ip6nd_ra_config (vat_main_t * vam)
6247 {
6248     unformat_input_t * i = vam->input;
6249     vl_api_sw_interface_ip6nd_ra_config_t *mp;
6250     f64 timeout;
6251     u32 sw_if_index;
6252     u8 sw_if_index_set = 0;
6253     u8 suppress = 0;
6254     u8 managed = 0;
6255     u8 other = 0;
6256     u8 ll_option = 0;
6257     u8 send_unicast = 0;
6258     u8 cease = 0;
6259     u8 is_no = 0;
6260     u8 default_router = 0;
6261     u32 max_interval = 0;
6262     u32 min_interval = 0;
6263     u32 lifetime = 0;
6264     u32 initial_count = 0;
6265     u32 initial_interval = 0;
6266
6267
6268     /* Parse args required to build the message */
6269     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6270         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6271             sw_if_index_set = 1;
6272         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6273             sw_if_index_set = 1;
6274         else if (unformat (i, "maxint %d", &max_interval))
6275             ;
6276         else if (unformat (i, "minint %d", &min_interval))
6277             ;
6278         else if (unformat (i, "life %d", &lifetime))
6279             ;
6280         else if (unformat (i, "count %d", &initial_count))
6281             ;
6282         else if (unformat (i, "interval %d", &initial_interval))
6283             ;
6284         else if (unformat (i, "suppress") || unformat (i, "surpress"))
6285             suppress = 1;
6286         else if (unformat (i, "managed"))
6287             managed = 1;
6288         else if (unformat (i, "other"))
6289             other = 1;
6290         else if (unformat (i, "ll"))
6291             ll_option = 1;
6292         else if (unformat (i, "send"))
6293             send_unicast = 1;
6294         else if (unformat (i, "cease"))
6295             cease = 1;
6296         else if (unformat (i, "isno"))
6297             is_no = 1;
6298         else if (unformat (i, "def"))
6299             default_router = 1;
6300         else {
6301             clib_warning ("parse error '%U'", format_unformat_error, i);
6302             return -99;
6303         }
6304     }
6305
6306     if (sw_if_index_set == 0) {
6307         errmsg ("missing interface name or sw_if_index\n");
6308         return -99;
6309     }
6310
6311     /* Construct the API message */
6312     M(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config);
6313
6314     mp->sw_if_index = ntohl (sw_if_index);
6315     mp->max_interval = ntohl(max_interval);
6316     mp->min_interval = ntohl(min_interval);
6317     mp->lifetime = ntohl(lifetime);
6318     mp->initial_count = ntohl(initial_count);
6319     mp->initial_interval = ntohl(initial_interval);
6320     mp->suppress = suppress;
6321     mp->managed = managed;
6322     mp->other = other;
6323     mp->ll_option = ll_option;
6324     mp->send_unicast = send_unicast;
6325     mp->cease = cease;
6326     mp->is_no = is_no;
6327     mp->default_router = default_router;
6328
6329     /* send it... */
6330     S;
6331
6332     /* Wait for a reply, return good/bad news  */
6333     W;
6334
6335     /* NOTREACHED */
6336     return 0;
6337 }
6338
6339 static int api_set_arp_neighbor_limit (vat_main_t * vam)
6340 {
6341     unformat_input_t * i = vam->input;
6342     vl_api_set_arp_neighbor_limit_t *mp;
6343     f64 timeout;
6344     u32 arp_nbr_limit;
6345     u8 limit_set = 0;
6346     u8 is_ipv6 = 0;
6347
6348     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6349         if (unformat (i, "arp_nbr_limit %d", &arp_nbr_limit))
6350             limit_set = 1;
6351         else if (unformat (i, "ipv6"))
6352             is_ipv6 = 1;
6353         else {
6354             clib_warning ("parse error '%U'", format_unformat_error, i);
6355             return -99;
6356         }
6357     }
6358
6359     if (limit_set == 0) {
6360         errmsg ("missing limit value\n");
6361         return -99;
6362     }
6363
6364     M(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit);
6365
6366     mp->arp_neighbor_limit = ntohl(arp_nbr_limit);
6367     mp->is_ipv6 = is_ipv6;
6368
6369     S; W;
6370     /* NOTREACHED */
6371     return 0;
6372 }
6373
6374 static int api_l2_patch_add_del (vat_main_t * vam)
6375 {
6376     unformat_input_t * i = vam->input;
6377     vl_api_l2_patch_add_del_t *mp;
6378     f64 timeout;
6379     u32 rx_sw_if_index;
6380     u8 rx_sw_if_index_set = 0;
6381     u32 tx_sw_if_index;
6382     u8 tx_sw_if_index_set = 0;
6383     u8 is_add = 1;
6384
6385     /* Parse args required to build the message */
6386     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6387         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
6388             rx_sw_if_index_set = 1;
6389         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
6390             tx_sw_if_index_set = 1;
6391         else if (unformat (i, "rx")) {
6392             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6393                 if (unformat (i, "%U", unformat_sw_if_index, vam,
6394                               &rx_sw_if_index))
6395                     rx_sw_if_index_set = 1;
6396             } else
6397                 break;
6398         } else if (unformat (i, "tx")) {
6399             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6400                 if (unformat (i, "%U", unformat_sw_if_index, vam,
6401                               &tx_sw_if_index))
6402                     tx_sw_if_index_set = 1;
6403             } else
6404                 break;
6405         } else if (unformat (i, "del"))
6406             is_add = 0;
6407         else
6408             break;
6409     }
6410
6411     if (rx_sw_if_index_set == 0) {
6412         errmsg ("missing rx interface name or rx_sw_if_index\n");
6413         return -99;
6414     }
6415
6416     if (tx_sw_if_index_set == 0) {
6417         errmsg ("missing tx interface name or tx_sw_if_index\n");
6418         return -99;
6419     }
6420
6421     M(L2_PATCH_ADD_DEL, l2_patch_add_del);
6422
6423     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
6424     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
6425     mp->is_add = is_add;
6426
6427     S; W;
6428     /* NOTREACHED */
6429     return 0;
6430 }
6431 static int api_trace_profile_add (vat_main_t *vam)
6432 {
6433    unformat_input_t * input = vam->input;
6434    vl_api_trace_profile_add_t *mp;
6435    f64 timeout;
6436    u32 id = 0;
6437    u32 trace_option_elts = 0;
6438    u32 trace_type = 0, node_id = 0, app_data = 0, trace_tsp = 2;
6439    int has_pow_option = 0;
6440    int has_ppc_option = 0;
6441
6442   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6443     {
6444       if (unformat (input, "id %d trace-type 0x%x trace-elts %d "
6445                            "trace-tsp %d node-id 0x%x app-data 0x%x",
6446                     &id, &trace_type, &trace_option_elts, &trace_tsp,
6447                       &node_id, &app_data))
6448             ;
6449       else if (unformat (input, "pow"))
6450         has_pow_option = 1;
6451       else if (unformat (input, "ppc encap"))
6452         has_ppc_option = PPC_ENCAP;
6453       else if (unformat (input, "ppc decap"))
6454         has_ppc_option = PPC_DECAP;
6455       else if (unformat (input, "ppc none"))
6456         has_ppc_option = PPC_NONE;
6457       else
6458         break;
6459     }
6460   M(TRACE_PROFILE_ADD, trace_profile_add);
6461   mp->id = htons(id);
6462   mp->trace_type = trace_type;
6463   mp->trace_num_elt = trace_option_elts;
6464   mp->trace_ppc = has_ppc_option;
6465   mp->trace_app_data = htonl(app_data);
6466   mp->pow_enable = has_pow_option;
6467   mp->trace_tsp = trace_tsp;
6468   mp->node_id = htonl(node_id);
6469
6470   S; W;
6471
6472   return(0);
6473
6474 }
6475 static int api_trace_profile_apply (vat_main_t *vam)
6476 {
6477   unformat_input_t * input = vam->input;
6478   vl_api_trace_profile_apply_t *mp;
6479   f64 timeout;
6480   ip6_address_t addr;
6481   u32 mask_width = ~0;
6482   int is_add = 0;
6483   int is_pop = 0;
6484   int is_none = 0;
6485   u32 vrf_id = 0;
6486   u32 id = 0;
6487
6488   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6489     {
6490       if (unformat (input, "%U/%d",
6491                     unformat_ip6_address, &addr, &mask_width))
6492         ;
6493       else if (unformat (input, "id %d", &id))
6494         ;
6495       else if (unformat (input, "vrf-id %d", &vrf_id))
6496         ;
6497       else if (unformat (input, "add"))
6498         is_add = 1;
6499       else if (unformat (input, "pop"))
6500         is_pop = 1;
6501       else if (unformat (input, "none"))
6502         is_none = 1;
6503       else
6504         break;
6505     }
6506
6507   if ((is_add + is_pop + is_none) != 1) {
6508     errmsg("One of (add, pop, none) required");
6509     return -99;
6510   }
6511   if (mask_width == ~0) {
6512     errmsg("<address>/<mask-width> required");
6513     return -99;
6514   }
6515   M(TRACE_PROFILE_APPLY, trace_profile_apply);
6516   clib_memcpy(mp->dest_ipv6, &addr, sizeof(mp->dest_ipv6));
6517   mp->id = htons(id);
6518   mp->prefix_length = htonl(mask_width);
6519   mp->vrf_id = htonl(vrf_id);
6520   if (is_add)
6521     mp->trace_op = IOAM_HBYH_ADD;
6522   else if (is_pop)
6523     mp->trace_op = IOAM_HBYH_POP;
6524   else
6525     mp->trace_op = IOAM_HBYH_MOD;
6526
6527   if(is_none)
6528     mp->enable = 0;
6529   else
6530     mp->enable = 1;
6531
6532   S; W;
6533
6534   return 0;
6535 }
6536
6537 static int api_trace_profile_del (vat_main_t *vam)
6538 {
6539    vl_api_trace_profile_del_t *mp;
6540    f64 timeout;
6541
6542    M(TRACE_PROFILE_DEL, trace_profile_del);
6543    S; W;
6544    return 0;
6545 }
6546
6547 static int api_sr_tunnel_add_del (vat_main_t * vam)
6548 {
6549   unformat_input_t * i = vam->input;
6550   vl_api_sr_tunnel_add_del_t *mp;
6551   f64 timeout;
6552   int is_del = 0;
6553   int pl_index;
6554   ip6_address_t src_address;
6555   int src_address_set = 0;
6556   ip6_address_t dst_address;
6557   u32 dst_mask_width;
6558   int dst_address_set = 0;
6559   u16 flags = 0;
6560   u32 rx_table_id = 0;
6561   u32 tx_table_id = 0;
6562   ip6_address_t * segments = 0;
6563   ip6_address_t * this_seg;
6564   ip6_address_t * tags = 0;
6565   ip6_address_t * this_tag;
6566   ip6_address_t next_address, tag;
6567   u8 * name = 0;
6568   u8 * policy_name = 0;
6569
6570   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
6571     {
6572       if (unformat (i, "del"))
6573         is_del = 1;
6574       else if (unformat (i, "name %s", &name))
6575             ;
6576       else if (unformat (i, "policy %s", &policy_name))
6577             ;
6578       else if (unformat (i, "rx_fib_id %d", &rx_table_id))
6579         ;
6580       else if (unformat (i, "tx_fib_id %d", &tx_table_id))
6581         ;
6582       else if (unformat (i, "src %U", unformat_ip6_address, &src_address))
6583         src_address_set = 1;
6584       else if (unformat (i, "dst %U/%d",
6585                          unformat_ip6_address, &dst_address,
6586                          &dst_mask_width))
6587         dst_address_set = 1;
6588       else if (unformat (i, "next %U", unformat_ip6_address,
6589                          &next_address))
6590         {
6591           vec_add2 (segments, this_seg, 1);
6592           clib_memcpy (this_seg->as_u8, next_address.as_u8, sizeof (*this_seg));
6593         }
6594       else if (unformat (i, "tag %U", unformat_ip6_address,
6595                          &tag))
6596         {
6597           vec_add2 (tags, this_tag, 1);
6598           clib_memcpy (this_tag->as_u8, tag.as_u8, sizeof (*this_tag));
6599         }
6600       else if (unformat (i, "clean"))
6601         flags |= IP6_SR_HEADER_FLAG_CLEANUP;
6602       else if (unformat (i, "protected"))
6603         flags |= IP6_SR_HEADER_FLAG_PROTECTED;
6604       else if (unformat (i, "InPE %d", &pl_index))
6605         {
6606           if (pl_index <= 0 || pl_index > 4)
6607             {
6608             pl_index_range_error:
6609               errmsg ("pl index %d out of range\n", pl_index);
6610               return -99;
6611             }
6612           flags |= IP6_SR_HEADER_FLAG_PL_ELT_INGRESS_PE << (3*(pl_index - 1));
6613         }
6614       else if (unformat (i, "EgPE %d", &pl_index))
6615         {
6616           if (pl_index <= 0 || pl_index > 4)
6617             goto pl_index_range_error;
6618           flags |= IP6_SR_HEADER_FLAG_PL_ELT_EGRESS_PE << (3*(pl_index - 1));
6619         }
6620       else if (unformat (i, "OrgSrc %d", &pl_index))
6621         {
6622           if (pl_index <= 0 || pl_index > 4)
6623             goto pl_index_range_error;
6624           flags |= IP6_SR_HEADER_FLAG_PL_ELT_ORIG_SRC_ADDR << (3*(pl_index - 1));
6625         }
6626       else
6627         break;
6628     }
6629
6630   if (!src_address_set)
6631     {
6632       errmsg ("src address required\n");
6633       return -99;
6634     }
6635
6636   if (!dst_address_set)
6637     {
6638       errmsg ("dst address required\n");
6639       return -99;
6640     }
6641
6642   if (!segments)
6643     {
6644       errmsg ("at least one sr segment required\n");
6645       return -99;
6646     }
6647
6648   M2(SR_TUNNEL_ADD_DEL, sr_tunnel_add_del,
6649      vec_len(segments) * sizeof (ip6_address_t)
6650      + vec_len(tags) * sizeof (ip6_address_t));
6651
6652   clib_memcpy (mp->src_address, &src_address, sizeof (mp->src_address));
6653   clib_memcpy (mp->dst_address, &dst_address, sizeof (mp->dst_address));
6654   mp->dst_mask_width = dst_mask_width;
6655   mp->flags_net_byte_order = clib_host_to_net_u16 (flags);
6656   mp->n_segments = vec_len (segments);
6657   mp->n_tags = vec_len (tags);
6658   mp->is_add = is_del == 0;
6659   clib_memcpy (mp->segs_and_tags, segments,
6660           vec_len(segments)* sizeof (ip6_address_t));
6661   clib_memcpy (mp->segs_and_tags + vec_len(segments)*sizeof (ip6_address_t),
6662           tags, vec_len(tags)* sizeof (ip6_address_t));
6663
6664   mp->outer_vrf_id = ntohl (rx_table_id);
6665   mp->inner_vrf_id = ntohl (tx_table_id);
6666   memcpy (mp->name, name, vec_len(name));
6667   memcpy (mp->policy_name, policy_name, vec_len(policy_name));
6668
6669   vec_free (segments);
6670   vec_free (tags);
6671
6672   S; W;
6673   /* NOTREACHED */
6674 }
6675
6676 static int api_sr_policy_add_del (vat_main_t * vam)
6677 {
6678   unformat_input_t * input = vam->input;
6679   vl_api_sr_policy_add_del_t *mp;
6680   f64 timeout;
6681   int is_del = 0;
6682   u8 * name = 0;
6683   u8 * tunnel_name = 0;
6684   u8 ** tunnel_names = 0;
6685
6686   int name_set = 0 ;
6687   int tunnel_set = 0;
6688   int j = 0;
6689   int tunnel_names_length = 1; // Init to 1 to offset the #tunnel_names counter byte
6690   int tun_name_len = 0; // Different naming convention used as confusing these would be "bad" (TM)
6691
6692   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6693     {
6694       if (unformat (input, "del"))
6695         is_del = 1;
6696       else if (unformat (input, "name %s", &name))
6697         name_set = 1;
6698       else if (unformat (input, "tunnel %s", &tunnel_name))
6699         {
6700           if (tunnel_name)
6701             {
6702               vec_add1 (tunnel_names, tunnel_name);
6703               /* For serializer:
6704                  - length = #bytes to store in serial vector
6705                  - +1 = byte to store that length
6706               */
6707               tunnel_names_length += (vec_len (tunnel_name) + 1);
6708               tunnel_set = 1;
6709               tunnel_name = 0;
6710             }
6711         }
6712       else
6713         break;
6714     }
6715
6716   if (!name_set)
6717     {
6718       errmsg ("policy name required\n");
6719       return -99;
6720     }
6721
6722   if ((!tunnel_set) && (!is_del))
6723     {
6724       errmsg ("tunnel name required\n");
6725       return -99;
6726     }
6727
6728   M2(SR_POLICY_ADD_DEL, sr_policy_add_del, tunnel_names_length);
6729
6730
6731
6732   mp->is_add = !is_del;
6733
6734   memcpy (mp->name, name, vec_len(name));
6735   // Since mp->tunnel_names is of type u8[0] and not a u8 *, u8 ** needs to be serialized
6736   u8 * serial_orig = 0;
6737   vec_validate (serial_orig, tunnel_names_length);
6738   *serial_orig = vec_len(tunnel_names); // Store the number of tunnels as length in first byte of serialized vector
6739   serial_orig += 1; // Move along one byte to store the length of first tunnel_name
6740
6741   for (j=0; j < vec_len(tunnel_names); j++)
6742     {
6743       tun_name_len = vec_len (tunnel_names[j]);
6744       *serial_orig = tun_name_len; // Store length of tunnel name in first byte of Length/Value pair
6745       serial_orig += 1; // Move along one byte to store the actual tunnel name
6746       memcpy (serial_orig, tunnel_names[j], tun_name_len);
6747       serial_orig += tun_name_len; // Advance past the copy
6748     }
6749   memcpy (mp->tunnel_names, serial_orig - tunnel_names_length, tunnel_names_length); // Regress serial_orig to head then copy fwd
6750
6751   vec_free (tunnel_names);
6752   vec_free (tunnel_name);
6753
6754   S; W;
6755   /* NOTREACHED */
6756 }
6757
6758 static int api_sr_multicast_map_add_del (vat_main_t * vam)
6759 {
6760   unformat_input_t * input = vam->input;
6761   vl_api_sr_multicast_map_add_del_t *mp;
6762   f64 timeout;
6763   int is_del = 0;
6764   ip6_address_t multicast_address;
6765   u8 * policy_name = 0;
6766   int multicast_address_set = 0;
6767
6768   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6769     {
6770       if (unformat (input, "del"))
6771         is_del = 1;
6772       else if (unformat (input, "address %U", unformat_ip6_address, &multicast_address))
6773         multicast_address_set = 1;
6774       else if (unformat (input, "sr-policy %s", &policy_name))
6775         ;
6776       else
6777         break;
6778     }
6779
6780   if (!is_del && !policy_name)
6781     {
6782       errmsg ("sr-policy name required\n");
6783       return -99;
6784     }
6785
6786
6787   if (!multicast_address_set)
6788     {
6789       errmsg ("address required\n");
6790       return -99;
6791     }
6792
6793   M(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del);
6794
6795   mp->is_add = !is_del;
6796   memcpy (mp->policy_name, policy_name, vec_len(policy_name));
6797   clib_memcpy (mp->multicast_address, &multicast_address, sizeof (mp->multicast_address));
6798
6799
6800   vec_free (policy_name);
6801
6802   S; W;
6803   /* NOTREACHED */
6804 }
6805
6806
6807 #define foreach_ip4_proto_field                 \
6808 _(src_address)                                  \
6809 _(dst_address)                                  \
6810 _(tos)                                          \
6811 _(length)                                       \
6812 _(fragment_id)                                  \
6813 _(ttl)                                          \
6814 _(protocol)                                     \
6815 _(checksum)
6816
6817 uword unformat_ip4_mask (unformat_input_t * input, va_list * args)
6818 {
6819   u8 ** maskp = va_arg (*args, u8 **);
6820   u8 * mask = 0;
6821   u8 found_something = 0;
6822   ip4_header_t * ip;
6823
6824 #define _(a) u8 a=0;
6825   foreach_ip4_proto_field;
6826 #undef _
6827   u8 version = 0;
6828   u8 hdr_length = 0;
6829
6830
6831   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6832     {
6833       if (unformat (input, "version"))
6834         version = 1;
6835       else if (unformat (input, "hdr_length"))
6836         hdr_length = 1;
6837       else if (unformat (input, "src"))
6838         src_address = 1;
6839       else if (unformat (input, "dst"))
6840         dst_address = 1;
6841       else if (unformat (input, "proto"))
6842         protocol = 1;
6843
6844 #define _(a) else if (unformat (input, #a)) a=1;
6845       foreach_ip4_proto_field
6846 #undef _
6847       else
6848         break;
6849     }
6850
6851 #define _(a) found_something += a;
6852   foreach_ip4_proto_field;
6853 #undef _
6854
6855   if (found_something == 0)
6856     return 0;
6857
6858   vec_validate (mask, sizeof (*ip) - 1);
6859
6860   ip = (ip4_header_t *) mask;
6861
6862 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
6863   foreach_ip4_proto_field;
6864 #undef _
6865
6866   ip->ip_version_and_header_length = 0;
6867
6868   if (version)
6869     ip->ip_version_and_header_length |= 0xF0;
6870
6871   if (hdr_length)
6872     ip->ip_version_and_header_length |= 0x0F;
6873
6874   *maskp = mask;
6875   return 1;
6876 }
6877
6878 #define foreach_ip6_proto_field                 \
6879 _(src_address)                                  \
6880 _(dst_address)                                  \
6881 _(payload_length)                               \
6882 _(hop_limit)                                    \
6883 _(protocol)
6884
6885 uword unformat_ip6_mask (unformat_input_t * input, va_list * args)
6886 {
6887   u8 ** maskp = va_arg (*args, u8 **);
6888   u8 * mask = 0;
6889   u8 found_something = 0;
6890   ip6_header_t * ip;
6891   u32 ip_version_traffic_class_and_flow_label;
6892
6893 #define _(a) u8 a=0;
6894   foreach_ip6_proto_field;
6895 #undef _
6896   u8 version = 0;
6897   u8 traffic_class = 0;
6898   u8 flow_label = 0;
6899
6900   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6901     {
6902       if (unformat (input, "version"))
6903         version = 1;
6904       else if (unformat (input, "traffic-class"))
6905         traffic_class = 1;
6906       else if (unformat (input, "flow-label"))
6907         flow_label = 1;
6908       else if (unformat (input, "src"))
6909         src_address = 1;
6910       else if (unformat (input, "dst"))
6911         dst_address = 1;
6912       else if (unformat (input, "proto"))
6913         protocol = 1;
6914
6915 #define _(a) else if (unformat (input, #a)) a=1;
6916       foreach_ip6_proto_field
6917 #undef _
6918       else
6919         break;
6920     }
6921
6922 #define _(a) found_something += a;
6923   foreach_ip6_proto_field;
6924 #undef _
6925
6926   if (found_something == 0)
6927     return 0;
6928
6929   vec_validate (mask, sizeof (*ip) - 1);
6930
6931   ip = (ip6_header_t *) mask;
6932
6933 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
6934   foreach_ip6_proto_field;
6935 #undef _
6936
6937   ip_version_traffic_class_and_flow_label = 0;
6938
6939   if (version)
6940     ip_version_traffic_class_and_flow_label |= 0xF0000000;
6941
6942   if (traffic_class)
6943     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
6944
6945   if (flow_label)
6946     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
6947
6948   ip->ip_version_traffic_class_and_flow_label =
6949     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
6950
6951   *maskp = mask;
6952   return 1;
6953 }
6954
6955 uword unformat_l3_mask (unformat_input_t * input, va_list * args)
6956 {
6957   u8 ** maskp = va_arg (*args, u8 **);
6958
6959   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6960     if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
6961       return 1;
6962     else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
6963       return 1;
6964     else
6965       break;
6966   }
6967   return 0;
6968 }
6969
6970 uword unformat_l2_mask (unformat_input_t * input, va_list * args)
6971 {
6972   u8 ** maskp = va_arg (*args, u8 **);
6973   u8 * mask = 0;
6974   u8 src = 0;
6975   u8 dst = 0;
6976   u8 proto = 0;
6977   u8 tag1 = 0;
6978   u8 tag2 = 0;
6979   u8 ignore_tag1 = 0;
6980   u8 ignore_tag2 = 0;
6981   u8 cos1 = 0;
6982   u8 cos2 = 0;
6983   u8 dot1q = 0;
6984   u8 dot1ad = 0;
6985   int len = 14;
6986
6987   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6988     if (unformat (input, "src"))
6989       src = 1;
6990     else if (unformat (input, "dst"))
6991       dst = 1;
6992     else if (unformat (input, "proto"))
6993       proto = 1;
6994     else if (unformat (input, "tag1"))
6995       tag1 = 1;
6996     else if (unformat (input, "tag2"))
6997       tag2 = 1;
6998     else if (unformat (input, "ignore-tag1"))
6999       ignore_tag1 = 1;
7000     else if (unformat (input, "ignore-tag2"))
7001       ignore_tag2 = 1;
7002     else if (unformat (input, "cos1"))
7003       cos1 = 1;
7004     else if (unformat (input, "cos2"))
7005       cos2 = 1;
7006     else if (unformat (input, "dot1q"))
7007       dot1q = 1;
7008     else if (unformat (input, "dot1ad"))
7009       dot1ad = 1;
7010     else
7011       break;
7012   }
7013   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
7014       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7015     return 0;
7016
7017   if (tag1 || ignore_tag1 || cos1 || dot1q)
7018     len = 18;
7019   if (tag2 || ignore_tag2 || cos2 || dot1ad)
7020     len = 22;
7021
7022   vec_validate (mask, len-1);
7023
7024   if (dst)
7025     memset (mask, 0xff, 6);
7026
7027   if (src)
7028     memset (mask + 6, 0xff, 6);
7029
7030   if (tag2 || dot1ad)
7031     {
7032       /* inner vlan tag */
7033       if (tag2)
7034         {
7035           mask[19] = 0xff;
7036           mask[18] = 0x0f;
7037         }
7038       if (cos2)
7039         mask[18] |= 0xe0;
7040       if (proto)
7041           mask[21] = mask [20] = 0xff;
7042       if (tag1)
7043         {
7044           mask [15] = 0xff;
7045           mask [14] = 0x0f;
7046         }
7047       if (cos1)
7048         mask[14] |= 0xe0;
7049       *maskp = mask;
7050       return 1;
7051     }
7052   if (tag1 | dot1q)
7053     {
7054       if (tag1)
7055         {
7056           mask [15] = 0xff;
7057           mask [14] = 0x0f;
7058         }
7059       if (cos1)
7060         mask[14] |= 0xe0;
7061       if (proto)
7062           mask[16] = mask [17] = 0xff;
7063
7064       *maskp = mask;
7065       return 1;
7066     }
7067   if (cos2)
7068     mask[18] |= 0xe0;
7069   if (cos1)
7070     mask[14] |= 0xe0;
7071   if (proto)
7072     mask[12] = mask [13] = 0xff;
7073
7074   *maskp = mask;
7075   return 1;
7076 }
7077
7078 uword unformat_classify_mask (unformat_input_t * input, va_list * args)
7079 {
7080   u8 ** maskp = va_arg (*args, u8 **);
7081   u32 * skipp = va_arg (*args, u32 *);
7082   u32 * matchp = va_arg (*args, u32 *);
7083   u32 match;
7084   u8 * mask = 0;
7085   u8 * l2 = 0;
7086   u8 * l3 = 0;
7087   int i;
7088
7089   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
7090     if (unformat (input, "hex %U", unformat_hex_string, &mask))
7091       ;
7092     else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
7093       ;
7094     else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
7095       ;
7096     else
7097       break;
7098   }
7099
7100   if (mask || l2 || l3)
7101     {
7102       if (l2 || l3)
7103         {
7104           /* "With a free Ethernet header in every package" */
7105           if (l2 == 0)
7106             vec_validate (l2, 13);
7107           mask = l2;
7108           vec_append (mask, l3);
7109           vec_free (l3);
7110         }
7111
7112       /* Scan forward looking for the first significant mask octet */
7113       for (i = 0; i < vec_len (mask); i++)
7114         if (mask[i])
7115           break;
7116
7117       /* compute (skip, match) params */
7118       *skipp = i / sizeof(u32x4);
7119       vec_delete (mask, *skipp * sizeof(u32x4), 0);
7120
7121       /* Pad mask to an even multiple of the vector size */
7122       while (vec_len (mask) % sizeof (u32x4))
7123         vec_add1 (mask, 0);
7124
7125       match = vec_len (mask) / sizeof (u32x4);
7126
7127       for (i = match*sizeof(u32x4); i > 0; i-= sizeof(u32x4))
7128         {
7129           u64 *tmp = (u64 *)(mask + (i-sizeof(u32x4)));
7130           if (*tmp || *(tmp+1))
7131             break;
7132           match--;
7133         }
7134       if (match == 0)
7135         clib_warning ("BUG: match 0");
7136
7137       _vec_len (mask) = match * sizeof(u32x4);
7138
7139       *matchp = match;
7140       *maskp = mask;
7141
7142       return 1;
7143     }
7144
7145   return 0;
7146 }
7147
7148 #define foreach_l2_next                         \
7149 _(drop, DROP)                                   \
7150 _(ethernet, ETHERNET_INPUT)                     \
7151 _(ip4, IP4_INPUT)                               \
7152 _(ip6, IP6_INPUT)
7153
7154 uword unformat_l2_next_index (unformat_input_t * input, va_list * args)
7155 {
7156   u32 * miss_next_indexp = va_arg (*args, u32 *);
7157   u32 next_index = 0;
7158   u32 tmp;
7159
7160 #define _(n,N) \
7161   if (unformat (input, #n)) { next_index = L2_CLASSIFY_NEXT_##N; goto out;}
7162   foreach_l2_next;
7163 #undef _
7164
7165   if (unformat (input, "%d", &tmp))
7166     {
7167       next_index = tmp;
7168       goto out;
7169     }
7170
7171   return 0;
7172
7173  out:
7174   *miss_next_indexp = next_index;
7175   return 1;
7176 }
7177
7178 #define foreach_ip_next                         \
7179 _(miss, MISS)                                   \
7180 _(drop, DROP)                                   \
7181 _(local, LOCAL)                                 \
7182 _(rewrite, REWRITE)
7183
7184 uword unformat_ip_next_index (unformat_input_t * input, va_list * args)
7185 {
7186   u32 * miss_next_indexp = va_arg (*args, u32 *);
7187   u32 next_index = 0;
7188   u32 tmp;
7189
7190 #define _(n,N) \
7191   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
7192   foreach_ip_next;
7193 #undef _
7194
7195   if (unformat (input, "%d", &tmp))
7196     {
7197       next_index = tmp;
7198       goto out;
7199     }
7200
7201   return 0;
7202
7203  out:
7204   *miss_next_indexp = next_index;
7205   return 1;
7206 }
7207
7208 #define foreach_acl_next                        \
7209 _(deny, DENY)
7210
7211 uword unformat_acl_next_index (unformat_input_t * input, va_list * args)
7212 {
7213   u32 * miss_next_indexp = va_arg (*args, u32 *);
7214   u32 next_index = 0;
7215   u32 tmp;
7216
7217 #define _(n,N) \
7218   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
7219   foreach_acl_next;
7220 #undef _
7221
7222   if (unformat (input, "permit"))
7223     {
7224       next_index = ~0;
7225       goto out;
7226     }
7227   else if (unformat (input, "%d", &tmp))
7228     {
7229       next_index = tmp;
7230       goto out;
7231     }
7232
7233   return 0;
7234
7235  out:
7236   *miss_next_indexp = next_index;
7237   return 1;
7238 }
7239
7240 uword unformat_policer_precolor (unformat_input_t * input, va_list * args)
7241 {
7242   u32 * r = va_arg (*args, u32 *);
7243
7244   if (unformat (input, "conform-color"))
7245     *r = POLICE_CONFORM;
7246   else if (unformat (input, "exceed-color"))
7247     *r = POLICE_EXCEED;
7248   else
7249     return 0;
7250
7251   return 1;
7252 }
7253
7254 static int api_classify_add_del_table (vat_main_t * vam)
7255 {
7256   unformat_input_t * i = vam->input;
7257   vl_api_classify_add_del_table_t *mp;
7258
7259   u32 nbuckets = 2;
7260   u32 skip = ~0;
7261   u32 match = ~0;
7262   int is_add = 1;
7263   u32 table_index = ~0;
7264   u32 next_table_index = ~0;
7265   u32 miss_next_index = ~0;
7266   u32 memory_size = 32<<20;
7267   u8 * mask = 0;
7268   f64 timeout;
7269
7270   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7271     if (unformat (i, "del"))
7272       is_add = 0;
7273     else if (unformat (i, "buckets %d", &nbuckets))
7274       ;
7275     else if (unformat (i, "memory_size %d", &memory_size))
7276       ;
7277     else if (unformat (i, "skip %d", &skip))
7278       ;
7279     else if (unformat (i, "match %d", &match))
7280       ;
7281     else if (unformat (i, "table %d", &table_index))
7282       ;
7283     else if (unformat (i, "mask %U", unformat_classify_mask,
7284                        &mask, &skip, &match))
7285       ;
7286     else if (unformat (i, "next-table %d", &next_table_index))
7287       ;
7288     else if (unformat (i, "miss-next %U", unformat_ip_next_index,
7289                        &miss_next_index))
7290       ;
7291     else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
7292                        &miss_next_index))
7293       ;
7294     else if (unformat (i, "acl-miss-next %U", unformat_acl_next_index,
7295                        &miss_next_index))
7296       ;
7297     else
7298       break;
7299   }
7300
7301   if (is_add && mask == 0) {
7302       errmsg ("Mask required\n");
7303       return -99;
7304   }
7305
7306   if (is_add && skip == ~0) {
7307       errmsg ("skip count required\n");
7308       return -99;
7309   }
7310
7311   if (is_add && match == ~0) {
7312       errmsg ("match count required\n");
7313       return -99;
7314   }
7315
7316   if (!is_add && table_index == ~0) {
7317       errmsg ("table index required for delete\n");
7318       return -99;
7319   }
7320
7321   M2 (CLASSIFY_ADD_DEL_TABLE, classify_add_del_table,
7322       vec_len(mask));
7323
7324   mp->is_add = is_add;
7325   mp->table_index = ntohl(table_index);
7326   mp->nbuckets = ntohl(nbuckets);
7327   mp->memory_size = ntohl(memory_size);
7328   mp->skip_n_vectors = ntohl(skip);
7329   mp->match_n_vectors = ntohl(match);
7330   mp->next_table_index = ntohl(next_table_index);
7331   mp->miss_next_index = ntohl(miss_next_index);
7332   clib_memcpy (mp->mask, mask, vec_len(mask));
7333
7334   vec_free(mask);
7335
7336   S; W;
7337   /* NOTREACHED */
7338 }
7339
7340 uword unformat_ip4_match (unformat_input_t * input, va_list * args)
7341 {
7342   u8 ** matchp = va_arg (*args, u8 **);
7343   u8 * match = 0;
7344   ip4_header_t * ip;
7345   int version = 0;
7346   u32 version_val;
7347   int hdr_length = 0;
7348   u32 hdr_length_val;
7349   int src = 0, dst = 0;
7350   ip4_address_t src_val, dst_val;
7351   int proto = 0;
7352   u32 proto_val;
7353   int tos = 0;
7354   u32 tos_val;
7355   int length = 0;
7356   u32 length_val;
7357   int fragment_id = 0;
7358   u32 fragment_id_val;
7359   int ttl = 0;
7360   int ttl_val;
7361   int checksum = 0;
7362   u32 checksum_val;
7363
7364   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7365     {
7366       if (unformat (input, "version %d", &version_val))
7367         version = 1;
7368       else if (unformat (input, "hdr_length %d", &hdr_length_val))
7369         hdr_length = 1;
7370       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
7371         src = 1;
7372       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
7373         dst = 1;
7374       else if (unformat (input, "proto %d", &proto_val))
7375         proto = 1;
7376       else if (unformat (input, "tos %d", &tos_val))
7377         tos = 1;
7378       else if (unformat (input, "length %d", &length_val))
7379         length = 1;
7380       else if (unformat (input, "fragment_id %d", &fragment_id_val))
7381         fragment_id = 1;
7382       else if (unformat (input, "ttl %d", &ttl_val))
7383         ttl = 1;
7384       else if (unformat (input, "checksum %d", &checksum_val))
7385         checksum = 1;
7386       else
7387         break;
7388     }
7389
7390   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
7391       + ttl + checksum == 0)
7392     return 0;
7393
7394   /*
7395    * Aligned because we use the real comparison functions
7396    */
7397   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
7398
7399   ip = (ip4_header_t *) match;
7400
7401   /* These are realistically matched in practice */
7402   if (src)
7403     ip->src_address.as_u32 = src_val.as_u32;
7404
7405   if (dst)
7406     ip->dst_address.as_u32 = dst_val.as_u32;
7407
7408   if (proto)
7409     ip->protocol = proto_val;
7410
7411
7412   /* These are not, but they're included for completeness */
7413   if (version)
7414     ip->ip_version_and_header_length |= (version_val & 0xF)<<4;
7415
7416   if (hdr_length)
7417     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
7418
7419   if (tos)
7420     ip->tos = tos_val;
7421
7422   if (length)
7423     ip->length = length_val;
7424
7425   if (ttl)
7426     ip->ttl = ttl_val;
7427
7428   if (checksum)
7429     ip->checksum = checksum_val;
7430
7431   *matchp = match;
7432   return 1;
7433 }
7434
7435 uword unformat_ip6_match (unformat_input_t * input, va_list * args)
7436 {
7437   u8 ** matchp = va_arg (*args, u8 **);
7438   u8 * match = 0;
7439   ip6_header_t * ip;
7440   int version = 0;
7441   u32 version_val;
7442   u8  traffic_class;
7443   u32 traffic_class_val;
7444   u8  flow_label;
7445   u8  flow_label_val;
7446   int src = 0, dst = 0;
7447   ip6_address_t src_val, dst_val;
7448   int proto = 0;
7449   u32 proto_val;
7450   int payload_length = 0;
7451   u32 payload_length_val;
7452   int hop_limit = 0;
7453   int hop_limit_val;
7454   u32 ip_version_traffic_class_and_flow_label;
7455
7456   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
7457     {
7458       if (unformat (input, "version %d", &version_val))
7459         version = 1;
7460       else if (unformat (input, "traffic_class %d", &traffic_class_val))
7461         traffic_class = 1;
7462       else if (unformat (input, "flow_label %d", &flow_label_val))
7463         flow_label = 1;
7464       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
7465         src = 1;
7466       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
7467         dst = 1;
7468       else if (unformat (input, "proto %d", &proto_val))
7469         proto = 1;
7470       else if (unformat (input, "payload_length %d", &payload_length_val))
7471         payload_length = 1;
7472       else if (unformat (input, "hop_limit %d", &hop_limit_val))
7473         hop_limit = 1;
7474       else
7475         break;
7476     }
7477
7478   if (version + traffic_class + flow_label + src + dst + proto +
7479       payload_length + hop_limit == 0)
7480     return 0;
7481
7482   /*
7483    * Aligned because we use the real comparison functions
7484    */
7485   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
7486
7487   ip = (ip6_header_t *) match;
7488
7489   if (src)
7490     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
7491
7492   if (dst)
7493     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
7494
7495   if (proto)
7496     ip->protocol = proto_val;
7497
7498   ip_version_traffic_class_and_flow_label = 0;
7499
7500   if (version)
7501     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
7502
7503   if (traffic_class)
7504     ip_version_traffic_class_and_flow_label |= (traffic_class_val & 0xFF) << 20;
7505
7506   if (flow_label)
7507     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
7508
7509   ip->ip_version_traffic_class_and_flow_label =
7510     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
7511
7512   if (payload_length)
7513     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
7514
7515   if (hop_limit)
7516     ip->hop_limit = hop_limit_val;
7517
7518   *matchp = match;
7519   return 1;
7520 }
7521
7522 uword unformat_l3_match (unformat_input_t * input, va_list * args)
7523 {
7524   u8 ** matchp = va_arg (*args, u8 **);
7525
7526   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
7527     if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
7528       return 1;
7529     else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
7530       return 1;
7531     else
7532       break;
7533   }
7534   return 0;
7535 }
7536
7537 uword unformat_vlan_tag (unformat_input_t * input, va_list * args)
7538 {
7539   u8 * tagp = va_arg (*args, u8 *);
7540   u32 tag;
7541
7542   if (unformat(input, "%d", &tag))
7543     {
7544       tagp[0] = (tag>>8) & 0x0F;
7545       tagp[1] = tag & 0xFF;
7546       return 1;
7547     }
7548
7549   return 0;
7550 }
7551
7552 uword unformat_l2_match (unformat_input_t * input, va_list * args)
7553 {
7554   u8 ** matchp = va_arg (*args, u8 **);
7555   u8 * match = 0;
7556   u8 src = 0;
7557   u8 src_val[6];
7558   u8 dst = 0;
7559   u8 dst_val[6];
7560   u8 proto = 0;
7561   u16 proto_val;
7562   u8 tag1 = 0;
7563   u8 tag1_val [2];
7564   u8 tag2 = 0;
7565   u8 tag2_val [2];
7566   int len = 14;
7567   u8 ignore_tag1 = 0;
7568   u8 ignore_tag2 = 0;
7569   u8 cos1 = 0;
7570   u8 cos2 = 0;
7571   u32 cos1_val = 0;
7572   u32 cos2_val = 0;
7573
7574   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
7575     if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
7576       src = 1;
7577     else if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
7578       dst = 1;
7579     else if (unformat (input, "proto %U",
7580                        unformat_ethernet_type_host_byte_order, &proto_val))
7581       proto = 1;
7582     else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
7583       tag1 = 1;
7584     else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
7585       tag2 = 1;
7586     else if (unformat (input, "ignore-tag1"))
7587       ignore_tag1 = 1;
7588     else if (unformat (input, "ignore-tag2"))
7589       ignore_tag2 = 1;
7590     else if (unformat (input, "cos1 %d", &cos1_val))
7591       cos1 = 1;
7592     else if (unformat (input, "cos2 %d", &cos2_val))
7593       cos2 = 1;
7594     else
7595       break;
7596   }
7597   if ((src + dst + proto + tag1 + tag2 +
7598       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
7599     return 0;
7600
7601   if (tag1 || ignore_tag1 || cos1)
7602     len = 18;
7603   if (tag2 || ignore_tag2 || cos2)
7604     len = 22;
7605
7606   vec_validate_aligned (match, len-1, sizeof(u32x4));
7607
7608   if (dst)
7609     clib_memcpy (match, dst_val, 6);
7610
7611   if (src)
7612     clib_memcpy (match + 6, src_val, 6);
7613
7614   if (tag2)
7615     {
7616       /* inner vlan tag */
7617       match[19] = tag2_val[1];
7618       match[18] = tag2_val[0];
7619       if (cos2)
7620         match [18] |= (cos2_val & 0x7) << 5;
7621       if (proto)
7622         {
7623           match[21] = proto_val & 0xff;
7624           match[20] = proto_val >> 8;
7625         }
7626       if (tag1)
7627         {
7628           match [15] = tag1_val[1];
7629           match [14] = tag1_val[0];
7630         }
7631       if (cos1)
7632         match [14] |= (cos1_val & 0x7) << 5;
7633       *matchp = match;
7634       return 1;
7635     }
7636   if (tag1)
7637     {
7638       match [15] = tag1_val[1];
7639       match [14] = tag1_val[0];
7640       if (proto)
7641         {
7642           match[17] = proto_val & 0xff;
7643           match[16] = proto_val >> 8;
7644         }
7645       if (cos1)
7646         match [14] |= (cos1_val & 0x7) << 5;
7647
7648       *matchp = match;
7649       return 1;
7650     }
7651   if (cos2)
7652     match [18] |= (cos2_val & 0x7) << 5;
7653   if (cos1)
7654     match [14] |= (cos1_val & 0x7) << 5;
7655   if (proto)
7656     {
7657       match[13] = proto_val & 0xff;
7658       match[12] = proto_val >> 8;
7659     }
7660
7661   *matchp = match;
7662   return 1;
7663 }
7664
7665
7666 uword unformat_classify_match (unformat_input_t * input, va_list * args)
7667 {
7668   u8 ** matchp = va_arg (*args, u8 **);
7669   u32 skip_n_vectors = va_arg (*args, u32);
7670   u32 match_n_vectors = va_arg (*args, u32);
7671
7672   u8 * match = 0;
7673   u8 * l2 = 0;
7674   u8 * l3 = 0;
7675
7676   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
7677     if (unformat (input, "hex %U", unformat_hex_string, &match))
7678       ;
7679     else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
7680       ;
7681     else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
7682       ;
7683     else
7684       break;
7685   }
7686
7687   if (match || l2 || l3)
7688     {
7689       if (l2 || l3)
7690         {
7691           /* "Win a free Ethernet header in every packet" */
7692           if (l2 == 0)
7693             vec_validate_aligned (l2, 13, sizeof(u32x4));
7694           match = l2;
7695           vec_append_aligned (match, l3, sizeof(u32x4));
7696           vec_free (l3);
7697         }
7698
7699       /* Make sure the vector is big enough even if key is all 0's */
7700       vec_validate_aligned
7701           (match, ((match_n_vectors + skip_n_vectors) * sizeof(u32x4)) - 1,
7702            sizeof(u32x4));
7703
7704       /* Set size, include skipped vectors*/
7705       _vec_len (match) = (match_n_vectors+skip_n_vectors) * sizeof(u32x4);
7706
7707       *matchp = match;
7708
7709       return 1;
7710     }
7711
7712   return 0;
7713 }
7714
7715 static int api_classify_add_del_session (vat_main_t * vam)
7716 {
7717     unformat_input_t * i = vam->input;
7718     vl_api_classify_add_del_session_t *mp;
7719     int is_add = 1;
7720     u32 table_index = ~0;
7721     u32 hit_next_index = ~0;
7722     u32 opaque_index = ~0;
7723     u8 * match = 0;
7724     i32 advance = 0;
7725     f64 timeout;
7726     u32 skip_n_vectors = 0;
7727     u32 match_n_vectors = 0;
7728
7729     /*
7730      * Warning: you have to supply skip_n and match_n
7731      * because the API client cant simply look at the classify
7732      * table object.
7733      */
7734
7735     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7736         if (unformat (i, "del"))
7737             is_add = 0;
7738         else if (unformat (i, "hit-next %U", unformat_ip_next_index,
7739                            &hit_next_index))
7740             ;
7741         else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
7742                            &hit_next_index))
7743             ;
7744         else if (unformat (i, "acl-hit-next %U", unformat_acl_next_index,
7745                            &hit_next_index))
7746             ;
7747         else if (unformat (i, "policer-hit-next %d", &hit_next_index))
7748             ;
7749         else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index))
7750             ;
7751         else if (unformat (i, "opaque-index %d", &opaque_index))
7752             ;
7753         else if (unformat (i, "skip_n %d", &skip_n_vectors))
7754             ;
7755         else if (unformat (i, "match_n %d", &match_n_vectors))
7756             ;
7757         else if (unformat (i, "match %U", unformat_classify_match,
7758                            &match, skip_n_vectors, match_n_vectors))
7759             ;
7760         else if (unformat (i, "advance %d", &advance))
7761             ;
7762         else if (unformat (i, "table-index %d", &table_index))
7763             ;
7764         else
7765             break;
7766     }
7767
7768     if (table_index == ~0) {
7769         errmsg ("Table index required\n");
7770         return -99;
7771     }
7772
7773     if (is_add && match == 0) {
7774         errmsg ("Match value required\n");
7775         return -99;
7776     }
7777
7778     M2 (CLASSIFY_ADD_DEL_SESSION, classify_add_del_session,
7779         vec_len(match));
7780
7781     mp->is_add = is_add;
7782     mp->table_index = ntohl(table_index);
7783     mp->hit_next_index = ntohl(hit_next_index);
7784     mp->opaque_index = ntohl(opaque_index);
7785     mp->advance = ntohl(advance);
7786     clib_memcpy (mp->match, match, vec_len(match));
7787     vec_free(match);
7788
7789     S; W;
7790     /* NOTREACHED */
7791 }
7792
7793 static int api_classify_set_interface_ip_table (vat_main_t * vam)
7794 {
7795     unformat_input_t * i = vam->input;
7796     vl_api_classify_set_interface_ip_table_t *mp;
7797     f64 timeout;
7798     u32 sw_if_index;
7799     int sw_if_index_set;
7800     u32 table_index = ~0;
7801     u8  is_ipv6 = 0;
7802
7803     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7804         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7805             sw_if_index_set = 1;
7806         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7807             sw_if_index_set = 1;
7808         else if (unformat (i, "table %d", &table_index))
7809             ;
7810         else {
7811             clib_warning ("parse error '%U'", format_unformat_error, i);
7812             return -99;
7813         }
7814     }
7815
7816     if (sw_if_index_set == 0) {
7817         errmsg ("missing interface name or sw_if_index\n");
7818         return -99;
7819     }
7820
7821
7822     M(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table);
7823
7824     mp->sw_if_index = ntohl(sw_if_index);
7825     mp->table_index = ntohl(table_index);
7826     mp->is_ipv6 = is_ipv6;
7827
7828     S; W;
7829     /* NOTREACHED */
7830     return 0;
7831 }
7832
7833 static int api_classify_set_interface_l2_tables (vat_main_t * vam)
7834 {
7835     unformat_input_t * i = vam->input;
7836     vl_api_classify_set_interface_l2_tables_t *mp;
7837     f64 timeout;
7838     u32 sw_if_index;
7839     int sw_if_index_set;
7840     u32 ip4_table_index = ~0;
7841     u32 ip6_table_index = ~0;
7842     u32 other_table_index = ~0;
7843
7844     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7845         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7846             sw_if_index_set = 1;
7847         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7848             sw_if_index_set = 1;
7849         else if (unformat (i, "ip4-table %d", &ip4_table_index))
7850             ;
7851         else if (unformat (i, "ip6-table %d", &ip6_table_index))
7852             ;
7853         else if (unformat (i, "other-table %d", &other_table_index))
7854             ;
7855         else {
7856             clib_warning ("parse error '%U'", format_unformat_error, i);
7857             return -99;
7858         }
7859     }
7860
7861     if (sw_if_index_set == 0) {
7862         errmsg ("missing interface name or sw_if_index\n");
7863         return -99;
7864     }
7865
7866
7867     M(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables);
7868
7869     mp->sw_if_index = ntohl(sw_if_index);
7870     mp->ip4_table_index = ntohl(ip4_table_index);
7871     mp->ip6_table_index = ntohl(ip6_table_index);
7872     mp->other_table_index = ntohl(other_table_index);
7873
7874
7875     S; W;
7876     /* NOTREACHED */
7877     return 0;
7878 }
7879
7880 static int api_ipfix_enable (vat_main_t * vam)
7881 {
7882     unformat_input_t * i = vam->input;
7883     vl_api_ipfix_enable_t *mp;
7884     ip4_address_t collector_address;
7885     u8 collector_address_set = 0;
7886     u32 collector_port = ~0;
7887     ip4_address_t src_address;
7888     u8 src_address_set = 0;
7889     u32 vrf_id = ~0;
7890     u32 path_mtu = ~0;
7891     u32 template_interval = ~0;
7892     f64 timeout;
7893
7894     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7895         if (unformat (i, "collector_address %U", unformat_ip4_address,
7896             &collector_address))
7897             collector_address_set = 1;
7898         else if (unformat (i, "collector_port %d", &collector_port))
7899             ;
7900         else if (unformat (i, "src_address %U", unformat_ip4_address,
7901                  &src_address))
7902             src_address_set = 1;
7903         else if (unformat (i, "vrf_id %d", &vrf_id))
7904             ;
7905         else if (unformat (i, "path_mtu %d", &path_mtu))
7906             ;
7907         else if (unformat (i, "template_interval %d", &template_interval))
7908             ;
7909         else
7910             break;
7911     }
7912
7913     if (collector_address_set == 0) {
7914         errmsg ("collector_address required\n");
7915         return -99;
7916     }
7917
7918     if (src_address_set == 0) {
7919         errmsg ("src_address required\n");
7920         return -99;
7921     }
7922
7923     M (IPFIX_ENABLE, ipfix_enable);
7924
7925     memcpy(mp->collector_address, collector_address.data,
7926            sizeof(collector_address.data));
7927     mp->collector_port = htons((u16)collector_port);
7928     memcpy(mp->src_address, src_address.data,
7929            sizeof(src_address.data));
7930     mp->vrf_id = htonl(vrf_id);
7931     mp->path_mtu = htonl(path_mtu);
7932     mp->template_interval = htonl(template_interval);
7933
7934     S; W;
7935     /* NOTREACHED */
7936 }
7937
7938 static int api_get_node_index (vat_main_t * vam)
7939 {
7940     unformat_input_t * i = vam->input;
7941     vl_api_get_node_index_t * mp;
7942     f64 timeout;
7943     u8 * name = 0;
7944
7945     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7946         if (unformat (i, "node %s", &name))
7947             ;
7948         else
7949             break;
7950     }
7951     if (name == 0) {
7952         errmsg ("node name required\n");
7953         return -99;
7954     }
7955     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
7956         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
7957         return -99;
7958     }
7959
7960     M(GET_NODE_INDEX, get_node_index);
7961     clib_memcpy (mp->node_name, name, vec_len(name));
7962     vec_free(name);
7963
7964     S; W;
7965     /* NOTREACHED */
7966     return 0;
7967 }
7968
7969 static int api_get_next_index (vat_main_t * vam)
7970 {
7971     unformat_input_t * i = vam->input;
7972     vl_api_get_next_index_t * mp;
7973     f64 timeout;
7974     u8 * node_name = 0, * next_node_name = 0;
7975
7976     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7977         if (unformat (i, "node-name %s", &node_name))
7978             ;
7979         else if (unformat (i, "next-node-name %s", &next_node_name))
7980             break;
7981     }
7982
7983     if (node_name == 0) {
7984         errmsg ("node name required\n");
7985         return -99;
7986     }
7987     if (vec_len (node_name) >= ARRAY_LEN(mp->node_name)) {
7988         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
7989         return -99;
7990     }
7991
7992     if (next_node_name == 0) {
7993         errmsg ("next node name required\n");
7994         return -99;
7995     }
7996     if (vec_len (next_node_name) >= ARRAY_LEN(mp->next_name)) {
7997         errmsg ("next node name too long, max %d\n", ARRAY_LEN(mp->next_name));
7998         return -99;
7999     }
8000
8001     M(GET_NEXT_INDEX, get_next_index);
8002     clib_memcpy (mp->node_name, node_name, vec_len(node_name));
8003     clib_memcpy (mp->next_name, next_node_name, vec_len(next_node_name));
8004     vec_free(node_name);
8005     vec_free(next_node_name);
8006
8007     S; W;
8008     /* NOTREACHED */
8009     return 0;
8010 }
8011
8012 static int api_add_node_next (vat_main_t * vam)
8013 {
8014     unformat_input_t * i = vam->input;
8015     vl_api_add_node_next_t * mp;
8016     f64 timeout;
8017     u8 * name = 0;
8018     u8 * next = 0;
8019
8020     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8021         if (unformat (i, "node %s", &name))
8022             ;
8023         else if (unformat (i, "next %s", &next))
8024             ;
8025         else
8026             break;
8027     }
8028     if (name == 0) {
8029         errmsg ("node name required\n");
8030         return -99;
8031     }
8032     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
8033         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
8034         return -99;
8035     }
8036     if (next == 0) {
8037         errmsg ("next node required\n");
8038         return -99;
8039     }
8040     if (vec_len (next) >= ARRAY_LEN(mp->next_name)) {
8041         errmsg ("next name too long, max %d\n", ARRAY_LEN(mp->next_name));
8042         return -99;
8043     }
8044
8045     M(ADD_NODE_NEXT, add_node_next);
8046     clib_memcpy (mp->node_name, name, vec_len(name));
8047     clib_memcpy (mp->next_name, next, vec_len(next));
8048     vec_free(name);
8049     vec_free(next);
8050
8051     S; W;
8052     /* NOTREACHED */
8053     return 0;
8054 }
8055
8056 static int api_l2tpv3_create_tunnel (vat_main_t * vam)
8057 {
8058     unformat_input_t * i = vam->input;
8059     ip6_address_t client_address, our_address;
8060     int client_address_set = 0;
8061     int our_address_set = 0;
8062     u32 local_session_id = 0;
8063     u32 remote_session_id = 0;
8064     u64 local_cookie = 0;
8065     u64 remote_cookie = 0;
8066     u8 l2_sublayer_present = 0;
8067     vl_api_l2tpv3_create_tunnel_t * mp;
8068     f64 timeout;
8069
8070     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8071         if (unformat (i, "client_address %U", unformat_ip6_address,
8072                       &client_address))
8073             client_address_set = 1;
8074         else if (unformat (i, "our_address %U", unformat_ip6_address,
8075                            &our_address))
8076             our_address_set = 1;
8077         else if (unformat (i, "local_session_id %d", &local_session_id))
8078             ;
8079         else if (unformat (i, "remote_session_id %d", &remote_session_id))
8080             ;
8081         else if (unformat (i, "local_cookie %lld", &local_cookie))
8082             ;
8083         else if (unformat (i, "remote_cookie %lld", &remote_cookie))
8084             ;
8085         else if (unformat (i, "l2-sublayer-present"))
8086             l2_sublayer_present = 1;
8087         else
8088             break;
8089     }
8090
8091     if (client_address_set == 0) {
8092         errmsg ("client_address required\n");
8093         return -99;
8094     }
8095
8096     if (our_address_set == 0) {
8097         errmsg ("our_address required\n");
8098         return -99;
8099     }
8100
8101     M(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel);
8102
8103     clib_memcpy (mp->client_address, client_address.as_u8,
8104             sizeof (mp->client_address));
8105
8106     clib_memcpy (mp->our_address, our_address.as_u8,
8107             sizeof (mp->our_address));
8108
8109     mp->local_session_id = ntohl (local_session_id);
8110     mp->remote_session_id = ntohl (remote_session_id);
8111     mp->local_cookie = clib_host_to_net_u64 (local_cookie);
8112     mp->remote_cookie = clib_host_to_net_u64 (remote_cookie);
8113     mp->l2_sublayer_present = l2_sublayer_present;
8114     mp->is_ipv6 = 1;
8115
8116     S; W;
8117     /* NOTREACHED */
8118     return 0;
8119 }
8120
8121 static int api_l2tpv3_set_tunnel_cookies (vat_main_t * vam)
8122 {
8123     unformat_input_t * i = vam->input;
8124     u32 sw_if_index;
8125     u8  sw_if_index_set = 0;
8126     u64 new_local_cookie = 0;
8127     u64 new_remote_cookie = 0;
8128     vl_api_l2tpv3_set_tunnel_cookies_t *mp;
8129     f64 timeout;
8130
8131     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8132         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8133             sw_if_index_set = 1;
8134         else if (unformat (i, "sw_if_index %d", &sw_if_index))
8135             sw_if_index_set = 1;
8136         else if (unformat (i, "new_local_cookie %lld", &new_local_cookie))
8137             ;
8138         else if (unformat (i, "new_remote_cookie %lld", &new_remote_cookie))
8139             ;
8140         else
8141             break;
8142     }
8143
8144     if (sw_if_index_set == 0) {
8145         errmsg ("missing interface name or sw_if_index\n");
8146         return -99;
8147     }
8148
8149     M(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies);
8150
8151     mp->sw_if_index = ntohl(sw_if_index);
8152     mp->new_local_cookie = clib_host_to_net_u64 (new_local_cookie);
8153     mp->new_remote_cookie = clib_host_to_net_u64 (new_remote_cookie);
8154
8155     S; W;
8156     /* NOTREACHED */
8157     return 0;
8158 }
8159
8160 static int api_l2tpv3_interface_enable_disable (vat_main_t * vam)
8161 {
8162     unformat_input_t * i = vam->input;
8163     vl_api_l2tpv3_interface_enable_disable_t *mp;
8164     f64 timeout;
8165     u32 sw_if_index;
8166     u8  sw_if_index_set = 0;
8167     u8  enable_disable = 1;
8168
8169     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8170         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8171             sw_if_index_set = 1;
8172         else if (unformat (i, "sw_if_index %d", &sw_if_index))
8173             sw_if_index_set = 1;
8174         else if (unformat (i, "enable"))
8175             enable_disable = 1;
8176         else if (unformat (i, "disable"))
8177             enable_disable = 0;
8178         else
8179             break;
8180     }
8181
8182     if (sw_if_index_set == 0) {
8183         errmsg ("missing interface name or sw_if_index\n");
8184         return -99;
8185     }
8186
8187     M(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable);
8188
8189     mp->sw_if_index = ntohl(sw_if_index);
8190     mp->enable_disable = enable_disable;
8191
8192     S; W;
8193     /* NOTREACHED */
8194     return 0;
8195 }
8196
8197 static int api_l2tpv3_set_lookup_key (vat_main_t * vam)
8198 {
8199     unformat_input_t * i = vam->input;
8200     vl_api_l2tpv3_set_lookup_key_t * mp;
8201     f64 timeout;
8202     u8 key = ~0;
8203
8204     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8205         if (unformat (i, "lookup_v6_src"))
8206             key = L2T_LOOKUP_SRC_ADDRESS;
8207         else if (unformat (i, "lookup_v6_dst"))
8208             key = L2T_LOOKUP_DST_ADDRESS;
8209         else if (unformat (i, "lookup_session_id"))
8210             key = L2T_LOOKUP_SESSION_ID;
8211         else
8212             break;
8213     }
8214
8215     if (key == (u8) ~0) {
8216         errmsg ("l2tp session lookup key unset\n");
8217         return -99;
8218     }
8219
8220     M(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key);
8221
8222     mp->key = key;
8223
8224     S; W;
8225     /* NOTREACHED */
8226     return 0;
8227 }
8228
8229 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler
8230 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
8231 {
8232     vat_main_t * vam = &vat_main;
8233
8234     fformat(vam->ofp,  "* %U (our) %U (client) (sw_if_index %d)\n",
8235               format_ip6_address, mp->our_address,
8236               format_ip6_address, mp->client_address,
8237               clib_net_to_host_u32(mp->sw_if_index));
8238
8239     fformat (vam->ofp, "   local cookies %016llx %016llx remote cookie %016llx\n",
8240               clib_net_to_host_u64 (mp->local_cookie[0]),
8241               clib_net_to_host_u64 (mp->local_cookie[1]),
8242               clib_net_to_host_u64 (mp->remote_cookie));
8243
8244     fformat (vam->ofp, "   local session-id %d remote session-id %d\n",
8245               clib_net_to_host_u32 (mp->local_session_id),
8246               clib_net_to_host_u32 (mp->remote_session_id));
8247
8248     fformat (vam->ofp, "   l2 specific sublayer %s\n\n",
8249               mp->l2_sublayer_present ? "preset" : "absent");
8250
8251 }
8252
8253 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler_json
8254 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
8255 {
8256     vat_main_t * vam = &vat_main;
8257     vat_json_node_t *node = NULL;
8258     struct in6_addr addr;
8259
8260     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8261         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8262         vat_json_init_array(&vam->json_tree);
8263     }
8264     node = vat_json_array_add(&vam->json_tree);
8265
8266     vat_json_init_object(node);
8267
8268     clib_memcpy(&addr, mp->our_address, sizeof(addr));
8269     vat_json_object_add_ip6(node, "our_address", addr);
8270     clib_memcpy(&addr, mp->client_address, sizeof(addr));
8271     vat_json_object_add_ip6(node, "client_address", addr);
8272
8273     vat_json_node_t * lc = vat_json_object_add(node, "local_cookie");
8274     vat_json_init_array(lc);
8275     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[0]));
8276     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[1]));
8277     vat_json_object_add_uint(node, "remote_cookie", clib_net_to_host_u64(mp->remote_cookie));
8278
8279     printf("local id: %u", clib_net_to_host_u32(mp->local_session_id));
8280     vat_json_object_add_uint(node, "local_session_id", clib_net_to_host_u32(mp->local_session_id));
8281     vat_json_object_add_uint(node, "remote_session_id", clib_net_to_host_u32(mp->remote_session_id));
8282     vat_json_object_add_string_copy(node, "l2_sublayer", mp->l2_sublayer_present ?
8283             (u8*)"present" : (u8*)"absent");
8284 }
8285
8286 static int api_sw_if_l2tpv3_tunnel_dump (vat_main_t * vam)
8287 {
8288     vl_api_sw_if_l2tpv3_tunnel_dump_t *mp;
8289     f64 timeout;
8290
8291     /* Get list of l2tpv3-tunnel interfaces */
8292     M(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump);
8293     S;
8294
8295     /* Use a control ping for synchronization */
8296     {
8297         vl_api_control_ping_t * mp;
8298         M(CONTROL_PING, control_ping);
8299         S;
8300     }
8301     W;
8302 }
8303
8304
8305 static void vl_api_sw_interface_tap_details_t_handler
8306 (vl_api_sw_interface_tap_details_t * mp)
8307 {
8308     vat_main_t * vam = &vat_main;
8309
8310     fformat(vam->ofp,  "%-16s %d\n",
8311               mp->dev_name,
8312               clib_net_to_host_u32(mp->sw_if_index));
8313 }
8314
8315 static void vl_api_sw_interface_tap_details_t_handler_json
8316 (vl_api_sw_interface_tap_details_t * mp)
8317 {
8318     vat_main_t * vam = &vat_main;
8319     vat_json_node_t *node = NULL;
8320
8321     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8322         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8323         vat_json_init_array(&vam->json_tree);
8324     }
8325     node = vat_json_array_add(&vam->json_tree);
8326
8327     vat_json_init_object(node);
8328     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
8329     vat_json_object_add_string_copy(node, "dev_name", mp->dev_name);
8330 }
8331
8332 static int api_sw_interface_tap_dump (vat_main_t * vam)
8333 {
8334     vl_api_sw_interface_tap_dump_t *mp;
8335     f64 timeout;
8336
8337     fformat(vam->ofp,  "\n%-16s %s\n", "dev_name", "sw_if_index");
8338     /* Get list of tap interfaces */
8339     M(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump);
8340     S;
8341
8342     /* Use a control ping for synchronization */
8343     {
8344         vl_api_control_ping_t * mp;
8345         M(CONTROL_PING, control_ping);
8346         S;
8347     }
8348     W;
8349 }
8350
8351 static uword unformat_vxlan_decap_next
8352 (unformat_input_t * input, va_list * args)
8353 {
8354   u32 * result = va_arg (*args, u32 *);
8355   u32 tmp;
8356
8357   if (unformat (input, "drop"))
8358     *result = VXLAN_INPUT_NEXT_DROP;
8359   else if (unformat (input, "ip4"))
8360     *result = VXLAN_INPUT_NEXT_IP4_INPUT;
8361   else if (unformat (input, "ip6"))
8362     *result = VXLAN_INPUT_NEXT_IP6_INPUT;
8363   else if (unformat (input, "l2"))
8364     *result = VXLAN_INPUT_NEXT_L2_INPUT;
8365   else if (unformat (input, "%d", &tmp))
8366     *result = tmp;
8367   else
8368     return 0;
8369   return 1;
8370 }
8371
8372 static int api_vxlan_add_del_tunnel (vat_main_t * vam)
8373 {
8374     unformat_input_t * line_input = vam->input;
8375     vl_api_vxlan_add_del_tunnel_t *mp;
8376     f64 timeout;
8377     ip4_address_t src4, dst4;
8378     ip6_address_t src6, dst6;
8379     u8 is_add = 1;
8380     u8 ipv4_set = 0, ipv6_set = 0;
8381     u8 src_set = 0;
8382     u8 dst_set = 0;
8383     u32 encap_vrf_id = 0;
8384     u32 decap_next_index = ~0;
8385     u32 vni = 0;
8386
8387     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8388         if (unformat (line_input, "del"))
8389             is_add = 0;
8390         else if (unformat (line_input, "src %U",
8391                            unformat_ip4_address, &src4))
8392           {
8393             ipv4_set = 1;
8394             src_set = 1;
8395           }
8396         else if (unformat (line_input, "dst %U",
8397                            unformat_ip4_address, &dst4))
8398           {
8399             ipv4_set = 1;
8400             dst_set = 1;
8401           }
8402         else if (unformat (line_input, "src %U",
8403                            unformat_ip6_address, &src6))
8404           {
8405             ipv6_set = 1;
8406             src_set = 1;
8407           }
8408         else if (unformat (line_input, "dst %U",
8409                            unformat_ip6_address, &dst6))
8410           {
8411             ipv6_set = 1;
8412             dst_set = 1;
8413           }
8414         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
8415             ;
8416         else if (unformat (line_input, "decap-next %U",
8417                            unformat_vxlan_decap_next, &decap_next_index))
8418             ;
8419         else if (unformat (line_input, "vni %d", &vni))
8420             ;
8421         else {
8422             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
8423             return -99;
8424         }
8425     }
8426
8427     if (src_set == 0) {
8428         errmsg ("tunnel src address not specified\n");
8429         return -99;
8430     }
8431     if (dst_set == 0) {
8432         errmsg ("tunnel dst address not specified\n");
8433         return -99;
8434     }
8435
8436     if (ipv4_set && ipv6_set) {
8437         errmsg ("both IPv4 and IPv6 addresses specified");
8438         return -99;
8439     }
8440
8441     if ((vni == 0) || (vni>>24)) {
8442         errmsg ("vni not specified or out of range\n");
8443         return -99;
8444     }
8445
8446     M (VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel);
8447
8448     if (ipv6_set) {
8449         clib_memcpy(&mp->src_address, &src6, sizeof(src6));
8450         clib_memcpy(&mp->dst_address, &dst6, sizeof(dst6));
8451     } else {
8452         clib_memcpy(&mp->src_address, &src4, sizeof(src4));
8453         clib_memcpy(&mp->dst_address, &dst4, sizeof(dst4));
8454     }
8455     mp->encap_vrf_id = ntohl(encap_vrf_id);
8456     mp->decap_next_index = ntohl(decap_next_index);
8457     mp->vni = ntohl(vni);
8458     mp->is_add = is_add;
8459     mp->is_ipv6 = ipv6_set;
8460
8461     S; W;
8462     /* NOTREACHED */
8463     return 0;
8464 }
8465
8466 static void vl_api_vxlan_tunnel_details_t_handler
8467 (vl_api_vxlan_tunnel_details_t * mp)
8468 {
8469     vat_main_t * vam = &vat_main;
8470
8471     fformat(vam->ofp, "%11d%24U%24U%14d%18d%13d\n",
8472             ntohl(mp->sw_if_index),
8473             format_ip46_address, &(mp->src_address[0]),
8474             IP46_TYPE_ANY,
8475             format_ip46_address, &(mp->dst_address[0]),
8476             IP46_TYPE_ANY,
8477             ntohl(mp->encap_vrf_id),
8478             ntohl(mp->decap_next_index),
8479             ntohl(mp->vni));
8480 }
8481
8482 static void vl_api_vxlan_tunnel_details_t_handler_json
8483 (vl_api_vxlan_tunnel_details_t * mp)
8484 {
8485     vat_main_t * vam = &vat_main;
8486     vat_json_node_t *node = NULL;
8487     struct in_addr ip4;
8488     struct in6_addr ip6;
8489
8490     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8491         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8492         vat_json_init_array(&vam->json_tree);
8493     }
8494     node = vat_json_array_add(&vam->json_tree);
8495
8496     vat_json_init_object(node);
8497     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
8498     if (mp->is_ipv6) {
8499         clib_memcpy(&ip6, &(mp->src_address[0]), sizeof(ip6));
8500         vat_json_object_add_ip6(node, "src_address", ip6);
8501         clib_memcpy(&ip6, &(mp->dst_address[0]), sizeof(ip6));
8502         vat_json_object_add_ip6(node, "dst_address", ip6);
8503     } else {
8504         clib_memcpy(&ip4, &(mp->src_address[0]), sizeof(ip4));
8505         vat_json_object_add_ip4(node, "src_address", ip4);
8506         clib_memcpy(&ip4, &(mp->dst_address[0]), sizeof(ip4));
8507         vat_json_object_add_ip4(node, "dst_address", ip4);
8508     }
8509     vat_json_object_add_uint(node, "encap_vrf_id", ntohl(mp->encap_vrf_id));
8510     vat_json_object_add_uint(node, "decap_next_index", ntohl(mp->decap_next_index));
8511     vat_json_object_add_uint(node, "vni", ntohl(mp->vni));
8512     vat_json_object_add_uint(node, "is_ipv6", mp->is_ipv6 ? 1 : 0);
8513 }
8514
8515 static int api_vxlan_tunnel_dump (vat_main_t * vam)
8516 {
8517     unformat_input_t * i = vam->input;
8518     vl_api_vxlan_tunnel_dump_t *mp;
8519     f64 timeout;
8520     u32 sw_if_index;
8521     u8 sw_if_index_set = 0;
8522
8523     /* Parse args required to build the message */
8524     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8525         if (unformat (i, "sw_if_index %d", &sw_if_index))
8526             sw_if_index_set = 1;
8527         else
8528             break;
8529     }
8530
8531     if (sw_if_index_set == 0) {
8532         sw_if_index = ~0;
8533     }
8534
8535     if (!vam->json_output) {
8536         fformat(vam->ofp, "%11s%24s%24s%14s%18s%13s\n",
8537                 "sw_if_index", "src_address", "dst_address",
8538                 "encap_vrf_id", "decap_next_index", "vni");
8539     }
8540
8541     /* Get list of vxlan-tunnel interfaces */
8542     M(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump);
8543
8544     mp->sw_if_index = htonl(sw_if_index);
8545
8546     S;
8547
8548     /* Use a control ping for synchronization */
8549     {
8550         vl_api_control_ping_t * mp;
8551         M(CONTROL_PING, control_ping);
8552         S;
8553     }
8554     W;
8555 }
8556
8557 static int api_gre_add_del_tunnel (vat_main_t * vam)
8558 {
8559     unformat_input_t * line_input = vam->input;
8560     vl_api_gre_add_del_tunnel_t *mp;
8561     f64 timeout;
8562     ip4_address_t src4, dst4;
8563     u8 is_add = 1;
8564     u8 src_set = 0;
8565     u8 dst_set = 0;
8566     u32 outer_fib_id = 0;
8567
8568     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8569         if (unformat (line_input, "del"))
8570             is_add = 0;
8571         else if (unformat (line_input, "src %U",
8572                            unformat_ip4_address, &src4))
8573             src_set = 1;
8574         else if (unformat (line_input, "dst %U",
8575                            unformat_ip4_address, &dst4))
8576             dst_set = 1;
8577         else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id))
8578             ;
8579         else {
8580             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
8581             return -99;
8582         }
8583     }
8584
8585     if (src_set == 0) {
8586         errmsg ("tunnel src address not specified\n");
8587         return -99;
8588     }
8589     if (dst_set == 0) {
8590         errmsg ("tunnel dst address not specified\n");
8591         return -99;
8592     }
8593
8594
8595     M (GRE_ADD_DEL_TUNNEL, gre_add_del_tunnel);
8596
8597     clib_memcpy(&mp->src_address, &src4, sizeof(src4));
8598     clib_memcpy(&mp->dst_address, &dst4, sizeof(dst4));
8599     mp->outer_fib_id = ntohl(outer_fib_id);
8600     mp->is_add = is_add;
8601
8602     S; W;
8603     /* NOTREACHED */
8604     return 0;
8605 }
8606
8607 static void vl_api_gre_tunnel_details_t_handler
8608 (vl_api_gre_tunnel_details_t * mp)
8609 {
8610     vat_main_t * vam = &vat_main;
8611
8612     fformat(vam->ofp, "%11d%15U%15U%14d\n",
8613             ntohl(mp->sw_if_index),
8614             format_ip4_address, &mp->src_address,
8615             format_ip4_address, &mp->dst_address,
8616             ntohl(mp->outer_fib_id));
8617 }
8618
8619 static void vl_api_gre_tunnel_details_t_handler_json
8620 (vl_api_gre_tunnel_details_t * mp)
8621 {
8622     vat_main_t * vam = &vat_main;
8623     vat_json_node_t *node = NULL;
8624     struct in_addr ip4;
8625
8626     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8627         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8628         vat_json_init_array(&vam->json_tree);
8629     }
8630     node = vat_json_array_add(&vam->json_tree);
8631
8632     vat_json_init_object(node);
8633     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
8634     clib_memcpy(&ip4, &mp->src_address, sizeof(ip4));
8635     vat_json_object_add_ip4(node, "src_address", ip4);
8636     clib_memcpy(&ip4, &mp->dst_address, sizeof(ip4));
8637     vat_json_object_add_ip4(node, "dst_address", ip4);
8638     vat_json_object_add_uint(node, "outer_fib_id", ntohl(mp->outer_fib_id));
8639 }
8640
8641 static int api_gre_tunnel_dump (vat_main_t * vam)
8642 {
8643     unformat_input_t * i = vam->input;
8644     vl_api_gre_tunnel_dump_t *mp;
8645     f64 timeout;
8646     u32 sw_if_index;
8647     u8 sw_if_index_set = 0;
8648
8649     /* Parse args required to build the message */
8650     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8651         if (unformat (i, "sw_if_index %d", &sw_if_index))
8652             sw_if_index_set = 1;
8653         else
8654             break;
8655     }
8656
8657     if (sw_if_index_set == 0) {
8658         sw_if_index = ~0;
8659     }
8660
8661     if (!vam->json_output) {
8662         fformat(vam->ofp, "%11s%15s%15s%14s\n",
8663                 "sw_if_index", "src_address", "dst_address",
8664                 "outer_fib_id");
8665     }
8666
8667     /* Get list of gre-tunnel interfaces */
8668     M(GRE_TUNNEL_DUMP, gre_tunnel_dump);
8669
8670     mp->sw_if_index = htonl(sw_if_index);
8671
8672     S;
8673
8674     /* Use a control ping for synchronization */
8675     {
8676         vl_api_control_ping_t * mp;
8677         M(CONTROL_PING, control_ping);
8678         S;
8679     }
8680     W;
8681 }
8682
8683 static int api_l2_fib_clear_table (vat_main_t * vam)
8684 {
8685 //  unformat_input_t * i = vam->input;
8686     vl_api_l2_fib_clear_table_t *mp;
8687     f64 timeout;
8688
8689     M(L2_FIB_CLEAR_TABLE, l2_fib_clear_table);
8690
8691     S; W;
8692     /* NOTREACHED */
8693     return 0;
8694 }
8695
8696 static int api_l2_interface_efp_filter (vat_main_t * vam)
8697 {
8698     unformat_input_t * i = vam->input;
8699     vl_api_l2_interface_efp_filter_t *mp;
8700     f64 timeout;
8701     u32 sw_if_index;
8702     u8 enable = 1;
8703     u8 sw_if_index_set = 0;
8704
8705     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8706         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8707             sw_if_index_set = 1;
8708         else if (unformat (i, "sw_if_index %d", &sw_if_index))
8709             sw_if_index_set = 1;
8710         else if (unformat (i, "enable"))
8711             enable = 1;
8712         else if (unformat (i, "disable"))
8713             enable = 0;
8714         else {
8715             clib_warning ("parse error '%U'", format_unformat_error, i);
8716             return -99;
8717         }
8718     }
8719
8720     if (sw_if_index_set == 0) {
8721         errmsg ("missing sw_if_index\n");
8722         return -99;
8723     }
8724
8725     M(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter);
8726
8727     mp->sw_if_index = ntohl(sw_if_index);
8728     mp->enable_disable = enable;
8729
8730     S; W;
8731     /* NOTREACHED */
8732     return 0;
8733 }
8734
8735 #define foreach_vtr_op                          \
8736 _("disable",  L2_VTR_DISABLED)                  \
8737 _("push-1",  L2_VTR_PUSH_1)                     \
8738 _("push-2",  L2_VTR_PUSH_2)                     \
8739 _("pop-1",  L2_VTR_POP_1)                       \
8740 _("pop-2",  L2_VTR_POP_2)                       \
8741 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
8742 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
8743 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
8744 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
8745
8746 static int api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
8747 {
8748     unformat_input_t * i = vam->input;
8749     vl_api_l2_interface_vlan_tag_rewrite_t *mp;
8750     f64 timeout;
8751     u32 sw_if_index;
8752     u8 sw_if_index_set = 0;
8753     u8 vtr_op_set = 0;
8754     u32 vtr_op = 0;
8755     u32 push_dot1q = 1;
8756     u32 tag1 = ~0;
8757     u32 tag2 = ~0;
8758
8759     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8760         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8761             sw_if_index_set = 1;
8762         else if (unformat (i, "sw_if_index %d", &sw_if_index))
8763             sw_if_index_set = 1;
8764         else if (unformat (i, "vtr_op %d", &vtr_op))
8765             vtr_op_set = 1;
8766 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
8767         foreach_vtr_op
8768 #undef _
8769
8770         else if (unformat (i, "push_dot1q %d", &push_dot1q))
8771             ;
8772         else if (unformat (i, "tag1 %d", &tag1))
8773             ;
8774         else if (unformat (i, "tag2 %d", &tag2))
8775             ;
8776         else {
8777             clib_warning ("parse error '%U'", format_unformat_error, i);
8778             return -99;
8779         }
8780     }
8781
8782     if ((sw_if_index_set == 0)||(vtr_op_set == 0)) {
8783         errmsg ("missing vtr operation or sw_if_index\n");
8784         return -99;
8785     }
8786
8787     M(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)
8788
8789     mp->sw_if_index = ntohl(sw_if_index);
8790     mp->vtr_op = ntohl(vtr_op);
8791     mp->push_dot1q = ntohl(push_dot1q);
8792     mp->tag1 = ntohl(tag1);
8793     mp->tag2 = ntohl(tag2);
8794
8795     S; W;
8796     /* NOTREACHED */
8797     return 0;
8798 }
8799
8800 static int api_create_vhost_user_if (vat_main_t * vam)
8801 {
8802     unformat_input_t * i = vam->input;
8803     vl_api_create_vhost_user_if_t *mp;
8804     f64 timeout;
8805     u8 * file_name;
8806     u8 is_server = 0;
8807     u8 file_name_set = 0;
8808     u32 custom_dev_instance = ~0;
8809     u8 hwaddr[6];
8810     u8 use_custom_mac = 0;
8811
8812     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8813       if (unformat (i, "socket %s", &file_name)) {
8814         file_name_set = 1;
8815       }
8816       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
8817         ;
8818       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
8819         use_custom_mac = 1;
8820       else if (unformat (i, "server"))
8821         is_server = 1;
8822       else
8823         break;
8824     }
8825
8826     if (file_name_set == 0) {
8827       errmsg ("missing socket file name\n");
8828       return -99;
8829     }
8830
8831     if (vec_len (file_name) > 255) {
8832       errmsg ("socket file name too long\n");
8833       return -99;
8834     }
8835     vec_add1 (file_name, 0);
8836
8837     M(CREATE_VHOST_USER_IF, create_vhost_user_if);
8838
8839     mp->is_server = is_server;
8840     clib_memcpy(mp->sock_filename, file_name, vec_len(file_name));
8841     vec_free(file_name);
8842     if (custom_dev_instance != ~0) {
8843         mp->renumber = 1;
8844         mp->custom_dev_instance = ntohl(custom_dev_instance);
8845     }
8846     mp->use_custom_mac = use_custom_mac;
8847     clib_memcpy(mp->mac_address, hwaddr, 6);
8848
8849     S; W;
8850     /* NOTREACHED */
8851     return 0;
8852 }
8853
8854 static int api_modify_vhost_user_if (vat_main_t * vam)
8855 {
8856     unformat_input_t * i = vam->input;
8857     vl_api_modify_vhost_user_if_t *mp;
8858     f64 timeout;
8859     u8 * file_name;
8860     u8 is_server = 0;
8861     u8 file_name_set = 0;
8862     u32 custom_dev_instance = ~0;
8863     u8 sw_if_index_set = 0;
8864     u32 sw_if_index = (u32)~0;
8865
8866     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8867       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8868           sw_if_index_set = 1;
8869       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8870           sw_if_index_set = 1;
8871       else if (unformat (i, "socket %s", &file_name)) {
8872         file_name_set = 1;
8873       }
8874       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
8875         ;
8876       else if (unformat (i, "server"))
8877         is_server = 1;
8878       else
8879         break;
8880     }
8881
8882     if (sw_if_index_set == 0) {
8883        errmsg ("missing sw_if_index or interface name\n");
8884        return -99;
8885     }
8886
8887     if (file_name_set == 0) {
8888       errmsg ("missing socket file name\n");
8889       return -99;
8890     }
8891
8892     if (vec_len (file_name) > 255) {
8893       errmsg ("socket file name too long\n");
8894       return -99;
8895     }
8896     vec_add1 (file_name, 0);
8897
8898     M(MODIFY_VHOST_USER_IF, modify_vhost_user_if);
8899
8900     mp->sw_if_index = ntohl(sw_if_index);
8901     mp->is_server = is_server;
8902     clib_memcpy(mp->sock_filename, file_name, vec_len(file_name));
8903     vec_free(file_name);
8904     if (custom_dev_instance != ~0) {
8905         mp->renumber = 1;
8906         mp->custom_dev_instance = ntohl(custom_dev_instance);
8907     }
8908
8909     S; W;
8910     /* NOTREACHED */
8911     return 0;
8912 }
8913
8914 static int api_delete_vhost_user_if (vat_main_t * vam)
8915 {
8916     unformat_input_t * i = vam->input;
8917     vl_api_delete_vhost_user_if_t *mp;
8918     f64 timeout;
8919     u32 sw_if_index = ~0;
8920     u8 sw_if_index_set = 0;
8921
8922     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8923       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8924           sw_if_index_set = 1;
8925       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8926           sw_if_index_set = 1;
8927       else
8928         break;
8929     }
8930
8931     if (sw_if_index_set == 0) {
8932        errmsg ("missing sw_if_index or interface name\n");
8933        return -99;
8934     }
8935
8936
8937     M(DELETE_VHOST_USER_IF, delete_vhost_user_if);
8938
8939     mp->sw_if_index = ntohl(sw_if_index);
8940
8941     S; W;
8942     /* NOTREACHED */
8943     return 0;
8944 }
8945
8946 static void vl_api_sw_interface_vhost_user_details_t_handler
8947 (vl_api_sw_interface_vhost_user_details_t * mp)
8948 {
8949     vat_main_t * vam = &vat_main;
8950
8951     fformat(vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s\n",
8952             (char *)mp->interface_name,
8953             ntohl(mp->sw_if_index), ntohl(mp->virtio_net_hdr_sz),
8954             clib_net_to_host_u64(mp->features), mp->is_server,
8955             ntohl(mp->num_regions), (char *)mp->sock_filename);
8956     fformat(vam->ofp, "    Status: '%s'\n", strerror(ntohl(mp->sock_errno)));
8957 }
8958
8959 static void vl_api_sw_interface_vhost_user_details_t_handler_json
8960 (vl_api_sw_interface_vhost_user_details_t * mp)
8961 {
8962     vat_main_t * vam = &vat_main;
8963     vat_json_node_t *node = NULL;
8964
8965     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8966         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8967         vat_json_init_array(&vam->json_tree);
8968     }
8969     node = vat_json_array_add(&vam->json_tree);
8970
8971     vat_json_init_object(node);
8972     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
8973     vat_json_object_add_string_copy(node, "interface_name", mp->interface_name);
8974     vat_json_object_add_uint(node, "virtio_net_hdr_sz", ntohl(mp->virtio_net_hdr_sz));
8975     vat_json_object_add_uint(node, "features", clib_net_to_host_u64(mp->features));
8976     vat_json_object_add_uint(node, "is_server", mp->is_server);
8977     vat_json_object_add_string_copy(node, "sock_filename", mp->sock_filename);
8978     vat_json_object_add_uint(node, "num_regions", ntohl(mp->num_regions));
8979     vat_json_object_add_uint(node, "sock_errno", ntohl(mp->sock_errno));
8980 }
8981
8982 static int api_sw_interface_vhost_user_dump (vat_main_t * vam)
8983 {
8984     vl_api_sw_interface_vhost_user_dump_t *mp;
8985     f64 timeout;
8986     fformat(vam->ofp, "Interface name           idx hdr_sz features server regions filename\n");
8987
8988     /* Get list of vhost-user interfaces */
8989     M(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump);
8990     S;
8991
8992     /* Use a control ping for synchronization */
8993     {
8994         vl_api_control_ping_t * mp;
8995         M(CONTROL_PING, control_ping);
8996         S;
8997     }
8998     W;
8999 }
9000
9001 static int api_show_version (vat_main_t * vam)
9002 {
9003     vl_api_show_version_t *mp;
9004     f64 timeout;
9005
9006     M(SHOW_VERSION, show_version);
9007
9008     S; W;
9009     /* NOTREACHED */
9010     return 0;
9011 }
9012
9013
9014 static int api_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
9015 {
9016     unformat_input_t * line_input = vam->input;
9017     vl_api_vxlan_gpe_add_del_tunnel_t *mp;
9018     f64 timeout;
9019     ip4_address_t local4, remote4;
9020     ip6_address_t local6, remote6;
9021     u8 is_add = 1;
9022     u8 ipv4_set = 0, ipv6_set = 0;
9023     u8 local_set = 0;
9024     u8 remote_set = 0;
9025     u32 encap_vrf_id = 0;
9026     u32 decap_vrf_id = 0;
9027     u8 protocol = ~0;
9028     u32 vni;
9029     u8 vni_set = 0;
9030
9031     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
9032         if (unformat (line_input, "del"))
9033             is_add = 0;
9034         else if (unformat (line_input, "local %U",
9035                            unformat_ip4_address, &local4))
9036         {
9037             local_set = 1;
9038             ipv4_set = 1;
9039         }
9040         else if (unformat (line_input, "remote %U",
9041                            unformat_ip4_address, &remote4))
9042         {
9043             remote_set = 1;
9044             ipv4_set = 1;
9045         }
9046         else if (unformat (line_input, "local %U",
9047                            unformat_ip6_address, &local6))
9048         {
9049             local_set = 1;
9050             ipv6_set = 1;
9051         }
9052         else if (unformat (line_input, "remote %U",
9053                            unformat_ip6_address, &remote6))
9054         {
9055             remote_set = 1;
9056             ipv6_set = 1;
9057         }
9058         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
9059             ;
9060         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
9061             ;
9062         else if (unformat (line_input, "vni %d", &vni))
9063             vni_set = 1;
9064         else if (unformat(line_input, "next-ip4"))
9065             protocol = 1;
9066         else if (unformat(line_input, "next-ip6"))
9067             protocol = 2;
9068         else if (unformat(line_input, "next-ethernet"))
9069             protocol = 3;
9070         else if (unformat(line_input, "next-nsh"))
9071             protocol = 4;
9072         else {
9073             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
9074             return -99;
9075         }
9076     }
9077
9078     if (local_set == 0) {
9079         errmsg ("tunnel local address not specified\n");
9080         return -99;
9081     }
9082     if (remote_set == 0) {
9083         errmsg ("tunnel remote address not specified\n");
9084         return -99;
9085     }
9086     if (ipv4_set && ipv6_set) {
9087         errmsg ("both IPv4 and IPv6 addresses specified");
9088         return -99;
9089     }
9090
9091     if (vni_set == 0) {
9092         errmsg ("vni not specified\n");
9093         return -99;
9094     }
9095
9096     M(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel);
9097
9098
9099     if (ipv6_set) {
9100         clib_memcpy(&mp->local, &local6, sizeof(local6));
9101         clib_memcpy(&mp->remote, &remote6, sizeof(remote6));
9102     } else {
9103         clib_memcpy(&mp->local, &local4, sizeof(local4));
9104         clib_memcpy(&mp->remote, &remote4, sizeof(remote4));
9105     }
9106
9107     mp->encap_vrf_id = ntohl(encap_vrf_id);
9108     mp->decap_vrf_id = ntohl(decap_vrf_id);
9109     mp->protocol = ntohl(protocol);
9110     mp->vni = ntohl(vni);
9111     mp->is_add = is_add;
9112     mp->is_ipv6 = ipv6_set;
9113
9114     S; W;
9115     /* NOTREACHED */
9116     return 0;
9117 }
9118
9119 static void vl_api_vxlan_gpe_tunnel_details_t_handler
9120 (vl_api_vxlan_gpe_tunnel_details_t * mp)
9121 {
9122     vat_main_t * vam = &vat_main;
9123
9124     fformat(vam->ofp, "%11d%24U%24U%13d%12d%14d%14d\n",
9125             ntohl(mp->sw_if_index),
9126             format_ip46_address, &(mp->local[0]),
9127             format_ip46_address, &(mp->remote[0]),
9128                         ntohl(mp->vni),
9129             ntohl(mp->protocol),
9130             ntohl(mp->encap_vrf_id),
9131             ntohl(mp->decap_vrf_id));
9132 }
9133
9134 static void vl_api_vxlan_gpe_tunnel_details_t_handler_json
9135 (vl_api_vxlan_gpe_tunnel_details_t * mp)
9136 {
9137     vat_main_t * vam = &vat_main;
9138     vat_json_node_t *node = NULL;
9139     struct in_addr ip4;
9140     struct in6_addr ip6;
9141
9142     if (VAT_JSON_ARRAY != vam->json_tree.type) {
9143         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
9144         vat_json_init_array(&vam->json_tree);
9145     }
9146     node = vat_json_array_add(&vam->json_tree);
9147
9148     vat_json_init_object(node);
9149     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
9150     if (mp->is_ipv6) {
9151         clib_memcpy(&ip6, &(mp->local[0]), sizeof(ip6));
9152         vat_json_object_add_ip6(node, "local", ip6);
9153         clib_memcpy(&ip6, &(mp->remote[0]), sizeof(ip6));
9154         vat_json_object_add_ip6(node, "remote", ip6);
9155     } else {
9156         clib_memcpy(&ip4, &(mp->local[0]), sizeof(ip4));
9157         vat_json_object_add_ip4(node, "local", ip4);
9158         clib_memcpy(&ip4, &(mp->remote[0]), sizeof(ip4));
9159         vat_json_object_add_ip4(node, "remote", ip4);
9160     }
9161     vat_json_object_add_uint(node, "vni", ntohl(mp->vni));
9162     vat_json_object_add_uint(node, "protocol", ntohl(mp->protocol));
9163     vat_json_object_add_uint(node, "encap_vrf_id", ntohl(mp->encap_vrf_id));
9164     vat_json_object_add_uint(node, "decap_vrf_id", ntohl(mp->decap_vrf_id));
9165     vat_json_object_add_uint(node, "is_ipv6", mp->is_ipv6 ? 1 : 0);
9166 }
9167
9168 static int api_vxlan_gpe_tunnel_dump (vat_main_t * vam)
9169 {
9170     unformat_input_t * i = vam->input;
9171     vl_api_vxlan_gpe_tunnel_dump_t *mp;
9172     f64 timeout;
9173     u32 sw_if_index;
9174     u8 sw_if_index_set = 0;
9175
9176     /* Parse args required to build the message */
9177     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9178         if (unformat (i, "sw_if_index %d", &sw_if_index))
9179             sw_if_index_set = 1;
9180         else
9181             break;
9182     }
9183
9184     if (sw_if_index_set == 0) {
9185         sw_if_index = ~0;
9186     }
9187
9188     if (!vam->json_output) {
9189         fformat(vam->ofp, "%11s%24s%24s%13s%15s%14s%14s\n",
9190                 "sw_if_index", "local", "remote", "vni",
9191                                 "protocol","encap_vrf_id", "decap_vrf_id");
9192     }
9193
9194     /* Get list of vxlan-tunnel interfaces */
9195     M(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump);
9196
9197     mp->sw_if_index = htonl(sw_if_index);
9198
9199     S;
9200
9201     /* Use a control ping for synchronization */
9202     {
9203         vl_api_control_ping_t * mp;
9204         M(CONTROL_PING, control_ping);
9205         S;
9206     }
9207     W;
9208 }
9209
9210 u8 * format_l2_fib_mac_address (u8 * s, va_list * args)
9211 {
9212   u8 * a = va_arg (*args, u8 *);
9213
9214   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
9215                  a[2], a[3], a[4], a[5], a[6], a[7]);
9216 }
9217
9218 static void vl_api_l2_fib_table_entry_t_handler
9219 (vl_api_l2_fib_table_entry_t * mp)
9220 {
9221     vat_main_t * vam = &vat_main;
9222
9223     fformat(vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
9224             "       %d       %d     %d\n",
9225             ntohl(mp->bd_id), format_l2_fib_mac_address, &mp->mac,
9226             ntohl(mp->sw_if_index), mp->static_mac, mp->filter_mac,
9227             mp->bvi_mac);
9228 }
9229
9230 static void vl_api_l2_fib_table_entry_t_handler_json
9231 (vl_api_l2_fib_table_entry_t * mp)
9232 {
9233     vat_main_t * vam = &vat_main;
9234     vat_json_node_t *node = NULL;
9235
9236     if (VAT_JSON_ARRAY != vam->json_tree.type) {
9237         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
9238         vat_json_init_array(&vam->json_tree);
9239     }
9240     node = vat_json_array_add(&vam->json_tree);
9241
9242     vat_json_init_object(node);
9243     vat_json_object_add_uint(node, "bd_id", ntohl(mp->bd_id));
9244     vat_json_object_add_uint(node, "mac", clib_net_to_host_u64(mp->mac));
9245     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
9246     vat_json_object_add_uint(node, "static_mac", mp->static_mac);
9247     vat_json_object_add_uint(node, "filter_mac", mp->filter_mac);
9248     vat_json_object_add_uint(node, "bvi_mac", mp->bvi_mac);
9249 }
9250
9251 static int api_l2_fib_table_dump (vat_main_t * vam)
9252 {
9253     unformat_input_t * i = vam->input;
9254     vl_api_l2_fib_table_dump_t *mp;
9255     f64 timeout;
9256     u32 bd_id;
9257     u8 bd_id_set = 0;
9258
9259     /* Parse args required to build the message */
9260     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9261         if (unformat (i, "bd_id %d", &bd_id))
9262             bd_id_set = 1;
9263         else
9264             break;
9265     }
9266
9267     if (bd_id_set == 0) {
9268         errmsg ("missing bridge domain\n");
9269         return -99;
9270     }
9271
9272     fformat(vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI\n");
9273
9274     /* Get list of l2 fib entries */
9275     M(L2_FIB_TABLE_DUMP, l2_fib_table_dump);
9276
9277     mp->bd_id = ntohl(bd_id);
9278     S;
9279
9280     /* Use a control ping for synchronization */
9281     {
9282         vl_api_control_ping_t * mp;
9283         M(CONTROL_PING, control_ping);
9284         S;
9285     }
9286     W;
9287 }
9288
9289
9290 static int
9291 api_interface_name_renumber (vat_main_t * vam)
9292 {
9293     unformat_input_t * line_input = vam->input;
9294     vl_api_interface_name_renumber_t *mp;
9295     u32 sw_if_index = ~0;
9296     f64 timeout;
9297     u32 new_show_dev_instance = ~0;
9298
9299     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
9300         if (unformat (line_input, "%U", unformat_sw_if_index, vam,
9301                       &sw_if_index))
9302             ;
9303         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
9304             ;
9305         else if (unformat (line_input, "new_show_dev_instance %d",
9306                            &new_show_dev_instance))
9307             ;
9308         else
9309             break;
9310     }
9311
9312     if (sw_if_index == ~0) {
9313         errmsg ("missing interface name or sw_if_index\n");
9314         return -99;
9315     }
9316
9317     if (new_show_dev_instance == ~0) {
9318         errmsg ("missing new_show_dev_instance\n");
9319         return -99;
9320     }
9321
9322     M(INTERFACE_NAME_RENUMBER, interface_name_renumber);
9323
9324     mp->sw_if_index = ntohl (sw_if_index);
9325     mp->new_show_dev_instance = ntohl (new_show_dev_instance);
9326
9327     S; W;
9328 }
9329
9330 static int
9331 api_want_ip4_arp_events (vat_main_t * vam)
9332 {
9333     unformat_input_t * line_input = vam->input;
9334     vl_api_want_ip4_arp_events_t * mp;
9335     f64 timeout;
9336     ip4_address_t address;
9337     int address_set = 0;
9338     u32 enable_disable = 1;
9339
9340     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
9341         if (unformat (line_input, "address %U",
9342                       unformat_ip4_address, &address))
9343             address_set = 1;
9344         else if (unformat (line_input, "del"))
9345             enable_disable = 0;
9346         else
9347             break;
9348     }
9349
9350     if (address_set == 0) {
9351         errmsg ("missing addresses\n");
9352         return -99;
9353     }
9354
9355     M(WANT_IP4_ARP_EVENTS, want_ip4_arp_events);
9356     mp->enable_disable = enable_disable;
9357     mp->pid = getpid();
9358     mp->address = address.as_u32;
9359
9360     S; W;
9361 }
9362
9363 static int api_input_acl_set_interface (vat_main_t * vam)
9364 {
9365     unformat_input_t * i = vam->input;
9366     vl_api_input_acl_set_interface_t *mp;
9367     f64 timeout;
9368     u32 sw_if_index;
9369     int sw_if_index_set;
9370     u32 ip4_table_index = ~0;
9371     u32 ip6_table_index = ~0;
9372     u32 l2_table_index = ~0;
9373     u8 is_add = 1;
9374
9375     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9376         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
9377             sw_if_index_set = 1;
9378         else if (unformat (i, "sw_if_index %d", &sw_if_index))
9379             sw_if_index_set = 1;
9380         else if (unformat (i, "del"))
9381             is_add = 0;
9382         else if (unformat (i, "ip4-table %d", &ip4_table_index))
9383             ;
9384         else if (unformat (i, "ip6-table %d", &ip6_table_index))
9385             ;
9386         else if (unformat (i, "l2-table %d", &l2_table_index))
9387             ;
9388         else {
9389             clib_warning ("parse error '%U'", format_unformat_error, i);
9390             return -99;
9391         }
9392     }
9393
9394     if (sw_if_index_set == 0) {
9395         errmsg ("missing interface name or sw_if_index\n");
9396         return -99;
9397     }
9398
9399     M(INPUT_ACL_SET_INTERFACE, input_acl_set_interface);
9400
9401     mp->sw_if_index = ntohl(sw_if_index);
9402     mp->ip4_table_index = ntohl(ip4_table_index);
9403     mp->ip6_table_index = ntohl(ip6_table_index);
9404     mp->l2_table_index = ntohl(l2_table_index);
9405     mp->is_add = is_add;
9406
9407     S; W;
9408     /* NOTREACHED */
9409     return 0;
9410 }
9411
9412 static int
9413 api_ip_address_dump (vat_main_t * vam)
9414 {
9415     unformat_input_t * i = vam->input;
9416     vl_api_ip_address_dump_t * mp;
9417     u32 sw_if_index = ~0;
9418     u8 sw_if_index_set = 0;
9419     u8 ipv4_set = 0;
9420     u8 ipv6_set = 0;
9421     f64 timeout;
9422
9423     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9424         if (unformat (i, "sw_if_index %d", &sw_if_index))
9425             sw_if_index_set = 1;
9426         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
9427             sw_if_index_set = 1;
9428         else if (unformat (i, "ipv4"))
9429             ipv4_set = 1;
9430         else if (unformat (i, "ipv6"))
9431             ipv6_set = 1;
9432         else
9433             break;
9434     }
9435
9436     if (ipv4_set && ipv6_set) {
9437         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
9438         return -99;
9439     }
9440
9441     if ((!ipv4_set) && (!ipv6_set)) {
9442         errmsg ("no ipv4 nor ipv6 flag set\n");
9443         return -99;
9444     }
9445
9446     if (sw_if_index_set == 0) {
9447         errmsg ("missing interface name or sw_if_index\n");
9448         return -99;
9449     }
9450
9451     vam->current_sw_if_index = sw_if_index;
9452     vam->is_ipv6 = ipv6_set;
9453
9454     M(IP_ADDRESS_DUMP, ip_address_dump);
9455     mp->sw_if_index = ntohl(sw_if_index);
9456     mp->is_ipv6 = ipv6_set;
9457     S;
9458
9459     /* Use a control ping for synchronization */
9460     {
9461         vl_api_control_ping_t * mp;
9462         M(CONTROL_PING, control_ping);
9463         S;
9464     }
9465     W;
9466 }
9467
9468 static int
9469 api_ip_dump (vat_main_t * vam)
9470 {
9471     vl_api_ip_dump_t * mp;
9472     unformat_input_t * in = vam->input;
9473     int ipv4_set = 0;
9474     int ipv6_set = 0;
9475     int is_ipv6;
9476     f64 timeout;
9477     int i;
9478
9479     while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT) {
9480         if (unformat (in, "ipv4"))
9481             ipv4_set = 1;
9482         else if (unformat (in, "ipv6"))
9483             ipv6_set = 1;
9484         else
9485             break;
9486     }
9487
9488     if (ipv4_set && ipv6_set) {
9489         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
9490         return -99;
9491     }
9492
9493     if ((!ipv4_set) && (!ipv6_set)) {
9494         errmsg ("no ipv4 nor ipv6 flag set\n");
9495         return -99;
9496     }
9497
9498     is_ipv6 = ipv6_set;
9499     vam->is_ipv6 = is_ipv6;
9500
9501     /* free old data */
9502     for (i = 0; i < vec_len(vam->ip_details_by_sw_if_index[is_ipv6]); i++) {
9503         vec_free(vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
9504     }
9505     vec_free(vam->ip_details_by_sw_if_index[is_ipv6]);
9506
9507     M(IP_DUMP, ip_dump);
9508     mp->is_ipv6 = ipv6_set;
9509     S;
9510
9511     /* Use a control ping for synchronization */
9512     {
9513         vl_api_control_ping_t * mp;
9514         M(CONTROL_PING, control_ping);
9515         S;
9516     }
9517     W;
9518 }
9519
9520 static int
9521 api_ipsec_spd_add_del (vat_main_t * vam)
9522 {
9523 #if DPDK > 0
9524     unformat_input_t * i = vam->input;
9525     vl_api_ipsec_spd_add_del_t *mp;
9526     f64 timeout;
9527     u32 spd_id = ~0;
9528     u8 is_add = 1;
9529
9530     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9531         if (unformat (i, "spd_id %d", &spd_id))
9532             ;
9533         else if (unformat (i, "del"))
9534             is_add = 0;
9535         else {
9536             clib_warning ("parse error '%U'", format_unformat_error, i);
9537             return -99;
9538         }
9539     }
9540     if (spd_id == ~0) {
9541         errmsg ("spd_id must be set\n");
9542         return -99;
9543     }
9544
9545     M(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del);
9546
9547     mp->spd_id = ntohl(spd_id);
9548     mp->is_add = is_add;
9549
9550     S; W;
9551     /* NOTREACHED */
9552     return 0;
9553 #else
9554     clib_warning ("unsupported (no dpdk)");
9555     return -99;
9556 #endif
9557 }
9558
9559 static int
9560 api_ipsec_interface_add_del_spd (vat_main_t * vam)
9561 {
9562 #if DPDK > 0
9563     unformat_input_t * i = vam->input;
9564     vl_api_ipsec_interface_add_del_spd_t *mp;
9565     f64 timeout;
9566     u32 sw_if_index;
9567     u8 sw_if_index_set = 0;
9568     u32 spd_id = (u32) ~0;
9569     u8 is_add = 1;
9570
9571     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9572         if (unformat (i, "del"))
9573             is_add = 0;
9574         else if (unformat (i, "spd_id %d", &spd_id))
9575             ;
9576         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
9577             sw_if_index_set = 1;
9578         else if (unformat (i, "sw_if_index %d", &sw_if_index))
9579             sw_if_index_set = 1;
9580         else {
9581             clib_warning ("parse error '%U'", format_unformat_error, i);
9582             return -99;
9583         }
9584
9585     }
9586
9587     if (spd_id == (u32) ~0) {
9588         errmsg ("spd_id must be set\n");
9589         return -99;
9590     }
9591
9592     if (sw_if_index_set == 0) {
9593         errmsg ("missing interface name or sw_if_index\n");
9594         return -99;
9595     }
9596
9597     M(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd);
9598
9599     mp->spd_id = ntohl(spd_id);
9600     mp->sw_if_index = ntohl (sw_if_index);
9601     mp->is_add = is_add;
9602
9603     S; W;
9604     /* NOTREACHED */
9605     return 0;
9606 #else
9607     clib_warning ("unsupported (no dpdk)");
9608     return -99;
9609 #endif
9610 }
9611
9612 static int
9613 api_ipsec_spd_add_del_entry (vat_main_t * vam)
9614 {
9615 #if DPDK > 0
9616     unformat_input_t * i = vam->input;
9617     vl_api_ipsec_spd_add_del_entry_t *mp;
9618     f64 timeout;
9619     u8 is_add = 1, is_outbound = 0, is_ipv6 = 0, is_ip_any = 1;
9620     u32 spd_id, sa_id, protocol = 0, policy = 0;
9621     i32 priority;
9622     u32 rport_start = 0, rport_stop = (u32) ~0;
9623     u32 lport_start = 0, lport_stop = (u32) ~0;
9624     ip4_address_t laddr4_start, laddr4_stop, raddr4_start, raddr4_stop;
9625     ip6_address_t laddr6_start, laddr6_stop, raddr6_start, raddr6_stop;
9626
9627     laddr4_start.as_u32 = raddr4_start.as_u32 = 0;
9628     laddr4_stop.as_u32 = raddr4_stop.as_u32 = (u32) ~0;
9629     laddr6_start.as_u64[0] = raddr6_start.as_u64[0] = 0;
9630     laddr6_start.as_u64[1] = raddr6_start.as_u64[1] = 0;
9631     laddr6_stop.as_u64[0] = raddr6_stop.as_u64[0] = (u64) ~0;
9632     laddr6_stop.as_u64[1] = raddr6_stop.as_u64[1] = (u64) ~0;
9633
9634     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9635         if (unformat (i, "del"))
9636             is_add = 0;
9637         if (unformat (i, "outbound"))
9638             is_outbound = 1;
9639         if (unformat (i, "inbound"))
9640             is_outbound = 0;
9641         else if (unformat (i, "spd_id %d", &spd_id))
9642             ;
9643         else if (unformat (i, "sa_id %d", &sa_id))
9644             ;
9645         else if (unformat (i, "priority %d", &priority))
9646             ;
9647         else if (unformat (i, "protocol %d", &protocol))
9648             ;
9649         else if (unformat (i, "lport_start %d", &lport_start))
9650             ;
9651         else if (unformat (i, "lport_stop %d", &lport_stop))
9652             ;
9653         else if (unformat (i, "rport_start %d", &rport_start))
9654             ;
9655         else if (unformat (i, "rport_stop %d", &rport_stop))
9656             ;
9657         else if (unformat (i, "laddr_start %U", unformat_ip4_address, &laddr4_start))
9658           {
9659             is_ipv6 = 0;
9660             is_ip_any =0;
9661           }
9662         else if (unformat (i, "laddr_stop %U", unformat_ip4_address, &laddr4_stop))
9663           {
9664             is_ipv6 = 0;
9665             is_ip_any = 0;
9666           }
9667         else if (unformat (i, "raddr_start %U", unformat_ip4_address, &raddr4_start))
9668           {
9669             is_ipv6 = 0;
9670             is_ip_any = 0;
9671           }
9672         else if (unformat (i, "raddr_stop %U", unformat_ip4_address, &raddr4_stop))
9673           {
9674             is_ipv6 = 0;
9675             is_ip_any = 0;
9676           }
9677         else if (unformat (i, "laddr_start %U", unformat_ip6_address, &laddr6_start))
9678           {
9679             is_ipv6 = 1;
9680             is_ip_any = 0;
9681           }
9682         else if (unformat (i, "laddr_stop %U", unformat_ip6_address, &laddr6_stop))
9683           {
9684             is_ipv6 = 1;
9685             is_ip_any = 0;
9686           }
9687         else if (unformat (i, "raddr_start %U", unformat_ip6_address, &raddr6_start))
9688           {
9689             is_ipv6 = 1;
9690             is_ip_any = 0;
9691           }
9692         else if (unformat (i, "raddr_stop %U", unformat_ip6_address, &raddr6_stop))
9693           {
9694             is_ipv6 = 1;
9695             is_ip_any = 0;
9696           }
9697         else if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
9698           {
9699             if (policy == IPSEC_POLICY_ACTION_RESOLVE) {
9700                 clib_warning ("unsupported action: 'resolve'");
9701                 return -99;
9702             }
9703           }
9704         else {
9705             clib_warning ("parse error '%U'", format_unformat_error, i);
9706             return -99;
9707         }
9708
9709     }
9710
9711     M(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry);
9712
9713     mp->spd_id = ntohl(spd_id);
9714     mp->priority = ntohl(priority);
9715     mp->is_outbound = is_outbound;
9716
9717     mp->is_ipv6 = is_ipv6;
9718     if (is_ipv6 || is_ip_any) {
9719         clib_memcpy (mp->remote_address_start, &raddr6_start, sizeof(ip6_address_t));
9720         clib_memcpy (mp->remote_address_stop, &raddr6_stop, sizeof(ip6_address_t));
9721         clib_memcpy (mp->local_address_start, &laddr6_start, sizeof(ip6_address_t));
9722         clib_memcpy (mp->local_address_stop, &laddr6_stop, sizeof(ip6_address_t));
9723     } else {
9724         clib_memcpy (mp->remote_address_start, &raddr4_start, sizeof(ip4_address_t));
9725         clib_memcpy (mp->remote_address_stop, &raddr4_stop, sizeof(ip4_address_t));
9726         clib_memcpy (mp->local_address_start, &laddr4_start, sizeof(ip4_address_t));
9727         clib_memcpy (mp->local_address_stop, &laddr4_stop, sizeof(ip4_address_t));
9728     }
9729     mp->protocol = (u8) protocol;
9730     mp->local_port_start = ntohs((u16) lport_start);
9731     mp->local_port_stop = ntohs((u16) lport_stop);
9732     mp->remote_port_start = ntohs((u16) rport_start);
9733     mp->remote_port_stop = ntohs((u16) rport_stop);
9734     mp->policy = (u8) policy;
9735     mp->sa_id = ntohl(sa_id);
9736     mp->is_add = is_add;
9737     mp->is_ip_any = is_ip_any;
9738     S; W;
9739     /* NOTREACHED */
9740     return 0;
9741 #else
9742     clib_warning ("unsupported (no dpdk)");
9743     return -99;
9744 #endif
9745 }
9746
9747 static int
9748 api_ipsec_sad_add_del_entry (vat_main_t * vam)
9749 {
9750 #if DPDK > 0
9751     unformat_input_t * i = vam->input;
9752     vl_api_ipsec_sad_add_del_entry_t *mp;
9753     f64 timeout;
9754     u32 sad_id, spi;
9755     u8 * ck = 0, * ik = 0;
9756     u8 is_add = 1;
9757
9758     u8 protocol = IPSEC_PROTOCOL_AH;
9759     u8 is_tunnel = 0, is_tunnel_ipv6 = 0;
9760     u32 crypto_alg = 0, integ_alg = 0;
9761     ip4_address_t tun_src4;
9762     ip4_address_t tun_dst4;
9763     ip6_address_t tun_src6;
9764     ip6_address_t tun_dst6;
9765
9766     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9767         if (unformat (i, "del"))
9768             is_add = 0;
9769         else if (unformat (i, "sad_id %d", &sad_id))
9770             ;
9771         else if (unformat (i, "spi %d", &spi))
9772             ;
9773         else if (unformat (i, "esp"))
9774             protocol = IPSEC_PROTOCOL_ESP;
9775         else if (unformat (i, "tunnel_src %U", unformat_ip4_address, &tun_src4)) {
9776             is_tunnel = 1;
9777             is_tunnel_ipv6 = 0;
9778         }
9779         else if (unformat (i, "tunnel_dst %U", unformat_ip4_address, &tun_dst4)) {
9780             is_tunnel = 1;
9781             is_tunnel_ipv6 = 0;
9782         }
9783         else if (unformat (i, "tunnel_src %U", unformat_ip6_address, &tun_src6)) {
9784             is_tunnel = 1;
9785             is_tunnel_ipv6 = 1;
9786         }
9787         else if (unformat (i, "tunnel_dst %U", unformat_ip6_address, &tun_dst6)) {
9788             is_tunnel = 1;
9789             is_tunnel_ipv6 = 1;
9790         }
9791         else if (unformat (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg)) {
9792             if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
9793                 crypto_alg > IPSEC_INTEG_ALG_SHA_512_256) {
9794                 clib_warning ("unsupported crypto-alg: '%U'",
9795                               format_ipsec_crypto_alg, crypto_alg);
9796                 return -99;
9797             }
9798         }
9799         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
9800             ;
9801         else if (unformat (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) {
9802             if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
9803                 integ_alg > IPSEC_INTEG_ALG_SHA_512_256) {
9804                 clib_warning ("unsupported integ-alg: '%U'",
9805                               format_ipsec_integ_alg, integ_alg);
9806                 return -99;
9807             }
9808         }
9809         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
9810             ;
9811         else {
9812             clib_warning ("parse error '%U'", format_unformat_error, i);
9813             return -99;
9814         }
9815
9816     }
9817
9818     M(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry);
9819
9820     mp->sad_id = ntohl(sad_id);
9821     mp->is_add = is_add;
9822     mp->protocol = protocol;
9823     mp->spi = ntohl(spi);
9824     mp->is_tunnel = is_tunnel;
9825     mp->is_tunnel_ipv6 = is_tunnel_ipv6;
9826     mp->crypto_algorithm = crypto_alg;
9827     mp->integrity_algorithm = integ_alg;
9828     mp->crypto_key_length = vec_len(ck);
9829     mp->integrity_key_length = vec_len(ik);
9830
9831     if (mp->crypto_key_length > sizeof(mp->crypto_key))
9832       mp->crypto_key_length = sizeof(mp->crypto_key);
9833
9834     if (mp->integrity_key_length > sizeof(mp->integrity_key))
9835       mp->integrity_key_length = sizeof(mp->integrity_key);
9836
9837     clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length);
9838     clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length);
9839
9840     if (is_tunnel) {
9841       if (is_tunnel_ipv6) {
9842         clib_memcpy (mp->tunnel_src_address, &tun_src6, sizeof(ip6_address_t));
9843         clib_memcpy (mp->tunnel_dst_address, &tun_dst6, sizeof(ip6_address_t));
9844       } else {
9845         clib_memcpy (mp->tunnel_src_address, &tun_src4, sizeof(ip4_address_t));
9846         clib_memcpy (mp->tunnel_dst_address, &tun_dst4, sizeof(ip4_address_t));
9847       }
9848     }
9849
9850     S; W;
9851     /* NOTREACHED */
9852     return 0;
9853 #else
9854     clib_warning ("unsupported (no dpdk)");
9855     return -99;
9856 #endif
9857 }
9858
9859 static int
9860 api_ipsec_sa_set_key (vat_main_t * vam)
9861 {
9862 #if DPDK > 0
9863     unformat_input_t * i = vam->input;
9864     vl_api_ipsec_sa_set_key_t *mp;
9865     f64 timeout;
9866     u32 sa_id;
9867     u8 * ck = 0, * ik = 0;
9868
9869     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9870         if (unformat (i, "sa_id %d", &sa_id))
9871             ;
9872         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
9873             ;
9874         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
9875             ;
9876         else {
9877             clib_warning ("parse error '%U'", format_unformat_error, i);
9878             return -99;
9879         }
9880     }
9881
9882     M(IPSEC_SA_SET_KEY, ipsec_set_sa_key);
9883
9884     mp->sa_id = ntohl(sa_id);
9885     mp->crypto_key_length = vec_len(ck);
9886     mp->integrity_key_length = vec_len(ik);
9887
9888     if (mp->crypto_key_length > sizeof(mp->crypto_key))
9889       mp->crypto_key_length = sizeof(mp->crypto_key);
9890
9891     if (mp->integrity_key_length > sizeof(mp->integrity_key))
9892       mp->integrity_key_length = sizeof(mp->integrity_key);
9893
9894     clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length);
9895     clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length);
9896
9897     S; W;
9898     /* NOTREACHED */
9899     return 0;
9900 #else
9901     clib_warning ("unsupported (no dpdk)");
9902     return -99;
9903 #endif
9904 }
9905
9906 static int
9907 api_ikev2_profile_add_del (vat_main_t * vam)
9908 {
9909 #if DPDK > 0
9910     unformat_input_t * i = vam->input;
9911     vl_api_ikev2_profile_add_del_t * mp;
9912     f64 timeout;
9913     u8 is_add = 1;
9914     u8 * name = 0;
9915
9916     const char * valid_chars = "a-zA-Z0-9_";
9917
9918     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9919         if (unformat (i, "del"))
9920             is_add = 0;
9921         else if (unformat (i, "name %U", unformat_token, valid_chars, &name))
9922             vec_add1 (name, 0);
9923         else {
9924             errmsg ("parse error '%U'", format_unformat_error, i);
9925             return -99;
9926         }
9927     }
9928
9929     if (!vec_len (name)) {
9930         errmsg ("profile name must be specified");
9931         return -99;
9932     }
9933
9934     if (vec_len (name) > 64) {
9935         errmsg ("profile name too long");
9936         return -99;
9937     }
9938
9939     M(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del);
9940
9941     clib_memcpy(mp->name, name, vec_len (name));
9942     mp->is_add = is_add;
9943     vec_free (name);
9944
9945     S; W;
9946     /* NOTREACHED */
9947     return 0;
9948 #else
9949     clib_warning ("unsupported (no dpdk)");
9950     return -99;
9951 #endif
9952 }
9953
9954 static int
9955 api_ikev2_profile_set_auth (vat_main_t * vam)
9956 {
9957 #if DPDK > 0
9958     unformat_input_t * i = vam->input;
9959     vl_api_ikev2_profile_set_auth_t * mp;
9960     f64 timeout;
9961     u8 * name = 0;
9962     u8 * data = 0;
9963     u32 auth_method = 0;
9964     u8 is_hex = 0;
9965
9966     const char * valid_chars = "a-zA-Z0-9_";
9967
9968     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9969         if (unformat (i, "name %U", unformat_token, valid_chars, &name))
9970             vec_add1 (name, 0);
9971         else if (unformat (i, "auth_method %U",
9972                            unformat_ikev2_auth_method, &auth_method))
9973             ;
9974         else if (unformat (i, "auth_data 0x%U", unformat_hex_string, &data))
9975             is_hex = 1;
9976         else if (unformat (i, "auth_data %v", &data))
9977             ;
9978         else {
9979             errmsg ("parse error '%U'", format_unformat_error, i);
9980             return -99;
9981         }
9982     }
9983
9984     if (!vec_len (name)) {
9985         errmsg ("profile name must be specified");
9986         return -99;
9987     }
9988
9989     if (vec_len (name) > 64) {
9990         errmsg ("profile name too long");
9991         return -99;
9992     }
9993
9994     if (!vec_len(data)) {
9995         errmsg ("auth_data must be specified");
9996         return -99;
9997     }
9998
9999     if (!auth_method) {
10000         errmsg ("auth_method must be specified");
10001         return -99;
10002     }
10003
10004     M(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth);
10005
10006     mp->is_hex = is_hex;
10007     mp->auth_method = (u8) auth_method;
10008     mp->data_len = vec_len (data);
10009     clib_memcpy (mp->name, name, vec_len (name));
10010     clib_memcpy (mp->data, data, vec_len (data));
10011     vec_free (name);
10012     vec_free (data);
10013
10014     S; W;
10015     /* NOTREACHED */
10016     return 0;
10017 #else
10018     clib_warning ("unsupported (no dpdk)");
10019     return -99;
10020 #endif
10021 }
10022
10023 static int
10024 api_ikev2_profile_set_id (vat_main_t * vam)
10025 {
10026 #if DPDK > 0
10027     unformat_input_t * i = vam->input;
10028     vl_api_ikev2_profile_set_id_t * mp;
10029     f64 timeout;
10030     u8 * name = 0;
10031     u8 * data = 0;
10032     u8 is_local = 0;
10033     u32 id_type = 0;
10034     ip4_address_t ip4;
10035
10036     const char * valid_chars = "a-zA-Z0-9_";
10037
10038     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10039         if (unformat (i, "name %U", unformat_token, valid_chars, &name))
10040             vec_add1 (name, 0);
10041         else if (unformat (i, "id_type %U",
10042                            unformat_ikev2_id_type, &id_type))
10043             ;
10044         else if (unformat (i, "id_data %U", unformat_ip4_address, &ip4))
10045           {
10046             data = vec_new(u8, 4);
10047             clib_memcpy(data, ip4.as_u8, 4);
10048           }
10049         else if (unformat (i, "id_data 0x%U", unformat_hex_string, &data))
10050             ;
10051         else if (unformat (i, "id_data %v", &data))
10052             ;
10053         else if (unformat (i, "local"))
10054             is_local = 1;
10055         else if (unformat (i, "remote"))
10056             is_local = 0;
10057         else {
10058             errmsg ("parse error '%U'", format_unformat_error, i);
10059             return -99;
10060         }
10061     }
10062
10063     if (!vec_len (name)) {
10064         errmsg ("profile name must be specified");
10065         return -99;
10066     }
10067
10068     if (vec_len (name) > 64) {
10069         errmsg ("profile name too long");
10070         return -99;
10071     }
10072
10073     if (!vec_len(data)) {
10074         errmsg ("id_data must be specified");
10075         return -99;
10076     }
10077
10078     if (!id_type) {
10079         errmsg ("id_type must be specified");
10080         return -99;
10081     }
10082
10083     M(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id);
10084
10085     mp->is_local = is_local;
10086     mp->id_type = (u8) id_type;
10087     mp->data_len = vec_len (data);
10088     clib_memcpy (mp->name, name, vec_len (name));
10089     clib_memcpy (mp->data, data, vec_len (data));
10090     vec_free (name);
10091     vec_free (data);
10092
10093     S; W;
10094     /* NOTREACHED */
10095     return 0;
10096 #else
10097     clib_warning ("unsupported (no dpdk)");
10098     return -99;
10099 #endif
10100 }
10101
10102 static int
10103 api_ikev2_profile_set_ts (vat_main_t * vam)
10104 {
10105 #if DPDK > 0
10106     unformat_input_t * i = vam->input;
10107     vl_api_ikev2_profile_set_ts_t * mp;
10108     f64 timeout;
10109     u8 * name = 0;
10110     u8 is_local = 0;
10111     u32 proto = 0, start_port = 0, end_port = (u32) ~0;
10112     ip4_address_t start_addr, end_addr;
10113
10114     const char * valid_chars = "a-zA-Z0-9_";
10115
10116     start_addr.as_u32 = 0;
10117     end_addr.as_u32 = (u32) ~0;
10118
10119     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10120         if (unformat (i, "name %U", unformat_token, valid_chars, &name))
10121             vec_add1 (name, 0);
10122         else if (unformat (i, "protocol %d", &proto))
10123             ;
10124         else if (unformat (i, "start_port %d", &start_port))
10125             ;
10126         else if (unformat (i, "end_port %d", &end_port))
10127             ;
10128         else if (unformat (i, "start_addr %U", unformat_ip4_address, &start_addr))
10129             ;
10130         else if (unformat (i, "end_addr %U", unformat_ip4_address, &end_addr))
10131             ;
10132         else if (unformat (i, "local"))
10133             is_local = 1;
10134         else if (unformat (i, "remote"))
10135             is_local = 0;
10136         else {
10137             errmsg ("parse error '%U'", format_unformat_error, i);
10138             return -99;
10139         }
10140     }
10141
10142     if (!vec_len (name)) {
10143         errmsg ("profile name must be specified");
10144         return -99;
10145     }
10146
10147     if (vec_len (name) > 64) {
10148         errmsg ("profile name too long");
10149         return -99;
10150     }
10151
10152     M(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts);
10153
10154     mp->is_local = is_local;
10155     mp->proto = (u8) proto;
10156     mp->start_port = (u16) start_port;
10157     mp->end_port = (u16) end_port;
10158     mp->start_addr = start_addr.as_u32;
10159     mp->end_addr = end_addr.as_u32;
10160     clib_memcpy (mp->name, name, vec_len (name));
10161     vec_free (name);
10162
10163     S; W;
10164     /* NOTREACHED */
10165     return 0;
10166 #else
10167     clib_warning ("unsupported (no dpdk)");
10168     return -99;
10169 #endif
10170 }
10171
10172 static int
10173 api_ikev2_set_local_key (vat_main_t * vam)
10174 {
10175 #if DPDK > 0
10176     unformat_input_t * i = vam->input;
10177     vl_api_ikev2_set_local_key_t * mp;
10178     f64 timeout;
10179     u8 * file = 0;
10180
10181     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10182         if (unformat (i, "file %v", &file))
10183             vec_add1 (file, 0);
10184         else {
10185             errmsg ("parse error '%U'", format_unformat_error, i);
10186             return -99;
10187         }
10188     }
10189
10190     if (!vec_len (file)) {
10191         errmsg ("RSA key file must be specified");
10192         return -99;
10193     }
10194
10195     if (vec_len (file) > 256) {
10196         errmsg ("file name too long");
10197         return -99;
10198     }
10199
10200     M(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key);
10201
10202     clib_memcpy (mp->key_file, file, vec_len (file));
10203     vec_free (file);
10204
10205     S; W;
10206     /* NOTREACHED */
10207     return 0;
10208 #else
10209     clib_warning ("unsupported (no dpdk)");
10210     return -99;
10211 #endif
10212 }
10213
10214 /*
10215  * MAP
10216  */
10217 static int api_map_add_domain (vat_main_t * vam)
10218 {
10219   unformat_input_t *i = vam->input;
10220   vl_api_map_add_domain_t *mp;
10221   f64 timeout;
10222
10223   ip4_address_t ip4_prefix;
10224   ip6_address_t ip6_prefix;
10225   ip6_address_t ip6_src;
10226   u32 num_m_args = 0;
10227   u32 ip6_prefix_len, ip4_prefix_len, ea_bits_len, psid_offset,
10228     psid_length;
10229   u8 is_translation = 0;
10230   u32 mtu = 0;
10231   u8 ip6_src_len = 128;
10232
10233   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10234     if (unformat (i, "ip4-pfx %U/%d", unformat_ip4_address,
10235                   &ip4_prefix, &ip4_prefix_len))
10236       num_m_args++;
10237     else if (unformat (i, "ip6-pfx %U/%d", unformat_ip6_address,
10238                        &ip6_prefix, &ip6_prefix_len))
10239       num_m_args++;
10240     else if (unformat (i, "ip6-src %U/%d", unformat_ip6_address, &ip6_src, &ip6_src_len))
10241       num_m_args++;
10242     else if (unformat (i, "ip6-src %U", unformat_ip6_address, &ip6_src))
10243       num_m_args++;
10244     else if (unformat (i, "ea-bits-len %d", &ea_bits_len))
10245       num_m_args++;
10246     else if (unformat (i, "psid-offset %d", &psid_offset))
10247       num_m_args++;
10248     else if (unformat (i, "psid-len %d", &psid_length))
10249       num_m_args++;
10250     else if (unformat (i, "mtu %d", &mtu))
10251       num_m_args++;
10252     else if (unformat (i, "map-t"))
10253       is_translation = 1;
10254     else {
10255       clib_warning ("parse error '%U'", format_unformat_error, i);
10256       return -99;
10257     }
10258   }
10259
10260   if (num_m_args != 6) {
10261     errmsg("mandatory argument(s) missing\n");
10262     return -99;
10263   }
10264
10265   /* Construct the API message */
10266   M(MAP_ADD_DOMAIN, map_add_domain);
10267
10268   clib_memcpy(mp->ip4_prefix, &ip4_prefix, sizeof(ip4_prefix));
10269   mp->ip4_prefix_len = ip4_prefix_len;
10270
10271   clib_memcpy(mp->ip6_prefix, &ip6_prefix, sizeof(ip6_prefix));
10272   mp->ip6_prefix_len = ip6_prefix_len;
10273
10274   clib_memcpy(mp->ip6_src, &ip6_src, sizeof(ip6_src));
10275   mp->ip6_src_prefix_len = ip6_src_len;
10276
10277   mp->ea_bits_len = ea_bits_len;
10278   mp->psid_offset = psid_offset;
10279   mp->psid_length = psid_length;
10280   mp->is_translation = is_translation;
10281   mp->mtu = htons(mtu);
10282
10283   /* send it... */
10284   S;
10285
10286   /* Wait for a reply, return good/bad news  */
10287   W;
10288 }
10289
10290 static int api_map_del_domain (vat_main_t * vam)
10291 {
10292   unformat_input_t *i = vam->input;
10293   vl_api_map_del_domain_t *mp;
10294   f64 timeout;
10295
10296   u32 num_m_args = 0;
10297   u32 index;
10298
10299   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10300     if (unformat (i, "index %d", &index))
10301       num_m_args++;
10302     else {
10303       clib_warning ("parse error '%U'", format_unformat_error, i);
10304       return -99;
10305     }
10306   }
10307
10308   if (num_m_args != 1) {
10309     errmsg("mandatory argument(s) missing\n");
10310     return -99;
10311   }
10312
10313   /* Construct the API message */
10314   M(MAP_DEL_DOMAIN, map_del_domain);
10315
10316   mp->index = ntohl(index);
10317
10318   /* send it... */
10319   S;
10320
10321   /* Wait for a reply, return good/bad news  */
10322   W;
10323 }
10324
10325 static int api_map_add_del_rule (vat_main_t * vam)
10326 {
10327   unformat_input_t *i = vam->input;
10328   vl_api_map_add_del_rule_t *mp;
10329   f64 timeout;
10330   u8 is_add = 1;
10331   ip6_address_t ip6_dst;
10332   u32 num_m_args = 0, index, psid;
10333
10334   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10335     if (unformat (i, "index %d", &index))
10336       num_m_args++;
10337     else if (unformat (i, "psid %d", &psid))
10338       num_m_args++;
10339     else if (unformat (i, "dst %U", unformat_ip6_address, &ip6_dst))
10340       num_m_args++;
10341     else if (unformat (i, "del")) {
10342       is_add = 0;
10343     } else {
10344       clib_warning ("parse error '%U'", format_unformat_error, i);
10345       return -99;
10346     }
10347   }
10348
10349   /* Construct the API message */
10350   M(MAP_ADD_DEL_RULE, map_add_del_rule);
10351
10352   mp->index = ntohl(index);
10353   mp->is_add = is_add;
10354   clib_memcpy(mp->ip6_dst, &ip6_dst, sizeof(ip6_dst));
10355   mp->psid = ntohs(psid);
10356
10357   /* send it... */
10358   S;
10359
10360   /* Wait for a reply, return good/bad news  */
10361   W;
10362 }
10363
10364 static int api_map_domain_dump (vat_main_t * vam)
10365 {
10366     vl_api_map_domain_dump_t *mp;
10367     f64 timeout;
10368
10369     /* Construct the API message */
10370     M(MAP_DOMAIN_DUMP, map_domain_dump);
10371
10372     /* send it... */
10373     S;
10374
10375     /* Use a control ping for synchronization */
10376     {
10377         vl_api_control_ping_t * mp;
10378         M(CONTROL_PING, control_ping);
10379         S;
10380     }
10381     W;
10382 }
10383
10384 static int api_map_rule_dump (vat_main_t * vam)
10385 {
10386     unformat_input_t *i = vam->input;
10387     vl_api_map_rule_dump_t *mp;
10388     f64 timeout;
10389     u32 domain_index = ~0;
10390
10391     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10392         if (unformat (i, "index %u", &domain_index))
10393             ;
10394         else
10395             break;
10396     }
10397
10398     if (domain_index == ~0) {
10399         clib_warning("parse error: domain index expected");
10400         return -99;
10401     }
10402
10403     /* Construct the API message */
10404     M(MAP_RULE_DUMP, map_rule_dump);
10405
10406     mp->domain_index = htonl(domain_index);
10407
10408     /* send it... */
10409     S;
10410
10411     /* Use a control ping for synchronization */
10412     {
10413         vl_api_control_ping_t * mp;
10414         M(CONTROL_PING, control_ping);
10415         S;
10416     }
10417     W;
10418 }
10419
10420 static void vl_api_map_add_domain_reply_t_handler
10421 (vl_api_map_add_domain_reply_t * mp)
10422 {
10423   vat_main_t * vam = &vat_main;
10424   i32 retval = ntohl(mp->retval);
10425
10426   if (vam->async_mode) {
10427       vam->async_errors += (retval < 0);
10428   } else {
10429       vam->retval = retval;
10430       vam->result_ready = 1;
10431   }
10432 }
10433
10434 static void vl_api_map_add_domain_reply_t_handler_json
10435 (vl_api_map_add_domain_reply_t * mp)
10436 {
10437   vat_main_t * vam = &vat_main;
10438   vat_json_node_t node;
10439
10440   vat_json_init_object(&node);
10441   vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
10442   vat_json_object_add_uint(&node, "index", ntohl(mp->index));
10443
10444   vat_json_print(vam->ofp, &node);
10445   vat_json_free(&node);
10446
10447   vam->retval = ntohl(mp->retval);
10448   vam->result_ready = 1;
10449 }
10450
10451 static int
10452 api_get_first_msg_id (vat_main_t * vam)
10453 {
10454     vl_api_get_first_msg_id_t * mp;
10455     f64 timeout;
10456     unformat_input_t * i = vam->input;
10457     u8 * name;
10458     u8 name_set = 0;
10459
10460     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10461         if (unformat (i, "client %s", &name))
10462             name_set = 1;
10463         else
10464             break;
10465     }
10466
10467     if (name_set == 0) {
10468         errmsg ("missing client name\n");
10469         return -99;
10470     }
10471     vec_add1 (name, 0);
10472
10473     if (vec_len (name) > 63) {
10474         errmsg ("client name too long\n");
10475         return -99;
10476     }
10477
10478     M(GET_FIRST_MSG_ID, get_first_msg_id);
10479     clib_memcpy (mp->name, name, vec_len(name));
10480     S; W;
10481     /* NOTREACHED */
10482     return 0;
10483 }
10484
10485 static int api_cop_interface_enable_disable (vat_main_t * vam)
10486 {
10487     unformat_input_t * line_input = vam->input;
10488     vl_api_cop_interface_enable_disable_t * mp;
10489     f64 timeout;
10490     u32 sw_if_index = ~0;
10491     u8 enable_disable = 1;
10492
10493     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
10494         if (unformat (line_input, "disable"))
10495             enable_disable = 0;
10496         if (unformat (line_input, "enable"))
10497             enable_disable = 1;
10498         else if (unformat (line_input, "%U", unformat_sw_if_index,
10499                            vam, &sw_if_index))
10500             ;
10501         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
10502             ;
10503         else
10504             break;
10505     }
10506
10507     if (sw_if_index == ~0) {
10508         errmsg ("missing interface name or sw_if_index\n");
10509         return -99;
10510     }
10511
10512     /* Construct the API message */
10513     M(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable);
10514     mp->sw_if_index = ntohl(sw_if_index);
10515     mp->enable_disable = enable_disable;
10516
10517     /* send it... */
10518     S;
10519     /* Wait for the reply */
10520     W;
10521 }
10522
10523 static int api_cop_whitelist_enable_disable (vat_main_t * vam)
10524 {
10525     unformat_input_t * line_input = vam->input;
10526     vl_api_cop_whitelist_enable_disable_t * mp;
10527     f64 timeout;
10528     u32 sw_if_index = ~0;
10529     u8 ip4=0, ip6=0, default_cop=0;
10530     u32 fib_id;
10531
10532     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
10533         if (unformat (line_input, "ip4"))
10534             ip4 = 1;
10535         else if (unformat (line_input, "ip6"))
10536             ip6 = 1;
10537         else if (unformat (line_input, "default"))
10538             default_cop = 1;
10539         else if (unformat (line_input, "%U", unformat_sw_if_index,
10540                            vam, &sw_if_index))
10541             ;
10542         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
10543             ;
10544         else if (unformat (line_input, "fib-id %d", &fib_id))
10545             ;
10546         else
10547             break;
10548     }
10549
10550     if (sw_if_index == ~0) {
10551         errmsg ("missing interface name or sw_if_index\n");
10552         return -99;
10553     }
10554
10555     /* Construct the API message */
10556     M(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable);
10557     mp->sw_if_index = ntohl(sw_if_index);
10558     mp->fib_id = ntohl(fib_id);
10559     mp->ip4 = ip4;
10560     mp->ip6 = ip6;
10561     mp->default_cop = default_cop;
10562
10563     /* send it... */
10564     S;
10565     /* Wait for the reply */
10566     W;
10567 }
10568
10569 static int api_get_node_graph (vat_main_t * vam)
10570 {
10571     vl_api_get_node_graph_t * mp;
10572     f64 timeout;
10573
10574     M(GET_NODE_GRAPH, get_node_graph);
10575
10576     /* send it... */
10577     S;
10578     /* Wait for the reply */
10579     W;
10580 }
10581
10582 /** Used for parsing LISP eids */
10583 typedef CLIB_PACKED(struct{
10584   u8 addr[16];   /**< eid address */
10585   u32 len;       /**< prefix length if IP */
10586   u8 type;      /**< type of eid */
10587 }) lisp_eid_vat_t;
10588
10589 static uword
10590 unformat_lisp_eid_vat (unformat_input_t * input, va_list * args)
10591 {
10592   lisp_eid_vat_t * a = va_arg(*args, lisp_eid_vat_t *);
10593
10594   memset(a, 0, sizeof(a[0]));
10595
10596   if (unformat (input, "%U/%d", unformat_ip4_address, a->addr, &a->len)) {
10597       a->type = 0; /* ipv4 type */
10598   } else if (unformat (input, "%U/%d", unformat_ip6_address, a->addr,
10599                        &a->len)) {
10600       a->type = 1; /* ipv6 type */
10601   } else if (unformat (input, "%U", unformat_ethernet_address, a->addr)) {
10602       a->type = 2; /* mac type */
10603   } else {
10604       return 0;
10605   }
10606
10607   if ((a->type == 0 && a->len > 32) || (a->type == 1 && a->len > 128)) {
10608       return 0;
10609   }
10610
10611   return 1;
10612 }
10613
10614 static int
10615 lisp_eid_size_vat (u8 type)
10616 {
10617   switch (type) {
10618     case 0:
10619       return 4;
10620     case 1:
10621       return 16;
10622     case 2:
10623       return 6;
10624   }
10625   return 0;
10626 }
10627
10628 static void
10629 lisp_eid_put_vat (u8 * dst, u8 eid[16], u8 type)
10630 {
10631   clib_memcpy(dst, eid, lisp_eid_size_vat(type));
10632 }
10633
10634 /** Used for transferring locators via VPP API */
10635 typedef CLIB_PACKED(struct
10636 {
10637     u32 sw_if_index; /**< locator sw_if_index */
10638     u8 priority; /**< locator priority */
10639     u8 weight;   /**< locator weight */
10640 }) ls_locator_t;
10641
10642 static int
10643 api_lisp_add_del_locator_set(vat_main_t * vam)
10644 {
10645     unformat_input_t * input = vam->input;
10646     vl_api_lisp_add_del_locator_set_t *mp;
10647     f64 timeout = ~0;
10648     u8  is_add = 1;
10649     u8 *locator_set_name = NULL;
10650     u8  locator_set_name_set = 0;
10651     ls_locator_t locator, * locators = 0;
10652     u32 sw_if_index, priority, weight;
10653
10654     /* Parse args required to build the message */
10655     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10656         if (unformat(input, "del")) {
10657             is_add = 0;
10658         } else if (unformat(input, "locator-set %s", &locator_set_name)) {
10659             locator_set_name_set = 1;
10660         } else if (unformat(input, "sw_if_index %u p %u w %u",
10661                             &sw_if_index, &priority, &weight)) {
10662             locator.sw_if_index = htonl(sw_if_index);
10663             locator.priority = priority;
10664             locator.weight = weight;
10665             vec_add1(locators, locator);
10666         } else if (unformat(input, "iface %U p %u w %u", unformat_sw_if_index,
10667                             vam, &sw_if_index, &priority, &weight)) {
10668             locator.sw_if_index = htonl(sw_if_index);
10669             locator.priority = priority;
10670             locator.weight = weight;
10671             vec_add1(locators, locator);
10672         } else
10673             break;
10674     }
10675
10676     if (locator_set_name_set == 0) {
10677         errmsg ("missing locator-set name");
10678         vec_free(locators);
10679         return -99;
10680     }
10681
10682     if (vec_len(locator_set_name) > 64) {
10683         errmsg ("locator-set name too long\n");
10684         vec_free(locator_set_name);
10685         vec_free(locators);
10686         return -99;
10687     }
10688     vec_add1(locator_set_name, 0);
10689
10690     /* Construct the API message */
10691     M(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set);
10692
10693     mp->is_add = is_add;
10694     clib_memcpy(mp->locator_set_name, locator_set_name,
10695            vec_len(locator_set_name));
10696     vec_free(locator_set_name);
10697
10698     mp->locator_num = vec_len (locators);
10699     clib_memcpy (mp->locators, locators,
10700                  (sizeof (ls_locator_t) * vec_len (locators)));
10701     vec_free (locators);
10702
10703     /* send it... */
10704     S;
10705
10706     /* Wait for a reply... */
10707     W;
10708
10709     /* NOTREACHED */
10710     return 0;
10711 }
10712
10713 static int
10714 api_lisp_add_del_locator(vat_main_t * vam)
10715 {
10716     unformat_input_t * input = vam->input;
10717     vl_api_lisp_add_del_locator_t *mp;
10718     f64 timeout = ~0;
10719     u32 tmp_if_index = ~0;
10720     u32 sw_if_index = ~0;
10721     u8  sw_if_index_set = 0;
10722     u8  sw_if_index_if_name_set = 0;
10723     u32  priority = ~0;
10724     u8  priority_set = 0;
10725     u32  weight = ~0;
10726     u8  weight_set = 0;
10727     u8  is_add = 1;
10728     u8  *locator_set_name = NULL;
10729     u8  locator_set_name_set = 0;
10730
10731     /* Parse args required to build the message */
10732     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10733         if (unformat(input, "del")) {
10734             is_add = 0;
10735         } else if (unformat(input, "locator-set %s", &locator_set_name)) {
10736             locator_set_name_set = 1;
10737         } else if (unformat(input, "iface %U", unformat_sw_if_index, vam,
10738             &tmp_if_index)) {
10739             sw_if_index_if_name_set = 1;
10740             sw_if_index = tmp_if_index;
10741         } else if (unformat(input,"sw_if_index %d", &tmp_if_index)) {
10742             sw_if_index_set = 1;
10743             sw_if_index = tmp_if_index;
10744         } else if (unformat(input, "p %d", &priority)) {
10745             priority_set = 1;
10746         } else if (unformat(input, "w %d", &weight)) {
10747             weight_set = 1;
10748         } else
10749             break;
10750     }
10751
10752     if (locator_set_name_set == 0) {
10753         errmsg ("missing locator-set name");
10754         return -99;
10755     }
10756
10757     if (sw_if_index_set == 0 && sw_if_index_if_name_set == 0) {
10758         errmsg ("missing sw_if_index");
10759         vec_free(locator_set_name);
10760         return -99;
10761     }
10762
10763     if (sw_if_index_set != 0 && sw_if_index_if_name_set != 0) {
10764         errmsg ("cannot use both params interface name and sw_if_index");
10765         vec_free(locator_set_name);
10766         return -99;
10767     }
10768
10769     if (priority_set == 0) {
10770         errmsg ("missing locator-set priority\n");
10771         vec_free(locator_set_name);
10772         return -99;
10773     }
10774
10775     if (weight_set == 0) {
10776         errmsg ("missing locator-set weight\n");
10777         vec_free(locator_set_name);
10778         return -99;
10779     }
10780
10781     if (vec_len(locator_set_name) > 64) {
10782         errmsg ("locator-set name too long\n");
10783         vec_free(locator_set_name);
10784         return -99;
10785     }
10786     vec_add1(locator_set_name, 0);
10787
10788     /* Construct the API message */
10789     M(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator);
10790
10791     mp->is_add = is_add;
10792     mp->sw_if_index = ntohl(sw_if_index);
10793     mp->priority = priority;
10794     mp->weight = weight;
10795     clib_memcpy(mp->locator_set_name, locator_set_name,
10796            vec_len(locator_set_name));
10797     vec_free(locator_set_name);
10798
10799     /* send it... */
10800     S;
10801
10802     /* Wait for a reply... */
10803     W;
10804
10805     /* NOTREACHED */
10806     return 0;
10807 }
10808
10809 static int
10810 api_lisp_add_del_local_eid(vat_main_t * vam)
10811 {
10812     unformat_input_t * input = vam->input;
10813     vl_api_lisp_add_del_local_eid_t *mp;
10814     f64 timeout = ~0;
10815     u8 is_add = 1;
10816     u8 eid_set = 0;
10817     lisp_eid_vat_t _eid, *eid = &_eid;
10818     u8 *locator_set_name = 0;
10819     u8 locator_set_name_set = 0;
10820     u32 vni = 0;
10821
10822     /* Parse args required to build the message */
10823     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10824         if (unformat(input, "del")) {
10825             is_add = 0;
10826         } else if (unformat(input, "vni %d", &vni)) {
10827             ;
10828         } else if (unformat(input, "eid %U", unformat_lisp_eid_vat, eid)) {
10829             eid_set = 1;
10830         } else if (unformat(input, "locator-set %s", &locator_set_name)) {
10831             locator_set_name_set = 1;
10832         } else
10833             break;
10834     }
10835
10836     if (locator_set_name_set == 0) {
10837         errmsg ("missing locator-set name\n");
10838         return -99;
10839     }
10840
10841     if (0 == eid_set) {
10842         errmsg ("EID address not set!");
10843         vec_free(locator_set_name);
10844         return -99;
10845     }
10846
10847     if (vec_len(locator_set_name) > 64) {
10848         errmsg ("locator-set name too long\n");
10849         vec_free(locator_set_name);
10850         return -99;
10851     }
10852     vec_add1(locator_set_name, 0);
10853
10854     /* Construct the API message */
10855     M(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid);
10856
10857     mp->is_add = is_add;
10858     lisp_eid_put_vat (mp->eid, eid->addr, eid->type);
10859     mp->eid_type = eid->type;
10860     mp->prefix_len = eid->len;
10861     mp->vni = clib_host_to_net_u32(vni);
10862     clib_memcpy(mp->locator_set_name, locator_set_name,
10863            vec_len(locator_set_name));
10864
10865     vec_free(locator_set_name);
10866
10867     /* send it... */
10868     S;
10869
10870     /* Wait for a reply... */
10871     W;
10872
10873     /* NOTREACHED */
10874     return 0;
10875 }
10876
10877 /** Used for transferring locators via VPP API */
10878 typedef CLIB_PACKED(struct
10879 {
10880     u8 is_ip4; /**< is locator an IPv4 address? */
10881     u8 priority; /**< locator priority */
10882     u8 weight;   /**< locator weight */
10883     u8 addr[16]; /**< IPv4/IPv6 address */
10884 }) rloc_t;
10885
10886 static int
10887 api_lisp_gpe_add_del_fwd_entry(vat_main_t * vam)
10888 {
10889     unformat_input_t * input = vam->input;
10890     vl_api_lisp_gpe_add_del_fwd_entry_t *mp;
10891     f64 timeout = ~0;
10892     u8 is_add = 1;
10893     lisp_eid_vat_t _rmt_eid, * rmt_eid = &_rmt_eid;
10894     lisp_eid_vat_t _lcl_eid, * lcl_eid = &_lcl_eid;
10895     u8 rmt_eid_set = 0, lcl_eid_set = 0;
10896     u32 action = ~0, p, w;
10897     ip4_address_t rmt_rloc4, lcl_rloc4;
10898     ip6_address_t rmt_rloc6, lcl_rloc6;
10899     rloc_t * rmt_locs = 0, * lcl_locs = 0, rloc, * curr_rloc = 0;
10900
10901     /* Parse args required to build the message */
10902     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10903         if (unformat(input, "del")) {
10904             is_add = 0;
10905         } else if (unformat(input, "rmt_eid %U", unformat_lisp_eid_vat,
10906                             rmt_eid)) {
10907             rmt_eid_set = 1;
10908         } else if (unformat(input, "lcl_eid %U", unformat_lisp_eid_vat,
10909                             lcl_eid)) {
10910             lcl_eid_set = 1;
10911         } else if (unformat(input, "p %d w %d", &p, &w)) {
10912             if (!curr_rloc) {
10913               errmsg ("No RLOC configured for setting priority/weight!");
10914               return -99;
10915             }
10916             curr_rloc->priority = p;
10917             curr_rloc->weight = w;
10918         } else if (unformat(input, "loc-pair %U %U", unformat_ip4_address,
10919                             &lcl_rloc4, unformat_ip4_address, &rmt_rloc4)) {
10920             rloc.is_ip4 = 1;
10921             clib_memcpy (&rloc.addr, &lcl_rloc4, sizeof (lcl_rloc4));
10922             vec_add1 (lcl_locs, rloc);
10923             clib_memcpy (&rloc.addr, &rmt_rloc4, sizeof (rmt_rloc4));
10924             vec_add1 (rmt_locs, rloc);
10925             curr_rloc = &rmt_locs[vec_len (rmt_locs) - 1];
10926         } else if (unformat(input, "loc-pair %U", unformat_ip6_address,
10927                             &lcl_rloc6, unformat_ip6_address, &rmt_rloc6)) {
10928             rloc.is_ip4 = 0;
10929             clib_memcpy (&rloc.addr, &lcl_rloc6, sizeof (lcl_rloc6));
10930             vec_add1 (lcl_locs, rloc);
10931             clib_memcpy (&rloc.addr, &rmt_rloc6, sizeof (rmt_rloc6));
10932             vec_add1 (rmt_locs, rloc);
10933             curr_rloc = &rmt_locs[vec_len (rmt_locs) - 1];
10934         } else if (unformat(input, "action %d", &action)) {
10935             ;
10936         } else {
10937             clib_warning ("parse error '%U'", format_unformat_error, input);
10938             return -99;
10939         }
10940     }
10941
10942     if (!rmt_eid_set) {
10943         errmsg ("remote eid addresses not set\n");
10944         return -99;
10945     }
10946
10947     if (lcl_eid_set && rmt_eid->type != lcl_eid->type) {
10948         errmsg ("eid types don't match\n");
10949         return -99;
10950     }
10951
10952     /* Construct the API message */
10953     M(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry);
10954
10955     mp->is_add = is_add;
10956     lisp_eid_put_vat (mp->rmt_eid, rmt_eid->addr, rmt_eid->type);
10957     lisp_eid_put_vat (mp->lcl_eid, lcl_eid->addr, lcl_eid->type);
10958     mp->eid_type = rmt_eid->type;
10959     mp->rmt_len = rmt_eid->len;
10960     mp->lcl_len = lcl_eid->len;
10961     mp->action = action;
10962
10963     mp->loc_num = vec_len (rmt_locs);
10964     clib_memcpy (mp->lcl_locs, lcl_locs,
10965                  (sizeof(rloc_t) * vec_len(lcl_locs)));
10966     clib_memcpy (mp->rmt_locs, rmt_locs,
10967                  (sizeof(rloc_t) * vec_len(rmt_locs)));
10968     vec_free(lcl_locs);
10969     vec_free(rmt_locs);
10970
10971     /* send it... */
10972     S;
10973
10974     /* Wait for a reply... */
10975     W;
10976
10977     /* NOTREACHED */
10978     return 0;
10979 }
10980
10981 static int
10982 api_lisp_add_del_map_resolver(vat_main_t * vam)
10983 {
10984     unformat_input_t * input = vam->input;
10985     vl_api_lisp_add_del_map_resolver_t *mp;
10986     f64 timeout = ~0;
10987     u8 is_add = 1;
10988     u8 ipv4_set = 0;
10989     u8 ipv6_set = 0;
10990     ip4_address_t ipv4;
10991     ip6_address_t ipv6;
10992
10993     /* Parse args required to build the message */
10994     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10995         if (unformat(input, "del")) {
10996             is_add = 0;
10997         } else if (unformat(input, "%U", unformat_ip4_address, &ipv4)) {
10998             ipv4_set = 1;
10999         } else if (unformat(input, "%U", unformat_ip6_address, &ipv6)) {
11000             ipv6_set = 1;
11001         } else
11002             break;
11003     }
11004
11005     if (ipv4_set && ipv6_set) {
11006         errmsg ("both eid v4 and v6 addresses set\n");
11007         return -99;
11008     }
11009
11010     if (!ipv4_set && !ipv6_set) {
11011         errmsg ("eid addresses not set\n");
11012         return -99;
11013     }
11014
11015     /* Construct the API message */
11016     M(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver);
11017
11018     mp->is_add = is_add;
11019     if (ipv6_set) {
11020         mp->is_ipv6 = 1;
11021         clib_memcpy(mp->ip_address, &ipv6, sizeof(ipv6));
11022     } else {
11023         mp->is_ipv6 = 0;
11024         clib_memcpy(mp->ip_address, &ipv4, sizeof(ipv4));
11025     }
11026
11027     /* send it... */
11028     S;
11029
11030     /* Wait for a reply... */
11031     W;
11032
11033     /* NOTREACHED */
11034     return 0;
11035 }
11036
11037 static int
11038 api_lisp_gpe_enable_disable (vat_main_t * vam)
11039 {
11040   unformat_input_t * input = vam->input;
11041   vl_api_lisp_gpe_enable_disable_t *mp;
11042   f64 timeout = ~0;
11043   u8 is_set = 0;
11044   u8 is_en = 1;
11045
11046   /* Parse args required to build the message */
11047   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11048       if (unformat(input, "enable")) {
11049           is_set = 1;
11050           is_en = 1;
11051       } else if (unformat(input, "disable")) {
11052           is_set = 1;
11053           is_en = 0;
11054       } else
11055           break;
11056   }
11057
11058   if (is_set == 0) {
11059       errmsg("Value not set\n");
11060       return -99;
11061   }
11062
11063   /* Construct the API message */
11064   M(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable);
11065
11066   mp->is_en = is_en;
11067
11068   /* send it... */
11069   S;
11070
11071   /* Wait for a reply... */
11072   W;
11073
11074   /* NOTREACHED */
11075   return 0;
11076 }
11077
11078 static int
11079 api_lisp_enable_disable (vat_main_t * vam)
11080 {
11081   unformat_input_t * input = vam->input;
11082   vl_api_lisp_enable_disable_t *mp;
11083   f64 timeout = ~0;
11084   u8 is_set = 0;
11085   u8 is_en = 0;
11086
11087   /* Parse args required to build the message */
11088   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11089     {
11090       if (unformat (input, "enable"))
11091         {
11092           is_set = 1;
11093           is_en = 1;
11094         }
11095       else if (unformat (input, "disable"))
11096         {
11097           is_set = 1;
11098         }
11099       else
11100           break;
11101     }
11102
11103   if (!is_set)
11104     {
11105       errmsg ("Value not set\n");
11106       return -99;
11107     }
11108
11109   /* Construct the API message */
11110   M(LISP_ENABLE_DISABLE, lisp_enable_disable);
11111
11112   mp->is_en = is_en;
11113
11114   /* send it... */
11115   S;
11116
11117   /* Wait for a reply... */
11118   W;
11119
11120   /* NOTREACHED */
11121   return 0;
11122 }
11123
11124 /**
11125  * Enable/disable LISP proxy ITR.
11126  *
11127  * @param vam vpp API test context
11128  * @return return code
11129  */
11130 static int
11131 api_lisp_pitr_set_locator_set (vat_main_t * vam)
11132 {
11133   f64 timeout = ~0;
11134   u8 ls_name_set = 0;
11135   unformat_input_t * input = vam->input;
11136   vl_api_lisp_pitr_set_locator_set_t * mp;
11137   u8 is_add = 1;
11138   u8 * ls_name = 0;
11139
11140   /* Parse args required to build the message */
11141   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11142     {
11143       if (unformat (input, "del"))
11144         is_add = 0;
11145       else if (unformat (input, "locator-set %s", &ls_name))
11146         ls_name_set = 1;
11147       else
11148         {
11149           errmsg ("parse error '%U'", format_unformat_error, input);
11150           return -99;
11151         }
11152     }
11153
11154   if (!ls_name_set)
11155     {
11156       errmsg ("locator-set name not set!");
11157       return -99;
11158     }
11159
11160   M(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set);
11161
11162   mp->is_add = is_add;
11163   clib_memcpy (mp->ls_name, ls_name, vec_len (ls_name));
11164   vec_free (ls_name);
11165
11166   /* send */
11167   S;
11168
11169   /* wait for reply */
11170   W;
11171
11172   /* notreached*/
11173   return 0;
11174 }
11175
11176 static int
11177 api_show_lisp_pitr (vat_main_t * vam)
11178 {
11179     vl_api_show_lisp_pitr_t *mp;
11180     f64 timeout = ~0;
11181
11182     if (!vam->json_output) {
11183         fformat(vam->ofp, "%=20s\n",
11184                 "lisp status:");
11185     }
11186
11187     M(SHOW_LISP_PITR, show_lisp_pitr);
11188     /* send it... */
11189     S;
11190
11191     /* Wait for a reply... */
11192     W;
11193
11194     /* NOTREACHED */
11195     return 0;
11196 }
11197
11198 /**
11199  * Add/delete mapping between vni and vrf
11200  */
11201 static int
11202 api_lisp_eid_table_add_del_map (vat_main_t * vam)
11203 {
11204   f64 timeout = ~0;
11205   unformat_input_t * input = vam->input;
11206   vl_api_lisp_eid_table_add_del_map_t *mp;
11207   u8 is_add = 1, vni_set = 0, vrf_set = 0, bd_index_set = 0;
11208   u32 vni, vrf, bd_index;
11209
11210   /* Parse args required to build the message */
11211   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11212     {
11213       if (unformat (input, "del"))
11214         is_add = 0;
11215       else if (unformat(input, "vrf %d", &vrf))
11216         vrf_set = 1;
11217       else if (unformat(input, "bd_index %d", &bd_index))
11218         bd_index_set = 1;
11219       else if (unformat(input, "vni %d", &vni))
11220         vni_set = 1;
11221       else
11222         break;
11223     }
11224
11225   if (!vni_set || (!vrf_set && !bd_index_set))
11226     {
11227       errmsg ("missing arguments!");
11228       return -99;
11229     }
11230
11231   M(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map);
11232
11233   mp->is_add = is_add;
11234   mp->vni = htonl (vni);
11235   mp->dp_table = htonl (vrf);
11236   mp->is_l2 = bd_index_set;
11237
11238   /* send */
11239   S;
11240
11241   /* wait for reply */
11242   W;
11243
11244   /* notreached*/
11245   return 0;
11246 }
11247
11248 /**
11249  * Add/del remote mapping to/from LISP control plane
11250  *
11251  * @param vam vpp API test context
11252  * @return return code
11253  */
11254 static int
11255 api_lisp_add_del_remote_mapping (vat_main_t * vam)
11256 {
11257     unformat_input_t * input = vam->input;
11258     vl_api_lisp_add_del_remote_mapping_t *mp;
11259     f64 timeout = ~0;
11260     u32 vni = 0;
11261     //TODO: seid need remove
11262     lisp_eid_vat_t _eid, * eid = &_eid;
11263     lisp_eid_vat_t _seid, * seid = &_seid;
11264     u8 is_add = 1, del_all = 0, eid_set = 0;
11265     u32 action = ~0, p, w;
11266     ip4_address_t rloc4;
11267     ip6_address_t rloc6;
11268     rloc_t * rlocs = 0, rloc, * curr_rloc = 0;
11269
11270     /* Parse args required to build the message */
11271     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11272         if (unformat(input, "del-all")) {
11273             del_all = 1;
11274         } else if (unformat(input, "del")) {
11275             is_add = 0;
11276         } else if (unformat(input, "add")) {
11277             is_add = 1;
11278         } else if (unformat(input, "deid %U", unformat_lisp_eid_vat, eid)) {
11279             eid_set = 1;
11280         } else if (unformat(input, "seid %U", unformat_lisp_eid_vat, &seid)) {
11281             //TODO: Need remove, but first must be remove from CSIT test
11282         } else if (unformat(input, "vni %d", &vni)) {
11283             ;
11284         } else if (unformat(input, "p %d w %d", &p, &w)) {
11285             if (!curr_rloc) {
11286               errmsg ("No RLOC configured for setting priority/weight!");
11287               return -99;
11288             }
11289             curr_rloc->priority = p;
11290             curr_rloc->weight = w;
11291         } else if (unformat(input, "rloc %U", unformat_ip4_address, &rloc4)) {
11292             rloc.is_ip4 = 1;
11293             clib_memcpy (&rloc.addr, &rloc4, sizeof (rloc4));
11294             vec_add1 (rlocs, rloc);
11295             curr_rloc = &rlocs[vec_len (rlocs) - 1];
11296         } else if (unformat(input, "rloc %U", unformat_ip6_address, &rloc6)) {
11297             rloc.is_ip4 = 0;
11298             clib_memcpy (&rloc.addr, &rloc6, sizeof (rloc6));
11299             vec_add1 (rlocs, rloc);
11300             curr_rloc = &rlocs[vec_len (rlocs) - 1];
11301         } else if (unformat(input, "action %d", &action)) {
11302             ;
11303         } else {
11304             clib_warning ("parse error '%U'", format_unformat_error, input);
11305             return -99;
11306         }
11307     }
11308
11309     if (0 == eid_set) {
11310         errmsg ("missing params!");
11311         return -99;
11312     }
11313
11314     if (is_add && (~0 == action)
11315         && 0 == vec_len (rlocs)) {
11316           errmsg ("no action set for negative map-reply!");
11317           return -99;
11318     }
11319
11320     M(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping);
11321     mp->is_add = is_add;
11322     mp->vni = htonl (vni);
11323     mp->action = (u8) action;
11324     mp->eid_len = eid->len;
11325     mp->del_all = del_all;
11326     mp->eid_type = eid->type;
11327     lisp_eid_put_vat(mp->eid, eid->addr, eid->type);
11328
11329     mp->rloc_num = vec_len (rlocs);
11330     clib_memcpy (mp->rlocs, rlocs, (sizeof (rloc_t) * vec_len (rlocs)));
11331     vec_free (rlocs);
11332
11333     /* send it... */
11334     S;
11335
11336     /* Wait for a reply... */
11337     W;
11338
11339     /* NOTREACHED */
11340     return 0;
11341 }
11342
11343 /**
11344  * Add/del LISP adjacency. Saves mapping in LISP control plane and updates
11345  * forwarding entries in data-plane accordingly.
11346  *
11347  * @param vam vpp API test context
11348  * @return return code
11349  */
11350 static int
11351 api_lisp_add_del_adjacency (vat_main_t * vam)
11352 {
11353     unformat_input_t * input = vam->input;
11354     vl_api_lisp_add_del_adjacency_t *mp;
11355     f64 timeout = ~0;
11356     u32 vni = 0;
11357     ip4_address_t seid4, deid4;
11358     ip6_address_t seid6, deid6;
11359     u8 deid_mac[6] = {0};
11360     u8 seid_mac[6] = {0};
11361     u8 deid_type, seid_type;
11362     u32 seid_len = 0, deid_len = 0, len;
11363     u8 is_add = 1;
11364
11365     seid_type = deid_type =  (u8)~0;
11366
11367     /* Parse args required to build the message */
11368     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11369         if (unformat(input, "del")) {
11370             is_add = 0;
11371         } else if (unformat(input, "add")) {
11372             is_add = 1;
11373         } else if (unformat(input, "deid %U/%d", unformat_ip4_address,
11374                             &deid4, &len)) {
11375             deid_type = 0; /* ipv4 */
11376             deid_len = len;
11377         } else if (unformat(input, "deid %U/%d", unformat_ip6_address,
11378                             &deid6, &len)) {
11379             deid_type = 1; /* ipv6 */
11380             deid_len = len;
11381         } else if (unformat(input, "deid %U", unformat_ethernet_address,
11382                             deid_mac)) {
11383             deid_type = 2; /* mac */
11384         } else if (unformat(input, "seid %U/%d", unformat_ip4_address,
11385                             &seid4, &len)) {
11386             seid_type = 0; /* ipv4 */
11387             seid_len = len;
11388         } else if (unformat(input, "seid %U/%d", unformat_ip6_address,
11389                             &seid6, &len)) {
11390             seid_type = 1; /* ipv6 */
11391             seid_len = len;
11392         } else if (unformat(input, "seid %U", unformat_ethernet_address,
11393                             seid_mac)) {
11394             seid_type = 2; /* mac */
11395         } else if (unformat(input, "vni %d", &vni)) {
11396             ;
11397         } else {
11398             errmsg ("parse error '%U'", format_unformat_error, input);
11399             return -99;
11400         }
11401     }
11402
11403     if ((u8)~0 == deid_type) {
11404         errmsg ("missing params!");
11405         return -99;
11406     }
11407
11408     if (seid_type != deid_type) {
11409         errmsg ("source and destination EIDs are of different types!");
11410         return -99;
11411     }
11412
11413     M(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency);
11414     mp->is_add = is_add;
11415     mp->vni = htonl (vni);
11416     mp->seid_len = seid_len;
11417     mp->deid_len = deid_len;
11418     mp->eid_type = deid_type;
11419
11420     switch (mp->eid_type) {
11421     case 0:
11422         clib_memcpy (mp->seid, &seid4, sizeof (seid4));
11423         clib_memcpy (mp->deid, &deid4, sizeof (deid4));
11424         break;
11425     case 1:
11426         clib_memcpy (mp->seid, &seid6, sizeof (seid6));
11427         clib_memcpy (mp->deid, &deid6, sizeof (deid6));
11428         break;
11429     case 2:
11430         clib_memcpy (mp->seid, seid_mac, 6);
11431         clib_memcpy (mp->deid, deid_mac, 6);
11432         break;
11433     default:
11434         errmsg ("unknown EID type %d!", mp->eid_type);
11435         return 0;
11436     }
11437
11438     /* send it... */
11439     S;
11440
11441     /* Wait for a reply... */
11442     W;
11443
11444     /* NOTREACHED */
11445     return 0;
11446 }
11447
11448 static int
11449 api_lisp_gpe_add_del_iface(vat_main_t * vam)
11450 {
11451     unformat_input_t * input = vam->input;
11452     vl_api_lisp_gpe_add_del_iface_t *mp;
11453     f64 timeout = ~0;
11454     u8 is_set = 0, is_add = 1, is_l2 = 0;
11455     u32 dp_table, vni;
11456
11457     /* Parse args required to build the message */
11458     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11459         if (unformat(input, "up")) {
11460             is_set = 1;
11461             is_add = 1;
11462         } else if (unformat(input, "down")) {
11463             is_set = 1;
11464             is_add = 0;
11465         } else if (unformat(input, "table_id %d", &dp_table)) {
11466             ;
11467         } else if (unformat(input, "bd_id %d", &dp_table)) {
11468             is_l2 = 1;
11469         } else if (unformat(input, "vni %d", &vni)) {
11470             ;
11471         } else
11472             break;
11473     }
11474
11475     if (is_set == 0) {
11476         errmsg("Value not set\n");
11477         return -99;
11478     }
11479
11480     /* Construct the API message */
11481     M(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface);
11482
11483     mp->is_add = is_add;
11484     mp->dp_table = dp_table;
11485     mp->is_l2 = is_l2;
11486     mp->vni = vni;
11487
11488     /* send it... */
11489     S;
11490
11491     /* Wait for a reply... */
11492     W;
11493
11494     /* NOTREACHED */
11495     return 0;
11496 }
11497
11498 /**
11499  * Add/del map request itr rlocs from LISP control plane and updates
11500  *
11501  * @param vam vpp API test context
11502  * @return return code
11503  */
11504 static int
11505 api_lisp_add_del_map_request_itr_rlocs(vat_main_t * vam)
11506 {
11507     unformat_input_t * input = vam->input;
11508     vl_api_lisp_add_del_map_request_itr_rlocs_t *mp;
11509     f64 timeout = ~0;
11510     u8 *locator_set_name = 0;
11511     u8  locator_set_name_set = 0;
11512     u8 is_add = 1;
11513
11514     /* Parse args required to build the message */
11515     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11516         if (unformat(input, "del")) {
11517             is_add = 0;
11518         } else if (unformat(input, "%_%v%_", &locator_set_name)) {
11519             locator_set_name_set = 1;
11520         } else {
11521             clib_warning ("parse error '%U'", format_unformat_error, input);
11522             return -99;
11523         }
11524     }
11525
11526     if (is_add && !locator_set_name_set) {
11527         errmsg ("itr-rloc is not set!");
11528         return -99;
11529     }
11530
11531     if (is_add && vec_len(locator_set_name) > 64) {
11532         errmsg ("itr-rloc locator-set name too long\n");
11533         vec_free(locator_set_name);
11534         return -99;
11535     }
11536
11537     M(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS, lisp_add_del_map_request_itr_rlocs);
11538     mp->is_add = is_add;
11539     if (is_add) {
11540       clib_memcpy (mp->locator_set_name , locator_set_name,
11541                    vec_len(locator_set_name));
11542     } else {
11543       memset(mp->locator_set_name, 0, sizeof(mp->locator_set_name));
11544     }
11545     vec_free (locator_set_name);
11546
11547     /* send it... */
11548     S;
11549
11550     /* Wait for a reply... */
11551     W;
11552
11553     /* NOTREACHED */
11554     return 0;
11555 }
11556
11557 static int
11558 lisp_locator_dump_send_msg(vat_main_t * vam, u32 locator_set_index, u8 filter)
11559 {
11560     vl_api_lisp_locator_dump_t *mp;
11561     f64 timeout = ~0;
11562
11563     M(LISP_LOCATOR_DUMP, lisp_locator_dump);
11564
11565     mp->locator_set_index = htonl(locator_set_index);
11566     mp->filter = filter;
11567
11568     /* send it... */
11569     S;
11570
11571     /* Use a control ping for synchronization */
11572     {
11573       vl_api_noprint_control_ping_t * mp;
11574       M(NOPRINT_CONTROL_PING, noprint_control_ping);
11575       S;
11576     }
11577     /* Wait for a reply... */
11578     W;
11579 }
11580
11581 static inline void
11582 clean_locator_set_message(vat_main_t * vam)
11583 {
11584     locator_set_msg_t * ls = 0;
11585
11586     vec_foreach (ls, vam->locator_set_msg) {
11587         vec_free(ls->locator_set_name);
11588     }
11589
11590     vec_free(vam->locator_set_msg);
11591 }
11592
11593 static int
11594 print_locator_in_locator_set(vat_main_t * vam, u8 filter)
11595 {
11596     locator_set_msg_t * ls;
11597     locator_msg_t * loc;
11598     u8 * tmp_str = 0;
11599     int i = 0, ret = 0;
11600
11601     vec_foreach(ls, vam->locator_set_msg) {
11602         ret = lisp_locator_dump_send_msg(vam, ls->locator_set_index, filter);
11603         if (ret) {
11604             vec_free(vam->locator_msg);
11605             clean_locator_set_message(vam);
11606             return ret;
11607         }
11608
11609         tmp_str = format(0, "%=20s%=16d%s", ls->locator_set_name,
11610                          ls->locator_set_index,
11611                          vec_len(vam->locator_msg) ? "" : "\n");
11612         i = 0;
11613         vec_foreach(loc, vam->locator_msg) {
11614             if (i) {
11615                 tmp_str = format(tmp_str, "%=37s", " ");
11616             }
11617             if (loc->local) {
11618                 tmp_str = format(tmp_str, "%=16d%=16d%=16d\n",
11619                                  loc->sw_if_index,
11620                                  loc->priority,
11621                                  loc->weight);
11622             } else {
11623                 tmp_str = format(tmp_str, "%=16U%=16d%=16d\n",
11624                                  loc->is_ipv6 ? format_ip6_address :
11625                                  format_ip4_address,
11626                                  loc->ip_address,
11627                                  loc->priority,
11628                                  loc->weight);
11629             }
11630             i++;
11631         }
11632
11633         fformat(vam->ofp, "%s", tmp_str);
11634         vec_free(tmp_str);
11635         vec_free(vam->locator_msg);
11636     }
11637
11638     clean_locator_set_message(vam);
11639
11640     return ret;
11641 }
11642
11643 static int
11644 json_locator_in_locator_set(vat_main_t * vam, u8 filter)
11645 {
11646     locator_set_msg_t * ls;
11647     locator_msg_t * loc;
11648     vat_json_node_t * node = NULL;
11649     vat_json_node_t * locator_array;
11650     vat_json_node_t * locator;
11651     struct in6_addr ip6;
11652     struct in_addr ip4;
11653     int ret = 0;
11654
11655     if (!vec_len(vam->locator_set_msg)) {
11656         /* just print [] */
11657         vat_json_init_array(&vam->json_tree);
11658         vat_json_print(vam->ofp, &vam->json_tree);
11659         vam->json_tree.type = VAT_JSON_NONE;
11660         return ret;
11661     }
11662
11663     if (VAT_JSON_ARRAY != vam->json_tree.type) {
11664       ASSERT(VAT_JSON_NONE == vam->json_tree.type);
11665       vat_json_init_array(&vam->json_tree);
11666     }
11667
11668     vec_foreach(ls, vam->locator_set_msg) {
11669         ret = lisp_locator_dump_send_msg(vam, ls->locator_set_index, filter);
11670         if (ret) {
11671             vec_free(ls->locator_set_name);
11672             vec_free(vam->locator_msg);
11673             vec_free(vam->locator_set_msg);
11674             vat_json_free(&vam->json_tree);
11675             vam->json_tree.type = VAT_JSON_NONE;
11676             return ret;
11677         }
11678
11679         node = vat_json_array_add(&vam->json_tree);
11680         vat_json_init_object(node);
11681
11682         vat_json_object_add_uint(node, "locator-set-index",
11683                                  ls->locator_set_index);
11684         vat_json_object_add_string_copy(node, "locator-set",
11685                                         ls->locator_set_name);
11686         locator_array = vat_json_object_add_list(node, "locator");
11687         vec_foreach(loc, vam->locator_msg) {
11688             locator = vat_json_array_add(locator_array);
11689             vat_json_init_object(locator);
11690             if (loc->local) {
11691                 vat_json_object_add_uint(locator, "locator-index",
11692                                          loc->sw_if_index);
11693             } else {
11694                 if (loc->is_ipv6) {
11695                     clib_memcpy(&ip6, loc->ip_address, sizeof(ip6));
11696                     vat_json_object_add_ip6(locator, "locator", ip6);
11697                 } else {
11698                     clib_memcpy(&ip4, loc->ip_address, sizeof(ip4));
11699                     vat_json_object_add_ip4(locator, "locator", ip4);
11700                 }
11701             }
11702             vat_json_object_add_uint(locator, "priority", loc->priority);
11703             vat_json_object_add_uint(locator, "weight", loc->weight);
11704         }
11705
11706         vec_free(ls->locator_set_name);
11707         vec_free(vam->locator_msg);
11708     }
11709
11710     vat_json_print(vam->ofp, &vam->json_tree);
11711     vat_json_free(&vam->json_tree);
11712     vam->json_tree.type = VAT_JSON_NONE;
11713
11714     vec_free(vam->locator_set_msg);
11715
11716     return ret;
11717 }
11718
11719 static int
11720 get_locator_set_index_from_msg(vat_main_t * vam, u8 * locator_set,
11721                                u32 * locator_set_index)
11722 {
11723     locator_set_msg_t * ls;
11724     int ret = 0;
11725
11726     * locator_set_index = ~0;
11727
11728     if (!vec_len(vam->locator_set_msg)) {
11729       return ret;
11730     }
11731
11732     vec_foreach(ls, vam->locator_set_msg) {
11733         if (!strcmp((char *) locator_set, (char *) ls->locator_set_name)) {
11734             * locator_set_index = ls->locator_set_index;
11735             vec_free(vam->locator_set_msg);
11736             return ret;
11737         }
11738     }
11739
11740     vec_free(vam->locator_set_msg);
11741
11742     return ret;
11743 }
11744
11745 static int
11746 get_locator_set_index(vat_main_t * vam, u8 * locator_set,
11747                       u32 * locator_set_index)
11748 {
11749     vl_api_lisp_locator_set_dump_t *mp;
11750     f64 timeout = ~0;
11751
11752     M(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump);
11753     /* send it... */
11754     S;
11755
11756    /* Use a control ping for synchronization */
11757    {
11758      vl_api_noprint_control_ping_t * mp;
11759      M(NOPRINT_CONTROL_PING, noprint_control_ping);
11760      S;
11761    }
11762
11763    vam->noprint_msg = 1;
11764     /* Wait for a reply... */
11765     W_L({
11766       get_locator_set_index_from_msg(vam, locator_set, locator_set_index);
11767       vam->noprint_msg = 0;
11768     })
11769
11770     /* NOTREACHED */
11771     return 0;
11772 }
11773
11774 static inline int
11775 lisp_locator_dump(vat_main_t * vam, u32 locator_set_index, u8 * locator_set,
11776                   u8 filter)
11777 {
11778     int ret = 0;
11779
11780     ASSERT(vam);
11781
11782     if (!vam->json_output) {
11783       fformat(vam->ofp, "%=20s%=16s%=16s\n",
11784               "locator", "priority", "weight");
11785     }
11786
11787     if (locator_set) {
11788       ret = get_locator_set_index(vam, locator_set, &locator_set_index);
11789     }
11790
11791     if (!ret && ~0 == locator_set_index) {
11792       return -99;
11793     }
11794
11795     ret = lisp_locator_dump_send_msg(vam, locator_set_index, filter);
11796
11797     return ret;
11798 }
11799
11800 static int
11801 lisp_locator_set_dump(vat_main_t * vam, u8 filter)
11802 {
11803     vl_api_lisp_locator_set_dump_t *mp;
11804     f64 timeout = ~0;
11805
11806     if (!vam->json_output) {
11807         fformat(vam->ofp, "%=20s%=16s%=16s%=16s%=16s\n",
11808                 "locator-set", "locator-set-index", "locator", "priority",
11809                 "weight");
11810     }
11811
11812     vam->noprint_msg = 1;
11813
11814     M(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump);
11815
11816     mp->filter = filter;
11817
11818     /* send it... */
11819     S;
11820
11821    /* Use a control ping for synchronization */
11822    {
11823      vl_api_noprint_control_ping_t * mp;
11824      M(NOPRINT_CONTROL_PING, noprint_control_ping);
11825      S;
11826    }
11827
11828     /* Wait for a reply... */
11829     W_L({
11830       if (vam->noprint_msg) {
11831           if (!vam->json_output) {
11832               print_locator_in_locator_set(vam, filter);
11833           } else {
11834               json_locator_in_locator_set(vam, filter);
11835           }
11836       }
11837
11838       vam->noprint_msg = 0;
11839     });
11840
11841     /* NOTREACHED */
11842     return 0;
11843 }
11844
11845 static int
11846 api_lisp_locator_set_dump(vat_main_t *vam)
11847 {
11848     unformat_input_t * input = vam->input;
11849     vam->noprint_msg = 0;
11850     u32 locator_set_index = ~0;
11851     u8 locator_set_index_set = 0;
11852     u8 * locator_set = 0;
11853     u8 locator_set_set = 0;
11854     u8 filter = 0;
11855     int ret = 0;
11856
11857     /* Parse args required to build the message */
11858     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11859         if (unformat(input, "locator-set-index %u", &locator_set_index)) {
11860             locator_set_index_set = 1;
11861         } else if (unformat(input, "locator-set %s", &locator_set)) {
11862             locator_set_set = 1;
11863         } else if (unformat(input, "local")) {
11864             filter = 1;
11865         } else if (unformat(input, "remote")) {
11866             filter = 2;
11867         } else {
11868             break;
11869         }
11870     }
11871
11872     if (locator_set_index_set && locator_set_set) {
11873         errmsg ("use only input parameter!\n");
11874         return -99;
11875     }
11876
11877     if (locator_set_index_set || locator_set_set) {
11878         ret = lisp_locator_dump(vam, locator_set_index, locator_set, filter);
11879     } else {
11880         ret = lisp_locator_set_dump(vam, filter);
11881     }
11882
11883     vec_free(locator_set);
11884
11885     return ret;
11886 }
11887
11888 static int
11889 api_lisp_eid_table_map_dump(vat_main_t *vam)
11890 {
11891     vl_api_lisp_eid_table_map_dump_t *mp;
11892     f64 timeout = ~0;
11893
11894     if (!vam->json_output) {
11895         fformat (vam->ofp, "%=10s%=10s\n", "VNI", "VRF");
11896     }
11897
11898     M(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump);
11899
11900     /* send it... */
11901     S;
11902
11903     /* Use a control ping for synchronization */
11904     {
11905         vl_api_control_ping_t * mp;
11906         M(CONTROL_PING, control_ping);
11907         S;
11908     }
11909     /* Wait for a reply... */
11910     W;
11911
11912     /* NOTREACHED */
11913     return 0;
11914 }
11915
11916 static int
11917 get_locator_set(vat_main_t * vam)
11918 {
11919     vl_api_lisp_locator_set_dump_t *mp;
11920     f64 timeout = ~0;
11921
11922     M(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump);
11923     /* send it... */
11924     S;
11925
11926    /* Use a control ping for synchronization */
11927    {
11928      vl_api_noprint_control_ping_t * mp;
11929      M(NOPRINT_CONTROL_PING, noprint_control_ping);
11930      S;
11931    }
11932
11933     /* Wait for a reply... */
11934     W;
11935
11936     /* NOTREACHED */
11937     return 0;
11938 }
11939
11940 static inline u8 *
11941 format_eid_for_eid_table(vat_main_t *vam, u8 * str, eid_table_t * eid_table,
11942                          int *ret)
11943 {
11944     u8 * (*format_eid)(u8 *, va_list *) = 0;
11945
11946     ASSERT(vam != NULL);
11947     ASSERT(eid_table != NULL);
11948
11949     if (ret) {
11950         *ret = 0;
11951     }
11952
11953     switch (eid_table->eid_type)
11954     {
11955       case 0:
11956       case 1:
11957         format_eid = (eid_table->eid_type ? format_ip6_address :
11958           format_ip4_address);
11959         str = format(0, "[%d] %U/%d",
11960                           clib_net_to_host_u32 (eid_table->vni),
11961                           format_eid, eid_table->eid, eid_table->eid_prefix_len);
11962         break;
11963       case 2:
11964         str = format(0, "[%d] %U",
11965                           clib_net_to_host_u32 (eid_table->vni),
11966                           format_ethernet_address, eid_table->eid);
11967         break;
11968       default:
11969         errmsg ("unknown EID type %d!", eid_table->eid_type);
11970         if (ret) {
11971             *ret = -99;
11972         }
11973         return 0;
11974     }
11975
11976     return str;
11977 }
11978
11979 static inline u8 *
11980 format_locator_set_for_eid_table(vat_main_t * vam, u8 * str,
11981                                  eid_table_t * eid_table)
11982 {
11983     locator_set_msg_t * ls = 0;
11984
11985     ASSERT(vam != NULL);
11986     ASSERT(eid_table != NULL);
11987
11988     if (eid_table->is_local) {
11989         vec_foreach (ls, vam->locator_set_msg) {
11990             if (ls->locator_set_index == eid_table->locator_set_index) {
11991                 str = format(0, "local(%s)", ls->locator_set_name);
11992                 return str;
11993             }
11994         }
11995
11996         str = format(0, "local(N/A)");
11997     } else {
11998         str = format(0, "remote");
11999     }
12000
12001     return str;
12002 }
12003
12004 static inline u8 *
12005 format_locator_for_eid_table(vat_main_t * vam, u8 * str,
12006                              eid_table_t * eid_table)
12007 {
12008     locator_msg_t * loc = 0;
12009     int first_line = 1;
12010
12011     ASSERT(vam != NULL);
12012     ASSERT(eid_table != NULL);
12013
12014     vec_foreach(loc, vam->locator_msg) {
12015         if (!first_line) {
12016             if (loc->local) {
12017                 str = format(str, "%-55s%-d\n", " ", loc->sw_if_index);
12018             } else {
12019                 str = format(str, "%=55s%-U\n", " ",
12020                              loc->is_ipv6 ? format_ip6_address :
12021                              format_ip4_address,
12022                                loc->ip_address);
12023             }
12024
12025             continue;
12026         }
12027
12028         if (loc->local) {
12029             str = format(str, "%-30d%-20u%-u\n", loc->sw_if_index,
12030                          eid_table->ttl, eid_table->authoritative);
12031         } else {
12032             str = format(str, "%-30U%-20u%-u\n",
12033                          loc->is_ipv6 ? format_ip6_address :
12034                          format_ip4_address,
12035                          loc->ip_address, eid_table->ttl,
12036                          eid_table->authoritative);
12037         }
12038         first_line = 0;
12039     }
12040
12041     return str;
12042 }
12043
12044 static int
12045 print_lisp_eid_table_dump(vat_main_t * vam)
12046 {
12047     eid_table_t * eid_table = 0;
12048     u8 * tmp_str = 0, * tmp_str2 = 0;
12049     int ret = 0;
12050
12051     ASSERT(vam != NULL);
12052
12053     ret = get_locator_set(vam);
12054     if (ret) {
12055         vec_free(vam->eid_tables);
12056         return ret;
12057     }
12058
12059     fformat(vam->ofp, "%-35s%-20s%-30s%-20s%-s\n", "EID", "type", "locators",
12060                                                    "ttl", "authoritative");
12061
12062     vec_foreach(eid_table, vam->eid_tables) {
12063         ret = lisp_locator_dump_send_msg(vam, eid_table->locator_set_index, 0);
12064         if (ret) {
12065           vec_free(vam->locator_msg);
12066           clean_locator_set_message(vam);
12067           vec_free(vam->eid_tables);
12068           return ret;
12069         }
12070
12071         tmp_str2 = format_eid_for_eid_table(vam, tmp_str2, eid_table, &ret);
12072         if (ret) {
12073           vec_free(vam->locator_msg);
12074           clean_locator_set_message(vam);
12075           vec_free(vam->eid_tables);
12076           return ret;
12077         }
12078
12079         tmp_str = format(0, "%-35s", tmp_str2);
12080         vec_free(tmp_str2);
12081
12082         tmp_str2 = format_locator_set_for_eid_table(vam, tmp_str2, eid_table);
12083         tmp_str = format(tmp_str, "%-20s", tmp_str2);
12084         vec_free(tmp_str2);
12085
12086         tmp_str2 = format_locator_for_eid_table(vam, tmp_str2, eid_table);
12087         tmp_str = format(tmp_str, "%-s", tmp_str2);
12088         vec_free(tmp_str2);
12089
12090         fformat(vam->ofp, "%s", tmp_str);
12091         vec_free(tmp_str);
12092         vec_free(vam->locator_msg);
12093     }
12094
12095     clean_locator_set_message(vam);
12096     vec_free(vam->eid_tables);
12097
12098     return ret;
12099 }
12100
12101 static inline void
12102 json_locator_set_for_eid_table(vat_main_t * vam, vat_json_node_t * node,
12103                                eid_table_t * eid_table)
12104 {
12105     locator_set_msg_t * ls = 0;
12106     u8 * s = 0;
12107
12108     ASSERT(vam != NULL);
12109     ASSERT(node != NULL);
12110     ASSERT(eid_table != NULL);
12111
12112     if (eid_table->is_local) {
12113         vec_foreach (ls, vam->locator_set_msg) {
12114             if (ls->locator_set_index == eid_table->locator_set_index) {
12115                 vat_json_object_add_string_copy(node, "locator-set",
12116                                                 ls->locator_set_name);
12117                 return;
12118             }
12119         }
12120
12121         s = format(0, "N/A");
12122         vec_add1(s, 0);
12123         vat_json_object_add_string_copy(node, "locator-set", s);
12124         vec_free(s);
12125     } else {
12126         s = format(0, "remote");
12127         vec_add1(s, 0);
12128         vat_json_object_add_string_copy(node, "locator-set", s);
12129         vec_free(s);
12130     }
12131 }
12132
12133 static inline int
12134 json_eid_for_eid_table(vat_main_t * vam, vat_json_node_t * node,
12135                        eid_table_t * eid_table)
12136 {
12137     u8 * s = 0;
12138     struct in6_addr ip6;
12139     struct in_addr ip4;
12140
12141     ASSERT(vam != NULL);
12142     ASSERT(node != NULL);
12143     ASSERT(eid_table != NULL);
12144
12145     switch (eid_table->eid_type)
12146     {
12147       case 0:
12148         clib_memcpy(&ip4, eid_table->eid, sizeof(ip4));
12149         vat_json_object_add_ip4(node, "eid", ip4);
12150         vat_json_object_add_uint(node, "eid-prefix-len",
12151                                  eid_table->eid_prefix_len);
12152         break;
12153       case 1:
12154         clib_memcpy(&ip6, eid_table->eid, sizeof(ip6));
12155         vat_json_object_add_ip6(node, "eid", ip6);
12156         vat_json_object_add_uint(node, "eid-prefix-len",
12157                                  eid_table->eid_prefix_len);
12158         break;
12159       case 2:
12160         s = format (0, "%U", format_ethernet_address, eid_table->eid);
12161         vec_add1(s, 0);
12162         vat_json_object_add_string_copy(node, "eid", s);
12163         vec_free(s);
12164         break;
12165       default:
12166         errmsg ("unknown EID type %d!", eid_table->eid_type);
12167         return -99;
12168     }
12169
12170     return 0;
12171 }
12172
12173 static inline void
12174 json_locator_for_eid_table(vat_main_t * vam, vat_json_node_t * node,
12175                            eid_table_t * eid_table)
12176 {
12177     locator_msg_t * loc = 0;
12178     vat_json_node_t * locator_array = 0;
12179     vat_json_node_t * locator = 0;
12180     struct in6_addr ip6;
12181     struct in_addr ip4;
12182
12183     ASSERT(vam != NULL);
12184     ASSERT(node != NULL);
12185     ASSERT(eid_table != NULL);
12186
12187     locator_array = vat_json_object_add_list(node, "locator");
12188     vec_foreach(loc, vam->locator_msg) {
12189         locator = vat_json_array_add(locator_array);
12190         vat_json_init_object(locator);
12191         if (loc->local) {
12192             vat_json_object_add_uint(locator, "locator-index",
12193                                      loc->sw_if_index);
12194         } else {
12195             if (loc->is_ipv6) {
12196                 clib_memcpy(&ip6, loc->ip_address, sizeof(ip6));
12197                 vat_json_object_add_ip6(locator, "locator", ip6);
12198             } else {
12199                 clib_memcpy(&ip4, loc->ip_address, sizeof(ip4));
12200                 vat_json_object_add_ip4(locator, "locator", ip4);
12201             }
12202         }
12203     }
12204 }
12205
12206 static int
12207 json_lisp_eid_table_dump(vat_main_t * vam)
12208 {
12209     eid_table_t * eid_table;
12210     vat_json_node_t * node = 0;
12211     int ret = 0;
12212
12213     ASSERT(vam != NULL);
12214
12215     ret = get_locator_set(vam);
12216     if (ret) {
12217         vec_free(vam->eid_tables);
12218         return ret;
12219     }
12220
12221     if (!vec_len(vam->eid_tables)) {
12222         /* just print [] */
12223         vat_json_init_array(&vam->json_tree);
12224         vat_json_print(vam->ofp, &vam->json_tree);
12225         vam->json_tree.type = VAT_JSON_NONE;
12226         return ret;
12227     }
12228
12229     if (VAT_JSON_ARRAY != vam->json_tree.type) {
12230       ASSERT(VAT_JSON_NONE == vam->json_tree.type);
12231       vat_json_init_array(&vam->json_tree);
12232     }
12233
12234     vec_foreach(eid_table, vam->eid_tables) {
12235         ret = lisp_locator_dump_send_msg(vam, eid_table->locator_set_index, 0);
12236         if (ret) {
12237             vec_free(vam->locator_msg);
12238             vec_free(vam->eid_tables);
12239             clean_locator_set_message(vam);
12240             vat_json_free(&vam->json_tree);
12241             vam->json_tree.type = VAT_JSON_NONE;
12242             return ret;
12243         }
12244
12245         node = vat_json_array_add(&vam->json_tree);
12246         vat_json_init_object(node);
12247
12248         vat_json_object_add_uint(node, "vni", eid_table->vni);
12249
12250         json_locator_set_for_eid_table(vam, node, eid_table);
12251         ret = json_eid_for_eid_table(vam, node, eid_table);
12252         if (ret) {
12253             vec_free(vam->locator_msg);
12254             vec_free(vam->eid_tables);
12255             clean_locator_set_message(vam);
12256             vat_json_free(&vam->json_tree);
12257             vam->json_tree.type = VAT_JSON_NONE;
12258             return ret;
12259         }
12260
12261         json_locator_for_eid_table(vam, node, eid_table);
12262
12263         vat_json_object_add_uint(node, "ttl", eid_table->ttl);
12264         vat_json_object_add_uint(node, "authoritative",
12265                                 eid_table->authoritative);
12266
12267         vec_free(vam->locator_msg);
12268     }
12269
12270     vat_json_print(vam->ofp, &vam->json_tree);
12271     vat_json_free(&vam->json_tree);
12272     vam->json_tree.type = VAT_JSON_NONE;
12273
12274     clean_locator_set_message(vam);
12275     vec_free(vam->eid_tables);
12276
12277     return ret;
12278 }
12279
12280 static int
12281 api_lisp_eid_table_dump(vat_main_t *vam)
12282 {
12283     unformat_input_t * i = vam->input;
12284     vl_api_lisp_eid_table_dump_t *mp;
12285     f64 timeout = ~0;
12286     struct in_addr ip4;
12287     struct in6_addr ip6;
12288     u8 mac[6];
12289     u8 eid_type = ~0, eid_set = 0;
12290     u32 prefix_length = ~0, t, vni = 0;
12291     u8 filter = 0;
12292
12293     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12294         if (unformat (i, "eid %U/%d", unformat_ip4_address, &ip4, &t)) {
12295             eid_set = 1;
12296             eid_type = 0;
12297             prefix_length = t;
12298         } else if (unformat (i, "eid %U/%d", unformat_ip6_address, &ip6, &t)) {
12299             eid_set = 1;
12300             eid_type = 1;
12301             prefix_length = t;
12302         } else if (unformat (i, "eid %U", unformat_ethernet_address, mac)) {
12303             eid_set = 1;
12304             eid_type = 2;
12305         } else if (unformat (i, "vni %d", &t)) {
12306             vni = t;
12307         } else if (unformat (i, "local")) {
12308             filter = 1;
12309         } else if (unformat (i, "remote")) {
12310             filter = 2;
12311         } else {
12312             errmsg ("parse error '%U'", format_unformat_error, i);
12313             return -99;
12314         }
12315     }
12316
12317     M(LISP_EID_TABLE_DUMP, lisp_eid_table_dump);
12318
12319     mp->filter = filter;
12320     if (eid_set) {
12321         mp->eid_set = 1;
12322         mp->vni = htonl (vni);
12323         mp->eid_type = eid_type;
12324         switch (eid_type) {
12325         case 0:
12326             mp->prefix_length = prefix_length;
12327             clib_memcpy (mp->eid, &ip4, sizeof (ip4));
12328             break;
12329         case 1:
12330             mp->prefix_length = prefix_length;
12331             clib_memcpy (mp->eid, &ip6, sizeof (ip6));
12332             break;
12333         case 2:
12334             clib_memcpy (mp->eid, mac, sizeof (mac));
12335             break;
12336         default:
12337             errmsg ("unknown EID type %d!", eid_type);
12338             return -99;
12339         }
12340     }
12341
12342     vam->noprint_msg = 1;
12343
12344     /* send it... */
12345     S;
12346
12347     /* Use a control ping for synchronization */
12348     {
12349         vl_api_noprint_control_ping_t * mp;
12350         M(NOPRINT_CONTROL_PING, noprint_control_ping);
12351         S;
12352     }
12353
12354     /* Wait for a reply... */
12355     W_L({
12356       if (vam->noprint_msg) {
12357           if (!vam->json_output) {
12358               vam->retval = print_lisp_eid_table_dump(vam);
12359           } else {
12360               vam->retval = json_lisp_eid_table_dump(vam);
12361           }
12362       }
12363
12364       vam->noprint_msg = 0;
12365     });
12366
12367     /* NOTREACHED */
12368     return 0;
12369 }
12370
12371 static int
12372 api_lisp_gpe_tunnel_dump(vat_main_t *vam)
12373 {
12374     vl_api_lisp_gpe_tunnel_dump_t *mp;
12375     f64 timeout = ~0;
12376
12377     if (!vam->json_output) {
12378         fformat(vam->ofp, "%=20s%=30s%=16s%=16s%=16s%=16s"
12379                 "%=16s%=16s%=16s%=16s%=16s\n",
12380                 "Tunel", "Source", "Destination", "Fib encap", "Fib decap",
12381                 "Decap next", "Lisp version", "Flags", "Next protocol",
12382                 "ver_res", "res", "iid");
12383     }
12384
12385     M(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump);
12386     /* send it... */
12387     S;
12388
12389     /* Use a control ping for synchronization */
12390     {
12391         vl_api_control_ping_t * mp;
12392         M(CONTROL_PING, control_ping);
12393         S;
12394     }
12395     /* Wait for a reply... */
12396     W;
12397
12398     /* NOTREACHED */
12399     return 0;
12400 }
12401
12402 static int
12403 api_lisp_map_resolver_dump(vat_main_t *vam)
12404 {
12405     vl_api_lisp_map_resolver_dump_t *mp;
12406     f64 timeout = ~0;
12407
12408     if (!vam->json_output) {
12409         fformat(vam->ofp, "%=20s\n",
12410                 "Map resolver");
12411     }
12412
12413     M(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump);
12414     /* send it... */
12415     S;
12416
12417     /* Use a control ping for synchronization */
12418     {
12419         vl_api_control_ping_t * mp;
12420         M(CONTROL_PING, control_ping);
12421         S;
12422     }
12423     /* Wait for a reply... */
12424     W;
12425
12426     /* NOTREACHED */
12427     return 0;
12428 }
12429
12430 static int
12431 api_show_lisp_status(vat_main_t *vam)
12432 {
12433     vl_api_show_lisp_status_t *mp;
12434     f64 timeout = ~0;
12435
12436     if (!vam->json_output) {
12437         fformat(vam->ofp, "%-20s%-16s\n",
12438                 "lisp status", "locator-set");
12439     }
12440
12441     M(SHOW_LISP_STATUS, show_lisp_status);
12442     /* send it... */
12443     S;
12444     /* Wait for a reply... */
12445     W;
12446
12447     /* NOTREACHED */
12448     return 0;
12449 }
12450
12451 static int
12452 api_lisp_get_map_request_itr_rlocs(vat_main_t *vam)
12453 {
12454     vl_api_lisp_get_map_request_itr_rlocs_t *mp;
12455     f64 timeout = ~0;
12456
12457     if (!vam->json_output) {
12458         fformat(vam->ofp, "%=20s\n",
12459                 "itr-rlocs:");
12460     }
12461
12462     M(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs);
12463     /* send it... */
12464     S;
12465     /* Wait for a reply... */
12466     W;
12467
12468     /* NOTREACHED */
12469     return 0;
12470 }
12471
12472 static int
12473 api_af_packet_create (vat_main_t * vam)
12474 {
12475     unformat_input_t * i = vam->input;
12476     vl_api_af_packet_create_t * mp;
12477     f64 timeout;
12478     u8 * host_if_name = 0;
12479     u8 hw_addr[6];
12480     u8 random_hw_addr = 1;
12481
12482     memset (hw_addr, 0, sizeof (hw_addr));
12483
12484     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12485         if (unformat (i, "name %s", &host_if_name))
12486             vec_add1 (host_if_name, 0);
12487         else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
12488             random_hw_addr = 0;
12489         else
12490           break;
12491     }
12492
12493     if (!vec_len (host_if_name)) {
12494         errmsg ("host-interface name must be specified");
12495         return -99;
12496     }
12497
12498     if (vec_len (host_if_name) > 64) {
12499         errmsg ("host-interface name too long");
12500         return -99;
12501     }
12502
12503     M(AF_PACKET_CREATE, af_packet_create);
12504
12505     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
12506     clib_memcpy (mp->hw_addr, hw_addr, 6);
12507     mp->use_random_hw_addr = random_hw_addr;
12508     vec_free (host_if_name);
12509
12510     S; W2(fprintf(vam->ofp," new sw_if_index = %d ", vam->sw_if_index));
12511     /* NOTREACHED */
12512     return 0;
12513 }
12514
12515 static int
12516 api_af_packet_delete (vat_main_t * vam)
12517 {
12518     unformat_input_t * i = vam->input;
12519     vl_api_af_packet_delete_t * mp;
12520     f64 timeout;
12521     u8 * host_if_name = 0;
12522
12523     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12524         if (unformat (i, "name %s", &host_if_name))
12525             vec_add1 (host_if_name, 0);
12526         else
12527           break;
12528     }
12529
12530     if (!vec_len (host_if_name)) {
12531         errmsg ("host-interface name must be specified");
12532         return -99;
12533     }
12534
12535     if (vec_len (host_if_name) > 64) {
12536         errmsg ("host-interface name too long");
12537         return -99;
12538     }
12539
12540     M(AF_PACKET_DELETE, af_packet_delete);
12541
12542     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
12543     vec_free (host_if_name);
12544
12545     S; W;
12546     /* NOTREACHED */
12547     return 0;
12548 }
12549
12550 static int
12551 api_policer_add_del (vat_main_t * vam)
12552 {
12553     unformat_input_t * i = vam->input;
12554     vl_api_policer_add_del_t * mp;
12555     f64 timeout;
12556     u8 is_add = 1;
12557     u8 * name = 0;
12558     u32 cir = 0;
12559     u32 eir = 0;
12560     u64 cb = 0;
12561     u64 eb = 0;
12562     u8 rate_type = 0;
12563     u8 round_type = 0;
12564     u8 type = 0;
12565     u8 color_aware = 0;
12566     sse2_qos_pol_action_params_st conform_action, exceed_action, violate_action;
12567
12568     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12569         if (unformat (i, "del"))
12570             is_add = 0;
12571         else if (unformat (i, "name %s", &name))
12572             vec_add1 (name, 0);
12573         else if (unformat (i, "cir %u", &cir))
12574             ;
12575         else if (unformat (i, "eir %u", &eir))
12576             ;
12577         else if (unformat (i, "cb %u", &cb))
12578             ;
12579         else if (unformat (i, "eb %u", &eb))
12580             ;
12581         else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
12582                            &rate_type))
12583             ;
12584         else if (unformat (i, "round_type %U", unformat_policer_round_type,
12585                            &round_type))
12586             ;
12587         else if (unformat (i, "type %U", unformat_policer_type, &type))
12588             ;
12589         else if (unformat (i, "conform_action %U", unformat_policer_action_type,
12590                            &conform_action))
12591             ;
12592         else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
12593                            &exceed_action))
12594             ;
12595         else if (unformat (i, "violate_action %U", unformat_policer_action_type,
12596                            &violate_action))
12597             ;
12598         else if (unformat (i, "color-aware"))
12599             color_aware = 1;
12600         else
12601           break;
12602     }
12603
12604     if (!vec_len (name)) {
12605         errmsg ("policer name must be specified");
12606         return -99;
12607     }
12608
12609     if (vec_len (name) > 64) {
12610         errmsg ("policer name too long");
12611         return -99;
12612     }
12613
12614     M(POLICER_ADD_DEL, policer_add_del);
12615
12616     clib_memcpy (mp->name, name, vec_len (name));
12617     vec_free (name);
12618     mp->is_add = is_add;
12619     mp->cir = cir;
12620     mp->eir = eir;
12621     mp->cb = cb;
12622     mp->eb = eb;
12623     mp->rate_type = rate_type;
12624     mp->round_type = round_type;
12625     mp->type = type;
12626     mp->conform_action_type = conform_action.action_type;
12627     mp->conform_dscp = conform_action.dscp;
12628     mp->exceed_action_type = exceed_action.action_type;
12629     mp->exceed_dscp = exceed_action.dscp;
12630     mp->violate_action_type = violate_action.action_type;
12631     mp->violate_dscp = violate_action.dscp;
12632     mp->color_aware = color_aware;
12633
12634     S; W;
12635     /* NOTREACHED */
12636     return 0;
12637 }
12638
12639 static int
12640 api_policer_dump(vat_main_t *vam)
12641 {
12642     unformat_input_t * i = vam->input;
12643     vl_api_policer_dump_t *mp;
12644     f64 timeout = ~0;
12645     u8 *match_name = 0;
12646     u8 match_name_valid = 0;
12647
12648     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12649         if (unformat (i, "name %s", &match_name)) {
12650             vec_add1 (match_name, 0);
12651             match_name_valid = 1;
12652         } else
12653             break;
12654     }
12655
12656     M(POLICER_DUMP, policer_dump);
12657     mp->match_name_valid = match_name_valid;
12658     clib_memcpy (mp->match_name, match_name, vec_len (match_name));
12659     vec_free (match_name);
12660     /* send it... */
12661     S;
12662
12663     /* Use a control ping for synchronization */
12664     {
12665         vl_api_control_ping_t * mp;
12666         M(CONTROL_PING, control_ping);
12667         S;
12668     }
12669     /* Wait for a reply... */
12670     W;
12671
12672     /* NOTREACHED */
12673     return 0;
12674 }
12675
12676 static int
12677 api_policer_classify_set_interface (vat_main_t * vam)
12678 {
12679     unformat_input_t * i = vam->input;
12680     vl_api_policer_classify_set_interface_t *mp;
12681     f64 timeout;
12682     u32 sw_if_index;
12683     int sw_if_index_set;
12684     u32 ip4_table_index = ~0;
12685     u32 ip6_table_index = ~0;
12686     u32 l2_table_index = ~0;
12687     u8 is_add = 1;
12688
12689     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12690         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
12691             sw_if_index_set = 1;
12692         else if (unformat (i, "sw_if_index %d", &sw_if_index))
12693             sw_if_index_set = 1;
12694         else if (unformat (i, "del"))
12695             is_add = 0;
12696         else if (unformat (i, "ip4-table %d", &ip4_table_index))
12697             ;
12698         else if (unformat (i, "ip6-table %d", &ip6_table_index))
12699             ;
12700         else if (unformat (i, "l2-table %d", &l2_table_index))
12701             ;
12702         else {
12703             clib_warning ("parse error '%U'", format_unformat_error, i);
12704             return -99;
12705         }
12706     }
12707
12708     if (sw_if_index_set == 0) {
12709         errmsg ("missing interface name or sw_if_index\n");
12710         return -99;
12711     }
12712
12713     M(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface);
12714
12715     mp->sw_if_index = ntohl(sw_if_index);
12716     mp->ip4_table_index = ntohl(ip4_table_index);
12717     mp->ip6_table_index = ntohl(ip6_table_index);
12718     mp->l2_table_index = ntohl(l2_table_index);
12719     mp->is_add = is_add;
12720
12721     S; W;
12722     /* NOTREACHED */
12723     return 0;
12724 }
12725
12726 static int
12727 api_policer_classify_dump(vat_main_t *vam)
12728 {
12729     unformat_input_t * i = vam->input;
12730     vl_api_policer_classify_dump_t *mp;
12731     f64 timeout = ~0;
12732     u8 type = POLICER_CLASSIFY_N_TABLES;
12733
12734     if (unformat (i, "type %U", unformat_classify_table_type, &type))
12735         ;
12736     else {
12737         errmsg ("classify table type must be specified\n");
12738         return -99;
12739     }
12740
12741     if (!vam->json_output) {
12742         fformat(vam->ofp, "%10s%20s\n", "Intfc idx", "Classify table");
12743     }
12744
12745     M(POLICER_CLASSIFY_DUMP, policer_classify_dump);
12746     mp->type = type;
12747     /* send it... */
12748     S;
12749
12750     /* Use a control ping for synchronization */
12751     {
12752         vl_api_control_ping_t * mp;
12753         M(CONTROL_PING, control_ping);
12754         S;
12755     }
12756     /* Wait for a reply... */
12757     W;
12758
12759     /* NOTREACHED */
12760     return 0;
12761 }
12762
12763 static int
12764 api_netmap_create (vat_main_t * vam)
12765 {
12766     unformat_input_t * i = vam->input;
12767     vl_api_netmap_create_t * mp;
12768     f64 timeout;
12769     u8 * if_name = 0;
12770     u8 hw_addr[6];
12771     u8 random_hw_addr = 1;
12772     u8 is_pipe = 0;
12773     u8 is_master = 0;
12774
12775     memset (hw_addr, 0, sizeof (hw_addr));
12776
12777     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12778         if (unformat (i, "name %s", &if_name))
12779             vec_add1 (if_name, 0);
12780         else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
12781             random_hw_addr = 0;
12782         else if (unformat (i, "pipe"))
12783             is_pipe = 1;
12784         else if (unformat (i, "master"))
12785             is_master = 1;
12786         else if (unformat (i, "slave"))
12787             is_master = 0;
12788         else
12789           break;
12790     }
12791
12792     if (!vec_len (if_name)) {
12793         errmsg ("interface name must be specified");
12794         return -99;
12795     }
12796
12797     if (vec_len (if_name) > 64) {
12798         errmsg ("interface name too long");
12799         return -99;
12800     }
12801
12802     M(NETMAP_CREATE, netmap_create);
12803
12804     clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name));
12805     clib_memcpy (mp->hw_addr, hw_addr, 6);
12806     mp->use_random_hw_addr = random_hw_addr;
12807     mp->is_pipe = is_pipe;
12808     mp->is_master = is_master;
12809     vec_free (if_name);
12810
12811     S; W;
12812     /* NOTREACHED */
12813     return 0;
12814 }
12815
12816 static int
12817 api_netmap_delete (vat_main_t * vam)
12818 {
12819     unformat_input_t * i = vam->input;
12820     vl_api_netmap_delete_t * mp;
12821     f64 timeout;
12822     u8 * if_name = 0;
12823
12824     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12825         if (unformat (i, "name %s", &if_name))
12826             vec_add1 (if_name, 0);
12827         else
12828             break;
12829     }
12830
12831     if (!vec_len (if_name)) {
12832         errmsg ("interface name must be specified");
12833         return -99;
12834     }
12835
12836     if (vec_len (if_name) > 64) {
12837         errmsg ("interface name too long");
12838         return -99;
12839     }
12840
12841     M(NETMAP_DELETE, netmap_delete);
12842
12843     clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name));
12844     vec_free (if_name);
12845
12846     S; W;
12847     /* NOTREACHED */
12848     return 0;
12849 }
12850
12851 static void vl_api_mpls_gre_tunnel_details_t_handler
12852 (vl_api_mpls_gre_tunnel_details_t * mp)
12853 {
12854     vat_main_t * vam = &vat_main;
12855     i32 i;
12856     i32 len = ntohl(mp->nlabels);
12857
12858     if (mp->l2_only == 0) {
12859         fformat(vam->ofp, "[%d]: src %U, dst %U, adj %U/%d, labels ",
12860                 ntohl(mp->tunnel_index),
12861                 format_ip4_address, &mp->tunnel_src,
12862                 format_ip4_address, &mp->tunnel_dst,
12863                 format_ip4_address, &mp->intfc_address,
12864                 ntohl(mp->mask_width));
12865         for (i = 0; i < len; i++) {
12866             fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
12867         }
12868         fformat(vam->ofp, "\n");
12869         fformat(vam->ofp, "      inner fib index %d, outer fib index %d\n",
12870                 ntohl(mp->inner_fib_index), ntohl(mp->outer_fib_index));
12871     } else {
12872         fformat(vam->ofp, "[%d]: src %U, dst %U, key %U, labels ",
12873                 ntohl(mp->tunnel_index),
12874                 format_ip4_address, &mp->tunnel_src,
12875                 format_ip4_address, &mp->tunnel_dst,
12876                 format_ip4_address, &mp->intfc_address);
12877         for (i = 0; i < len; i++) {
12878             fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
12879         }
12880         fformat(vam->ofp, "\n");
12881         fformat(vam->ofp, "      l2 interface %d, outer fib index %d\n",
12882                 ntohl(mp->hw_if_index), ntohl(mp->outer_fib_index));
12883     }
12884 }
12885
12886 static void vl_api_mpls_gre_tunnel_details_t_handler_json
12887 (vl_api_mpls_gre_tunnel_details_t * mp)
12888 {
12889     vat_main_t * vam = &vat_main;
12890     vat_json_node_t *node = NULL;
12891     struct in_addr ip4;
12892     i32 i;
12893     i32 len = ntohl(mp->nlabels);
12894
12895     if (VAT_JSON_ARRAY != vam->json_tree.type) {
12896         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
12897         vat_json_init_array(&vam->json_tree);
12898     }
12899     node = vat_json_array_add(&vam->json_tree);
12900
12901     vat_json_init_object(node);
12902     vat_json_object_add_uint(node, "tunnel_index", ntohl(mp->tunnel_index));
12903     clib_memcpy(&ip4, &(mp->intfc_address), sizeof(ip4));
12904     vat_json_object_add_ip4(node, "intfc_address", ip4);
12905     vat_json_object_add_uint(node, "inner_fib_index", ntohl(mp->inner_fib_index));
12906     vat_json_object_add_uint(node, "mask_width", ntohl(mp->mask_width));
12907     vat_json_object_add_uint(node, "encap_index", ntohl(mp->encap_index));
12908     vat_json_object_add_uint(node, "hw_if_index", ntohl(mp->hw_if_index));
12909     vat_json_object_add_uint(node, "l2_only", ntohl(mp->l2_only));
12910     clib_memcpy(&ip4, &(mp->tunnel_src), sizeof(ip4));
12911     vat_json_object_add_ip4(node, "tunnel_src", ip4);
12912     clib_memcpy(&ip4, &(mp->tunnel_dst), sizeof(ip4));
12913     vat_json_object_add_ip4(node, "tunnel_dst", ip4);
12914     vat_json_object_add_uint(node, "outer_fib_index", ntohl(mp->outer_fib_index));
12915     vat_json_object_add_uint(node, "label_count", len);
12916     for (i = 0; i < len; i++) {
12917         vat_json_object_add_uint(node, "label", ntohl(mp->labels[i]));
12918     }
12919 }
12920
12921 static int api_mpls_gre_tunnel_dump (vat_main_t * vam)
12922 {
12923     vl_api_mpls_gre_tunnel_dump_t *mp;
12924     f64 timeout;
12925     i32 index = -1;
12926
12927     /* Parse args required to build the message */
12928     while (unformat_check_input (vam->input) != UNFORMAT_END_OF_INPUT) {
12929         if (!unformat (vam->input, "tunnel_index %d", &index)) {
12930             index = -1;
12931             break;
12932         }
12933     }
12934
12935     fformat(vam->ofp, "  tunnel_index %d\n", index);
12936
12937     M(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump);
12938     mp->tunnel_index = htonl(index);
12939     S;
12940
12941     /* Use a control ping for synchronization */
12942     {
12943         vl_api_control_ping_t * mp;
12944         M(CONTROL_PING, control_ping);
12945         S;
12946     }
12947     W;
12948 }
12949
12950 static void vl_api_mpls_eth_tunnel_details_t_handler
12951 (vl_api_mpls_eth_tunnel_details_t * mp)
12952 {
12953     vat_main_t * vam = &vat_main;
12954     i32 i;
12955     i32 len = ntohl(mp->nlabels);
12956
12957     fformat(vam->ofp, "[%d]: dst %U, adj %U/%d, labels ",
12958             ntohl(mp->tunnel_index),
12959             format_ethernet_address, &mp->tunnel_dst_mac,
12960             format_ip4_address, &mp->intfc_address,
12961             ntohl(mp->mask_width));
12962     for (i = 0; i < len; i++) {
12963         fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
12964     }
12965     fformat(vam->ofp, "\n");
12966     fformat(vam->ofp, "      tx on %d, rx fib index %d\n",
12967             ntohl(mp->tx_sw_if_index),
12968             ntohl(mp->inner_fib_index));
12969 }
12970
12971 static void vl_api_mpls_eth_tunnel_details_t_handler_json
12972 (vl_api_mpls_eth_tunnel_details_t * mp)
12973 {
12974     vat_main_t * vam = &vat_main;
12975     vat_json_node_t *node = NULL;
12976     struct in_addr ip4;
12977     i32 i;
12978     i32 len = ntohl(mp->nlabels);
12979
12980     if (VAT_JSON_ARRAY != vam->json_tree.type) {
12981         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
12982         vat_json_init_array(&vam->json_tree);
12983     }
12984     node = vat_json_array_add(&vam->json_tree);
12985
12986     vat_json_init_object(node);
12987     vat_json_object_add_uint(node, "tunnel_index", ntohl(mp->tunnel_index));
12988     clib_memcpy(&ip4, &(mp->intfc_address), sizeof(ip4));
12989     vat_json_object_add_ip4(node, "intfc_address", ip4);
12990     vat_json_object_add_uint(node, "inner_fib_index", ntohl(mp->inner_fib_index));
12991     vat_json_object_add_uint(node, "mask_width", ntohl(mp->mask_width));
12992     vat_json_object_add_uint(node, "encap_index", ntohl(mp->encap_index));
12993     vat_json_object_add_uint(node, "hw_if_index", ntohl(mp->hw_if_index));
12994     vat_json_object_add_uint(node, "l2_only", ntohl(mp->l2_only));
12995     vat_json_object_add_string_copy(node, "tunnel_dst_mac",
12996             format(0, "%U", format_ethernet_address, &mp->tunnel_dst_mac));
12997     vat_json_object_add_uint(node, "tx_sw_if_index", ntohl(mp->tx_sw_if_index));
12998     vat_json_object_add_uint(node, "label_count", len);
12999     for (i = 0; i < len; i++) {
13000         vat_json_object_add_uint(node, "label", ntohl(mp->labels[i]));
13001     }
13002 }
13003
13004 static int api_mpls_eth_tunnel_dump (vat_main_t * vam)
13005 {
13006     vl_api_mpls_eth_tunnel_dump_t *mp;
13007     f64 timeout;
13008     i32 index = -1;
13009
13010     /* Parse args required to build the message */
13011     while (unformat_check_input (vam->input) != UNFORMAT_END_OF_INPUT) {
13012         if (!unformat (vam->input, "tunnel_index %d", &index)) {
13013             index = -1;
13014             break;
13015         }
13016     }
13017
13018     fformat(vam->ofp, "  tunnel_index %d\n", index);
13019
13020     M(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump);
13021     mp->tunnel_index = htonl(index);
13022     S;
13023
13024     /* Use a control ping for synchronization */
13025     {
13026         vl_api_control_ping_t * mp;
13027         M(CONTROL_PING, control_ping);
13028         S;
13029     }
13030     W;
13031 }
13032
13033 static void vl_api_mpls_fib_encap_details_t_handler
13034 (vl_api_mpls_fib_encap_details_t * mp)
13035 {
13036     vat_main_t * vam = &vat_main;
13037     i32 i;
13038     i32 len = ntohl(mp->nlabels);
13039
13040     fformat(vam->ofp, "table %d, dest %U, label ",
13041             ntohl(mp->fib_index),
13042             format_ip4_address, &mp->dest,
13043             len);
13044     for (i = 0; i < len; i++) {
13045         fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
13046     }
13047     fformat(vam->ofp, "\n");
13048 }
13049
13050 static void vl_api_mpls_fib_encap_details_t_handler_json
13051 (vl_api_mpls_fib_encap_details_t * mp)
13052 {
13053     vat_main_t * vam = &vat_main;
13054     vat_json_node_t *node = NULL;
13055     i32 i;
13056     i32 len = ntohl(mp->nlabels);
13057     struct in_addr ip4;
13058
13059     if (VAT_JSON_ARRAY != vam->json_tree.type) {
13060         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
13061         vat_json_init_array(&vam->json_tree);
13062     }
13063     node = vat_json_array_add(&vam->json_tree);
13064
13065     vat_json_init_object(node);
13066     vat_json_object_add_uint(node, "table", ntohl(mp->fib_index));
13067     vat_json_object_add_uint(node, "entry_index", ntohl(mp->entry_index));
13068     clib_memcpy(&ip4, &(mp->dest), sizeof(ip4));
13069     vat_json_object_add_ip4(node, "dest", ip4);
13070     vat_json_object_add_uint(node, "s_bit", ntohl(mp->s_bit));
13071     vat_json_object_add_uint(node, "label_count", len);
13072     for (i = 0; i < len; i++) {
13073         vat_json_object_add_uint(node, "label", ntohl(mp->labels[i]));
13074     }
13075 }
13076
13077 static int api_mpls_fib_encap_dump (vat_main_t * vam)
13078 {
13079     vl_api_mpls_fib_encap_dump_t *mp;
13080     f64 timeout;
13081
13082     M(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump);
13083     S;
13084
13085     /* Use a control ping for synchronization */
13086     {
13087         vl_api_control_ping_t * mp;
13088         M(CONTROL_PING, control_ping);
13089         S;
13090     }
13091     W;
13092 }
13093
13094 static void vl_api_mpls_fib_decap_details_t_handler
13095 (vl_api_mpls_fib_decap_details_t * mp)
13096 {
13097     vat_main_t * vam = &vat_main;
13098
13099     fformat(vam->ofp, "RX table %d, TX table/intfc %u, swif_tag '%s', label %u, s_bit %u\n",
13100             ntohl(mp->rx_table_id),
13101             ntohl(mp->tx_table_id),
13102             mp->swif_tag,
13103             ntohl(mp->label),
13104             ntohl(mp->s_bit));
13105 }
13106
13107 static void vl_api_mpls_fib_decap_details_t_handler_json
13108 (vl_api_mpls_fib_decap_details_t * mp)
13109 {
13110     vat_main_t * vam = &vat_main;
13111     vat_json_node_t *node = NULL;
13112     struct in_addr ip4;
13113
13114     if (VAT_JSON_ARRAY != vam->json_tree.type) {
13115         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
13116         vat_json_init_array(&vam->json_tree);
13117     }
13118     node = vat_json_array_add(&vam->json_tree);
13119
13120     vat_json_init_object(node);
13121     vat_json_object_add_uint(node, "table", ntohl(mp->fib_index));
13122     vat_json_object_add_uint(node, "entry_index", ntohl(mp->entry_index));
13123     clib_memcpy(&ip4, &(mp->dest), sizeof(ip4));
13124     vat_json_object_add_ip4(node, "dest", ip4);
13125     vat_json_object_add_uint(node, "s_bit", ntohl(mp->s_bit));
13126     vat_json_object_add_uint(node, "label", ntohl(mp->label));
13127     vat_json_object_add_uint(node, "rx_table_id", ntohl(mp->rx_table_id));
13128     vat_json_object_add_uint(node, "tx_table_id", ntohl(mp->tx_table_id));
13129     vat_json_object_add_string_copy(node, "swif_tag", mp->swif_tag);
13130 }
13131
13132 static int api_mpls_fib_decap_dump (vat_main_t * vam)
13133 {
13134     vl_api_mpls_fib_decap_dump_t *mp;
13135     f64 timeout;
13136
13137     M(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump);
13138     S;
13139
13140     /* Use a control ping for synchronization */
13141     {
13142         vl_api_control_ping_t * mp;
13143         M(CONTROL_PING, control_ping);
13144         S;
13145     }
13146     W;
13147 }
13148
13149 int api_classify_table_ids (vat_main_t *vam)
13150 {
13151     vl_api_classify_table_ids_t *mp;
13152     f64 timeout;
13153
13154     /* Construct the API message */
13155     M(CLASSIFY_TABLE_IDS, classify_table_ids);
13156     mp->context = 0;
13157
13158     S; W;
13159     /* NOTREACHED */
13160     return 0;
13161 }
13162
13163 int api_classify_table_by_interface (vat_main_t *vam)
13164 {
13165     unformat_input_t * input = vam->input;
13166     vl_api_classify_table_by_interface_t *mp;
13167     f64 timeout;
13168
13169     u32 sw_if_index = ~0;
13170     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13171         if (unformat (input, "%U", unformat_sw_if_index, vam, &sw_if_index))
13172             ;
13173         else if (unformat (input, "sw_if_index %d", &sw_if_index))
13174             ;
13175         else
13176             break;
13177     }
13178     if (sw_if_index == ~0) {
13179         errmsg ("missing interface name or sw_if_index\n");
13180         return -99;
13181     }
13182
13183     /* Construct the API message */
13184     M(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface);
13185     mp->context = 0;
13186     mp->sw_if_index = ntohl(sw_if_index);
13187
13188     S; W;
13189     /* NOTREACHED */
13190     return 0;
13191 }
13192
13193 int api_classify_table_info (vat_main_t *vam)
13194 {
13195     unformat_input_t * input = vam->input;
13196     vl_api_classify_table_info_t *mp;
13197     f64 timeout;
13198
13199     u32 table_id = ~0;
13200     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13201         if (unformat (input, "table_id %d", &table_id))
13202             ;
13203         else
13204             break;
13205     }
13206     if (table_id == ~0) {
13207         errmsg ("missing table id\n");
13208         return -99;
13209     }
13210
13211     /* Construct the API message */
13212     M(CLASSIFY_TABLE_INFO, classify_table_info);
13213     mp->context = 0;
13214     mp->table_id = ntohl(table_id);
13215
13216     S; W;
13217     /* NOTREACHED */
13218     return 0;
13219 }
13220
13221 int api_classify_session_dump (vat_main_t *vam)
13222 {
13223     unformat_input_t * input = vam->input;
13224     vl_api_classify_session_dump_t *mp;
13225     f64 timeout;
13226
13227     u32 table_id = ~0;
13228     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13229         if (unformat (input, "table_id %d", &table_id))
13230             ;
13231         else
13232             break;
13233     }
13234     if (table_id == ~0) {
13235         errmsg ("missing table id\n");
13236         return -99;
13237     }
13238
13239     /* Construct the API message */
13240     M(CLASSIFY_SESSION_DUMP, classify_session_dump);
13241     mp->context = 0;
13242     mp->table_id = ntohl(table_id);
13243     S;
13244
13245     /* Use a control ping for synchronization */
13246     {
13247         vl_api_control_ping_t * mp;
13248         M(CONTROL_PING, control_ping);
13249         S;
13250     }
13251     W;
13252     /* NOTREACHED */
13253     return 0;
13254 }
13255
13256 static void vl_api_ipfix_details_t_handler (vl_api_ipfix_details_t * mp)
13257 {
13258     vat_main_t * vam = &vat_main;
13259
13260     fformat(vam->ofp, "collector_address %U, collector_port %d, "
13261                       "src_address %U, fib_index %u, path_mtu %u, "
13262                       "template_interval %u\n",
13263             format_ip4_address, mp->collector_address,
13264             ntohs(mp->collector_port),
13265             format_ip4_address, mp->src_address,
13266             ntohl(mp->fib_index),
13267             ntohl(mp->path_mtu),
13268             ntohl(mp->template_interval));
13269
13270     vam->retval = 0;
13271     vam->result_ready = 1;
13272 }
13273
13274 static void vl_api_ipfix_details_t_handler_json
13275 (vl_api_ipfix_details_t * mp)
13276 {
13277     vat_main_t * vam = &vat_main;
13278     vat_json_node_t node;
13279     struct in_addr collector_address;
13280     struct in_addr src_address;
13281
13282     vat_json_init_object(&node);
13283     clib_memcpy(&collector_address, &mp->collector_address,
13284                 sizeof(collector_address));
13285     vat_json_object_add_ip4(&node, "collector_address", collector_address);
13286     vat_json_object_add_uint(&node, "collector_port",
13287                              ntohs(mp->collector_port));
13288     clib_memcpy(&src_address, &mp->src_address, sizeof(src_address));
13289     vat_json_object_add_ip4(&node, "src_address", src_address);
13290     vat_json_object_add_uint(&node, "fib_index", ntohl(mp->fib_index));
13291     vat_json_object_add_uint(&node, "path_mtu", ntohl(mp->path_mtu));
13292     vat_json_object_add_uint(&node, "template_interval",
13293                              ntohl(mp->template_interval));
13294
13295     vat_json_print(vam->ofp, &node);
13296     vat_json_free(&node);
13297     vam->retval = 0;
13298     vam->result_ready = 1;
13299 }
13300
13301 int api_ipfix_dump (vat_main_t *vam)
13302 {
13303     vl_api_ipfix_dump_t *mp;
13304     f64 timeout;
13305
13306     /* Construct the API message */
13307     M(IPFIX_DUMP, ipfix_dump);
13308     mp->context = 0;
13309
13310     S; W;
13311     /* NOTREACHED */
13312     return 0;
13313 }
13314
13315 int api_pg_create_interface (vat_main_t *vam)
13316 {
13317     unformat_input_t * input = vam->input;
13318     vl_api_pg_create_interface_t *mp;
13319     f64 timeout;
13320
13321     u32 if_id = ~0;
13322     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13323         if (unformat (input, "if_id %d", &if_id))
13324             ;
13325         else
13326             break;
13327     }
13328     if (if_id == ~0) {
13329         errmsg ("missing pg interface index\n");
13330         return -99;
13331     }
13332
13333     /* Construct the API message */
13334     M(PG_CREATE_INTERFACE, pg_create_interface);
13335     mp->context = 0;
13336     mp->interface_id = ntohl(if_id);
13337
13338     S; W;
13339     /* NOTREACHED */
13340     return 0;
13341 }
13342
13343 int api_pg_capture (vat_main_t *vam)
13344 {
13345     unformat_input_t * input = vam->input;
13346     vl_api_pg_capture_t *mp;
13347     f64 timeout;
13348
13349     u32 if_id = ~0;
13350     u8 enable = 1;
13351     u32 count = 1;
13352     u8 pcap_file_set = 0;
13353     u8 * pcap_file = 0;
13354     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13355         if (unformat (input, "if_id %d", &if_id))
13356             ;
13357         else if (unformat (input, "pcap %s", &pcap_file))
13358             pcap_file_set = 1;
13359         else if (unformat (input, "count %d", &count))
13360             ;
13361         else if (unformat (input, "disable"))
13362             enable = 0;
13363         else
13364             break;
13365     }
13366     if (if_id == ~0) {
13367         errmsg ("missing pg interface index\n");
13368         return -99;
13369     }
13370     if (pcap_file_set>0) {
13371         if (vec_len (pcap_file) > 255) {
13372             errmsg ("pcap file name is too long\n");
13373             return -99;
13374         }
13375     }
13376
13377     u32 name_len = vec_len(pcap_file);
13378     /* Construct the API message */
13379     M(PG_CAPTURE, pg_capture);
13380     mp->context = 0;
13381     mp->interface_id = ntohl(if_id);
13382     mp->is_enabled = enable;
13383     mp->count = ntohl(count);
13384     mp->pcap_name_length = ntohl(name_len);
13385     if (pcap_file_set != 0) {
13386         clib_memcpy(mp->pcap_file_name, pcap_file, name_len);
13387     }
13388     vec_free(pcap_file);
13389
13390     S; W;
13391     /* NOTREACHED */
13392     return 0;
13393 }
13394
13395 int api_pg_enable_disable (vat_main_t *vam)
13396 {
13397     unformat_input_t * input = vam->input;
13398     vl_api_pg_enable_disable_t *mp;
13399     f64 timeout;
13400
13401     u8 enable = 1;
13402     u8 stream_name_set = 0;
13403     u8 * stream_name = 0;
13404     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13405         if (unformat (input, "stream %s", &stream_name))
13406             stream_name_set = 1;
13407         else if (unformat (input, "disable"))
13408             enable = 0;
13409         else
13410             break;
13411     }
13412
13413     if (stream_name_set>0) {
13414         if (vec_len (stream_name) > 255) {
13415             errmsg ("stream name too long\n");
13416             return -99;
13417         }
13418     }
13419
13420     u32 name_len = vec_len(stream_name);
13421     /* Construct the API message */
13422     M(PG_ENABLE_DISABLE, pg_enable_disable);
13423     mp->context = 0;
13424     mp->is_enabled = enable;
13425     if (stream_name_set != 0) {
13426         mp->stream_name_length = ntohl(name_len);
13427         clib_memcpy(mp->stream_name, stream_name, name_len);
13428     }
13429     vec_free(stream_name);
13430
13431     S; W;
13432     /* NOTREACHED */
13433     return 0;
13434 }
13435
13436 int api_ip_source_and_port_range_check_add_del (vat_main_t *vam)
13437 {
13438     unformat_input_t * input = vam->input;
13439     vl_api_ip_source_and_port_range_check_add_del_t *mp;
13440     f64 timeout;
13441
13442     u16 * low_ports = 0;
13443     u16 * high_ports = 0;
13444     u16 this_low;
13445     u16 this_hi;
13446     ip4_address_t ip4_addr;
13447     ip6_address_t ip6_addr;
13448     u32 length;
13449     u32 tmp, tmp2;
13450     u8 prefix_set = 0;
13451     u32 vrf_id =~0;
13452     u8 is_add = 1;
13453     u8 is_ipv6 = 0;
13454
13455     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13456         {
13457             if (unformat (input, "%U/%d", unformat_ip4_address, &ip4_addr, &length))
13458                 {
13459                     prefix_set = 1;
13460                 }
13461             else if (unformat (input, "%U/%d", unformat_ip6_address, &ip6_addr, &length))
13462                 {
13463                     prefix_set = 1;
13464                     is_ipv6 = 1;
13465                 }
13466             else if (unformat (input, "vrf %d", &vrf_id))
13467                 ;
13468             else if (unformat (input, "del"))
13469                 is_add = 0;
13470             else if (unformat (input, "port %d", &tmp))
13471                 {
13472                     if (tmp == 0 || tmp > 65535) {
13473                         errmsg ("port %d out of range", tmp);
13474                         return -99;
13475                     }
13476                     this_low = tmp;
13477                     this_hi = this_low + 1;
13478                     vec_add1 (low_ports, this_low);
13479                     vec_add1 (high_ports, this_hi);
13480                 }
13481             else if (unformat (input, "range %d - %d", &tmp, &tmp2))
13482                 {
13483                     if ((tmp > tmp2) ||
13484                         (tmp == 0) ||
13485                         (tmp2 > 65535)) {
13486                         errmsg ("incorrect range parameters\n");
13487                         return -99;
13488                     }
13489                     this_low = tmp;
13490                     /* Note: in debug CLI +1 is added to high before
13491                        passing to real fn that does "the work"
13492                        (ip_source_and_port_range_check_add_del).
13493                        This fn is a wrapper around the binary API fn a
13494                        control plane will call, which expects this increment
13495                        to have occurred. Hence letting the binary API control
13496                        plane fn do the increment for consistency between VAT
13497                        and other control planes.
13498                      */
13499                     this_hi = tmp2;
13500                     vec_add1 (low_ports, this_low);
13501                     vec_add1 (high_ports, this_hi);
13502                 }
13503             else
13504                 break;
13505         }
13506
13507     if (prefix_set == 0) {
13508         errmsg ("<address>/<mask> not specified\n");
13509         return -99;
13510     }
13511
13512     if (vrf_id == ~0) {
13513         errmsg ("VRF ID required, not specified\n");
13514         return -99;
13515     }
13516
13517     if (vrf_id == 0) {
13518         errmsg ("VRF ID should not be default. Should be distinct VRF for this purpose.\n");
13519         return -99;
13520     }
13521
13522     if (vec_len(low_ports) == 0) {
13523         errmsg ("At least one port or port range required\n");
13524         return -99;
13525     }
13526
13527     M(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, ip_source_and_port_range_check_add_del);
13528
13529     mp->is_add = is_add;
13530
13531     if (is_ipv6) {
13532         mp->is_ipv6 = 1;
13533         clib_memcpy (mp->address, &ip6_addr, sizeof (ip6_addr));
13534     } else {
13535         mp->is_ipv6 = 0;
13536         clib_memcpy (mp->address, &ip4_addr, sizeof (ip4_addr));
13537     }
13538
13539     mp->mask_length = length;
13540     mp->number_of_ranges = vec_len (low_ports);
13541
13542     clib_memcpy (mp->low_ports, low_ports, vec_len(low_ports));
13543     vec_free(low_ports);
13544
13545     clib_memcpy (mp->high_ports, high_ports, vec_len(high_ports));
13546     vec_free (high_ports);
13547
13548     mp->vrf_id = ntohl(vrf_id);
13549
13550     S; W;
13551     /* NOTREACHED */
13552     return 0;
13553 }
13554
13555 int api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
13556 {
13557     unformat_input_t * input = vam->input;
13558     vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
13559     f64 timeout;
13560     u32 sw_if_index = ~0;
13561     int vrf_set = 0;
13562     u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
13563     u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
13564     u8 is_add = 1;
13565
13566     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13567       {
13568         if (unformat (input, "%U", unformat_sw_if_index, vam, &sw_if_index))
13569             ;
13570         else if (unformat (input, "sw_if_index %d", &sw_if_index))
13571             ;
13572         else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
13573             vrf_set=1;
13574         else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
13575             vrf_set=1;
13576         else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
13577             vrf_set=1;
13578         else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
13579             vrf_set=1;
13580         else if (unformat (input, "del"))
13581             is_add = 0;
13582         else
13583               break;
13584       }
13585
13586     if (sw_if_index == ~0) {
13587           errmsg ("Interface required but not specified\n");
13588           return -99;
13589     }
13590
13591     if (vrf_set == 0) {
13592         errmsg ("VRF ID required but not specified\n");
13593         return -99;
13594     }
13595
13596     if (tcp_out_vrf_id == 0
13597         || udp_out_vrf_id == 0
13598         || tcp_in_vrf_id == 0
13599         || udp_in_vrf_id == 0) {
13600         errmsg ("VRF ID should not be default. Should be distinct VRF for this purpose.\n");
13601         return -99;
13602     }
13603
13604     /* Construct the API message */
13605     M(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, ip_source_and_port_range_check_interface_add_del);
13606
13607     mp->sw_if_index = ntohl (sw_if_index);
13608     mp->is_add = is_add;
13609     mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
13610     mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
13611     mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
13612     mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
13613
13614     /* send it... */
13615     S;
13616
13617     /* Wait for a reply... */
13618     W;
13619 }
13620
13621 static int q_or_quit (vat_main_t * vam)
13622 {
13623     longjmp (vam->jump_buf, 1);
13624     return 0; /* not so much */
13625 }
13626 static int q (vat_main_t * vam) {return q_or_quit (vam);}
13627 static int quit (vat_main_t * vam) {return q_or_quit (vam);}
13628
13629 static int comment (vat_main_t * vam)
13630 {
13631     return 0;
13632 }
13633
13634 static int cmd_cmp (void * a1, void * a2)
13635 {
13636   u8 ** c1 = a1;
13637   u8 ** c2 = a2;
13638
13639   return strcmp ((char *)(c1[0]), (char *)(c2[0]));
13640 }
13641
13642 static int help (vat_main_t * vam)
13643 {
13644     u8 ** cmds = 0;
13645     u8 * name = 0;
13646     hash_pair_t * p;
13647     unformat_input_t * i = vam->input;
13648     int j;
13649
13650     if (unformat (i, "%s", &name)) {
13651         uword *hs;
13652
13653         vec_add1(name, 0);
13654
13655         hs = hash_get_mem (vam->help_by_name, name);
13656         if (hs)
13657             fformat (vam->ofp, "usage: %s %s\n", name, hs[0]);
13658         else
13659             fformat (vam->ofp, "No such msg / command '%s'\n", name);
13660         vec_free(name);
13661         return 0;
13662     }
13663
13664     fformat(vam->ofp, "Help is available for the following:\n");
13665
13666     hash_foreach_pair (p, vam->function_by_name,
13667     ({
13668         vec_add1 (cmds, (u8 *)(p->key));
13669     }));
13670
13671     vec_sort_with_function (cmds, cmd_cmp);
13672
13673     for (j = 0; j < vec_len(cmds); j++)
13674         fformat (vam->ofp, "%s\n", cmds[j]);
13675
13676     vec_free (cmds);
13677     return 0;
13678 }
13679
13680 static int set (vat_main_t * vam)
13681 {
13682     u8 * name = 0, * value = 0;
13683     unformat_input_t * i = vam->input;
13684
13685     if (unformat (i, "%s", &name)) {
13686         /* The input buffer is a vector, not a string. */
13687         value = vec_dup (i->buffer);
13688         vec_delete (value, i->index, 0);
13689         /* Almost certainly has a trailing newline */
13690         if (value[vec_len(value)-1] == '\n')
13691             value[vec_len(value)-1] = 0;
13692         /* Make sure it's a proper string, one way or the other */
13693         vec_add1 (value, 0);
13694         (void) clib_macro_set_value (&vam->macro_main,
13695                                      (char *)name, (char *)value);
13696     }
13697     else
13698         errmsg ("usage: set <name> <value>\n");
13699
13700     vec_free (name);
13701     vec_free (value);
13702     return 0;
13703 }
13704
13705 static int unset (vat_main_t * vam)
13706 {
13707     u8 * name = 0;
13708
13709     if (unformat (vam->input, "%s", &name))
13710         if (clib_macro_unset (&vam->macro_main, (char *)name) == 1)
13711             errmsg ("unset: %s wasn't set\n", name);
13712     vec_free (name);
13713     return 0;
13714 }
13715
13716 typedef struct {
13717     u8 * name;
13718     u8 * value;
13719 } macro_sort_t;
13720
13721
13722 static int macro_sort_cmp (void * a1, void * a2)
13723 {
13724   macro_sort_t * s1 = a1;
13725   macro_sort_t * s2 = a2;
13726
13727   return strcmp ((char *)(s1->name), (char *)(s2->name));
13728 }
13729
13730 static int dump_macro_table (vat_main_t * vam)
13731 {
13732     macro_sort_t * sort_me = 0, * sm;
13733     int i;
13734     hash_pair_t * p;
13735
13736     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
13737     ({
13738         vec_add2 (sort_me, sm, 1);
13739         sm->name = (u8 *)(p->key);
13740         sm->value = (u8 *) (p->value[0]);
13741     }));
13742
13743     vec_sort_with_function (sort_me, macro_sort_cmp);
13744
13745     if (vec_len(sort_me))
13746         fformat (vam->ofp, "%-15s%s\n", "Name", "Value");
13747     else
13748         fformat (vam->ofp, "The macro table is empty...\n");
13749
13750     for (i = 0; i < vec_len (sort_me); i++)
13751         fformat (vam->ofp, "%-15s%s\n", sort_me[i].name,
13752                  sort_me[i].value);
13753     return 0;
13754 }
13755
13756 static int dump_node_table (vat_main_t * vam)
13757 {
13758     int i, j;
13759     vlib_node_t * node, * next_node;
13760
13761     if (vec_len (vam->graph_nodes) == 0) {
13762         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
13763         return 0;
13764     }
13765
13766     for (i = 0; i < vec_len (vam->graph_nodes); i++) {
13767         node = vam->graph_nodes[i];
13768         fformat (vam->ofp, "[%d] %s\n", i, node->name);
13769         for (j = 0; j < vec_len (node->next_nodes); j++) {
13770             if (node->next_nodes[j] != ~0) {
13771                 next_node = vam->graph_nodes[node->next_nodes[j]];
13772                 fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
13773             }
13774         }
13775     }
13776     return 0;
13777 }
13778
13779 static int search_node_table (vat_main_t * vam)
13780 {
13781     unformat_input_t * line_input = vam->input;
13782     u8 * node_to_find;
13783     int j;
13784     vlib_node_t * node, * next_node;
13785     uword * p;
13786
13787     if (vam->graph_node_index_by_name == 0) {
13788         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
13789         return 0;
13790     }
13791
13792     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
13793         if (unformat (line_input, "%s", &node_to_find)) {
13794             vec_add1 (node_to_find, 0);
13795             p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
13796             if (p == 0) {
13797                 fformat (vam->ofp, "%s not found...\n", node_to_find);
13798                 goto out;
13799             }
13800             node = vam->graph_nodes[p[0]];
13801             fformat (vam->ofp, "[%d] %s\n", p[0], node->name);
13802             for (j = 0; j < vec_len (node->next_nodes); j++) {
13803                 if (node->next_nodes[j] != ~0) {
13804                     next_node = vam->graph_nodes[node->next_nodes[j]];
13805                     fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
13806                 }
13807             }
13808         }
13809
13810         else {
13811             clib_warning ("parse error '%U'", format_unformat_error,
13812                           line_input);
13813             return -99;
13814         }
13815
13816     out:
13817         vec_free(node_to_find);
13818
13819     }
13820
13821     return 0;
13822 }
13823
13824
13825 static int script (vat_main_t * vam)
13826 {
13827     u8 * s = 0;
13828     char * save_current_file;
13829     unformat_input_t save_input;
13830     jmp_buf save_jump_buf;
13831     u32 save_line_number;
13832
13833     FILE * new_fp, * save_ifp;
13834
13835     if (unformat (vam->input, "%s", &s)) {
13836         new_fp = fopen ((char *)s, "r");
13837         if (new_fp == 0) {
13838             errmsg ("Couldn't open script file %s\n", s);
13839             vec_free (s);
13840             return -99;
13841         }
13842     } else {
13843         errmsg ("Missing script name\n");
13844         return -99;
13845     }
13846
13847     clib_memcpy (&save_input, &vam->input, sizeof (save_input));
13848     clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
13849     save_ifp = vam->ifp;
13850     save_line_number = vam->input_line_number;
13851     save_current_file = (char *) vam->current_file;
13852
13853     vam->input_line_number = 0;
13854     vam->ifp = new_fp;
13855     vam->current_file = s;
13856     do_one_file (vam);
13857
13858     clib_memcpy (&vam->input, &save_input, sizeof (vam->input));
13859     clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
13860     vam->ifp = save_ifp;
13861     vam->input_line_number = save_line_number;
13862     vam->current_file = (u8 *) save_current_file;
13863     vec_free (s);
13864
13865     return 0;
13866 }
13867
13868 static int echo (vat_main_t * vam)
13869 {
13870     fformat (vam->ofp, "%v", vam->input->buffer);
13871     return 0;
13872 }
13873
13874 /* List of API message constructors, CLI names map to api_xxx */
13875 #define foreach_vpe_api_msg                                             \
13876 _(create_loopback,"[mac <mac-addr>]")                                   \
13877 _(sw_interface_dump,"")                                                 \
13878 _(sw_interface_set_flags,                                               \
13879   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
13880 _(sw_interface_add_del_address,                                         \
13881   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
13882 _(sw_interface_set_table,                                               \
13883   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
13884 _(sw_interface_set_vpath,                                               \
13885   "<intfc> | sw_if_index <id> enable | disable")                        \
13886 _(sw_interface_set_l2_xconnect,                                         \
13887   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
13888   "enable | disable")                                                   \
13889 _(sw_interface_set_l2_bridge,                                           \
13890   "rx <intfc> | rx_sw_if_index <id> bd_id <bridge-domain-id>\n"         \
13891   "[shg <split-horizon-group>] [bvi]\n"                                 \
13892   "enable | disable")                                                   \
13893 _(bridge_domain_add_del,                                                \
13894   "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [del]\n")\
13895 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")     \
13896 _(l2fib_add_del,                                                        \
13897   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
13898 _(l2_flags,                                                             \
13899   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood]\n")       \
13900 _(bridge_flags,                                                         \
13901   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
13902 _(tap_connect,                                                          \
13903   "tapname <name> mac <mac-addr> | random-mac")                         \
13904 _(tap_modify,                                                           \
13905   "<vpp-if-name> | sw_if_index <id> tapname <name> mac <mac-addr> | random-mac") \
13906 _(tap_delete,                                                           \
13907   "<vpp-if-name> | sw_if_index <id>")                                   \
13908 _(sw_interface_tap_dump, "")                                            \
13909 _(ip_add_del_route,                                                     \
13910   "<addr>/<mask> via <addr> [vrf <n>]\n"                                \
13911   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
13912   "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
13913   "[multipath] [count <n>]")                                            \
13914 _(proxy_arp_add_del,                                                    \
13915   "<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]")                      \
13916 _(proxy_arp_intfc_enable_disable,                                       \
13917   "<intfc> | sw_if_index <id> enable | disable")                        \
13918 _(mpls_add_del_encap,                                                   \
13919   "label <n> dst <ip4-addr> [vrf <n>] [del]")                           \
13920 _(mpls_add_del_decap,                                                   \
13921   "label <n> [rx_vrf_id <n>] [tx_vrf_id] [s-bit-clear][del]")           \
13922 _(mpls_gre_add_del_tunnel,                                              \
13923   "inner_vrf_id <n> outer_vrf_id <n> src <ip4-address> dst <ip4-address>\n" \
13924   "adj <ip4-address>/<mask-width> [del]")                               \
13925 _(sw_interface_set_unnumbered,                                          \
13926   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
13927 _(ip_neighbor_add_del,                                                  \
13928   "(<intfc> | sw_if_index <id>) dst <ip46-address> "                    \
13929   "[mac <mac-addr>] [vrf <vrf-id>] [is_static] [del]")                  \
13930 _(reset_vrf, "vrf <id> [ipv6]")                                         \
13931 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
13932 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
13933   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
13934   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
13935   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
13936 _(oam_add_del, "src <ip4-address> dst <ip4-address> [vrf <n>] [del]")   \
13937 _(reset_fib, "vrf <n> [ipv6]")                                          \
13938 _(dhcp_proxy_config,                                                    \
13939   "svr <v46-address> src <v46-address>\n"                               \
13940    "insert-cid <n> [del]")                                              \
13941 _(dhcp_proxy_config_2,                                                  \
13942   "svr <v46-address> src <v46-address>\n"                               \
13943    "rx_vrf_id <nn> server_vrf_id <nn> insert-cid <n> [del]")            \
13944 _(dhcp_proxy_set_vss,                                                   \
13945   "tbl_id <n> fib_id <n> oui <n> [ipv6] [del]")                         \
13946 _(dhcp_client_config,                                                   \
13947   "<intfc> | sw_if_index <id> [hostname <name>] [disable_event] [del]") \
13948 _(set_ip_flow_hash,                                                     \
13949   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
13950 _(sw_interface_ip6_enable_disable,                                      \
13951   "<intfc> | sw_if_index <id> enable | disable")                        \
13952 _(sw_interface_ip6_set_link_local_address,                              \
13953   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>")              \
13954 _(sw_interface_ip6nd_ra_prefix,                                         \
13955   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>\n"             \
13956   "val_life <n> pref_life <n> [def] [noadv] [offl] [noauto]\n"          \
13957   "[nolink] [isno]")                                                    \
13958 _(sw_interface_ip6nd_ra_config,                                         \
13959   "<intfc> | sw_if_index <id> [maxint <n>] [minint <n>]\n"              \
13960   "[life <n>] [count <n>] [interval <n>] [suppress]\n"                  \
13961   "[managed] [other] [ll] [send] [cease] [isno] [def]")                 \
13962 _(set_arp_neighbor_limit, "arp_nbr_limit <n> [ipv6]")                   \
13963 _(l2_patch_add_del,                                                     \
13964   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
13965   "enable | disable")                                                   \
13966 _(mpls_ethernet_add_del_tunnel,                                         \
13967   "tx <intfc> | tx_sw_if_index <n> dst <mac-addr>\n"                    \
13968   "adj <ip4-addr>/<mw> dst <mac-addr> [del]")                           \
13969 _(mpls_ethernet_add_del_tunnel_2,                                       \
13970   "inner_vrf_id <n> outer_vrf_id <n> next-hop <ip4-addr>\n"             \
13971   "resolve-attempts <n> resolve-if-needed 0 | 1 [del]")                 \
13972 _(sr_tunnel_add_del,                                                    \
13973   "[name <name>] src <ip6-addr> dst <ip6-addr>/<mw> \n"                 \
13974   "(next <ip6-addr>)+ [tag <ip6-addr>]* [clean] [reroute] \n"           \
13975   "[policy <policy_name>]")                                             \
13976 _(sr_policy_add_del,                                                    \
13977   "name <name> tunnel <tunnel-name> [tunnel <tunnel-name>]* [del]")     \
13978 _(sr_multicast_map_add_del,                                             \
13979   "address [ip6 multicast address] sr-policy [policy name] [del]")      \
13980 _(classify_add_del_table,                                               \
13981   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
13982   "[del] mask <mask-value>\n"                                           \
13983   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>")              \
13984 _(classify_add_del_session,                                             \
13985   "[hit-next|l2-hit-next|acl-hit-next|policer-hit-next] <name|nn>\n"    \
13986   "  table-index <nn> skip_n <nn> match_n <nn> match [hex] [l2]\n"      \
13987   "  [l3 [ip4|ip6]]")                                                   \
13988 _(classify_set_interface_ip_table,                                      \
13989   "<intfc> | sw_if_index <nn> table <nn>")                              \
13990 _(classify_set_interface_l2_tables,                                     \
13991   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
13992   "  [other-table <nn>]")                                               \
13993 _(get_node_index, "node <node-name")                                    \
13994 _(add_node_next, "node <node-name> next <next-node-name>")              \
13995 _(l2tpv3_create_tunnel,                                                 \
13996   "client_address <ip6-addr> our_address <ip6-addr>\n"                  \
13997   "[local_session_id <nn>][remote_session_id <nn>][local_cookie <nn>]\n"\
13998   "[remote_cookie <nn>]\n[l2-sublayer-preset]\n")                       \
13999 _(l2tpv3_set_tunnel_cookies,                                            \
14000   "<intfc> | sw_if_index <nn> [new_local_cookie <nn>]\n"                \
14001   "[new_remote_cookie <nn>]\n")                                         \
14002 _(l2tpv3_interface_enable_disable,                                      \
14003   "<intfc> | sw_if_index <nn> enable | disable")                        \
14004 _(l2tpv3_set_lookup_key,                                                \
14005   "lookup_v6_src | lookup_v6_dst | lookup_session_id")                  \
14006 _(sw_if_l2tpv3_tunnel_dump, "")                                         \
14007 _(vxlan_add_del_tunnel,                                                 \
14008   "src <ip-addr> dst <ip-addr> vni <vni> [encap-vrf-id <nn>]\n"         \
14009   " [decap-next l2|ip4|ip6] [del]")                                     \
14010 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
14011 _(gre_add_del_tunnel,                                                   \
14012   "src <ip4-addr> dst <ip4-addr> [outer-fib-id <nn>] [del]\n")          \
14013 _(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                      \
14014 _(l2_fib_clear_table, "")                                               \
14015 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
14016 _(l2_interface_vlan_tag_rewrite,                                        \
14017   "<intfc> | sw_if_index <nn> \n"                                       \
14018   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
14019   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
14020 _(create_vhost_user_if,                                                 \
14021         "socket <filename> [server] [renumber <dev_instance>] "         \
14022         "[mac <mac_address>]")                                          \
14023 _(modify_vhost_user_if,                                                 \
14024         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
14025         "[server] [renumber <dev_instance>]")                           \
14026 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
14027 _(sw_interface_vhost_user_dump, "")                                     \
14028 _(show_version, "")                                                     \
14029 _(vxlan_gpe_add_del_tunnel,                                             \
14030   "local <addr> remote <addr> vni <nn>\n"                               \
14031     "[encap-vrf-id <nn>] [decap-vrf-id <nn>] [next-ip4][next-ip6]"      \
14032   "[next-ethernet] [next-nsh]\n")                                       \
14033 _(vxlan_gpe_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                \
14034 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
14035 _(interface_name_renumber,                                              \
14036   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
14037 _(input_acl_set_interface,                                              \
14038   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
14039   "  [l2-table <nn>] [del]")                                            \
14040 _(want_ip4_arp_events, "address <ip4-address> [del]")                   \
14041 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
14042 _(ip_dump, "ipv4 | ipv6")                                               \
14043 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
14044 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
14045   "  spid_id <n> ")                                                     \
14046 _(ipsec_sad_add_del_entry, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
14047   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
14048   "  integ_alg <alg> integ_key <hex>")                                  \
14049 _(ipsec_spd_add_del_entry, "spd_id <n> priority <n> action <action>\n"  \
14050   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
14051   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
14052   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" )\
14053 _(ipsec_sa_set_key, "sa_id <n> crypto_key <hex> integ_key <hex>")       \
14054 _(ikev2_profile_add_del, "name <profile_name> [del]")                   \
14055 _(ikev2_profile_set_auth, "name <profile_name> auth_method <method>\n"  \
14056   "(auth_data 0x<data> | auth_data <data>)")                            \
14057 _(ikev2_profile_set_id, "name <profile_name> id_type <type>\n"          \
14058   "(id_data 0x<data> | id_data <data>) (local|remote)")                 \
14059 _(ikev2_profile_set_ts, "name <profile_name> protocol <proto>\n"        \
14060   "start_port <port> end_port <port> start_addr <ip4> end_addr <ip4>\n" \
14061   "(local|remote)")                                                     \
14062 _(ikev2_set_local_key, "file <absolute_file_path>")                     \
14063 _(delete_loopback,"sw_if_index <nn>")                                   \
14064 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
14065 _(map_add_domain,                                                       \
14066   "ip4-pfx <ip4pfx> ip6-pfx <ip6pfx> "                                  \
14067   "ip6-src <ip6addr> "                                                  \
14068   "ea-bits-len <n> psid-offset <n> psid-len <n>")                       \
14069 _(map_del_domain, "index <n>")                                          \
14070 _(map_add_del_rule,                                                     \
14071   "index <n> psid <n> dst <ip6addr> [del]")                             \
14072 _(map_domain_dump, "")                                                  \
14073 _(map_rule_dump, "index <map-domain>")                                  \
14074 _(want_interface_events,  "enable|disable")                             \
14075 _(want_stats,"enable|disable")                                          \
14076 _(get_first_msg_id, "client <name>")                                    \
14077 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
14078 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
14079   "fib-id <nn> [ip4][ip6][default]")                                    \
14080 _(get_node_graph, " ")                                                  \
14081 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
14082 _(trace_profile_add, "id <nn> trace-type <0x1f|0x3|0x9|0x11|0x19> "     \
14083   "trace-elts <nn> trace-tsp <0|1|2|3> node-id <node id in hex> "       \
14084   "app-data <app_data in hex> [pow] [ppc <encap|decap>]")               \
14085 _(trace_profile_apply, "id <nn> <ip6-address>/<width>"                  \
14086   " vrf_id <nn>  add | pop | none")                                     \
14087 _(trace_profile_del, "")                                                \
14088 _(lisp_add_del_locator_set, "locator-set <locator_name> [iface <intf> |"\
14089                             " sw_if_index <sw_if_index> p <priority> "  \
14090                             "w <weight>] [del]")                        \
14091 _(lisp_add_del_locator, "locator-set <locator_name> "                   \
14092                         "iface <intf> | sw_if_index <sw_if_index> "     \
14093                         "p <priority> w <weight> [del]")                \
14094 _(lisp_add_del_local_eid,"vni <vni> eid "                               \
14095                          "<ipv4|ipv6>/<prefix> | <L2 address> "         \
14096                           "locator-set <locator_name> [del]")           \
14097 _(lisp_gpe_add_del_fwd_entry, "rmt_eid <eid> [lcl_eid <eid>] vni <vni>" \
14098   "dp_table <table> loc-pair <lcl_loc> <rmt_loc> ... [del]")            \
14099 _(lisp_add_del_map_resolver, "<ip4|6-addr> [del]")                      \
14100 _(lisp_gpe_enable_disable, "enable|disable")                            \
14101 _(lisp_enable_disable, "enable|disable")                                \
14102 _(lisp_gpe_add_del_iface, "up|down")                                    \
14103 _(lisp_add_del_remote_mapping, "add|del vni <vni> deid <dest-eid> "     \
14104                                "rloc <locator> p <prio> "               \
14105                                "w <weight> [rloc <loc> ... ] "          \
14106                                "action <action> [del-all]")             \
14107 _(lisp_add_del_adjacency, "add|del vni <vni> deid <dest-eid> seid "     \
14108                           "<src-eid> rloc <locator> p <prio> w <weight>"\
14109                           "[rloc <loc> ... ] action <action>")          \
14110 _(lisp_pitr_set_locator_set, "locator-set <loc-set-name> | del")        \
14111 _(lisp_add_del_map_request_itr_rlocs, "<loc-set-name> [del]")           \
14112 _(lisp_eid_table_add_del_map, "[del] vni <vni> vrf <vrf>")              \
14113 _(lisp_locator_set_dump, "[locator-set-index <ls-index> | "             \
14114                          "locator-set <loc-set-name>] [local | remote]")\
14115 _(lisp_eid_table_dump, "[eid <ipv4|ipv6>/<prefix> | <mac>] [vni] "      \
14116                        "[local] | [remote]")                            \
14117 _(lisp_eid_table_map_dump, "")                                          \
14118 _(lisp_gpe_tunnel_dump, "")                                             \
14119 _(lisp_map_resolver_dump, "")                                           \
14120 _(show_lisp_status, "")                                                 \
14121 _(lisp_get_map_request_itr_rlocs, "")                                   \
14122 _(show_lisp_pitr, "")                                                   \
14123 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
14124 _(af_packet_delete, "name <host interface name>")                       \
14125 _(policer_add_del, "name <policer name> <params> [del]")                \
14126 _(policer_dump, "[name <policer name>]")                                \
14127 _(policer_classify_set_interface,                                       \
14128   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
14129   "  [l2-table <nn>] [del]")                                            \
14130 _(policer_classify_dump, "type [ip4|ip6|l2]")                           \
14131 _(netmap_create, "name <interface name> [hw-addr <mac>] [pipe] "        \
14132     "[master|slave]")                                                   \
14133 _(netmap_delete, "name <interface name>")                               \
14134 _(mpls_gre_tunnel_dump, "tunnel_index <tunnel-id>")                     \
14135 _(mpls_eth_tunnel_dump, "tunnel_index <tunnel-id>")                     \
14136 _(mpls_fib_encap_dump, "")                                              \
14137 _(mpls_fib_decap_dump, "")                                              \
14138 _(classify_table_ids, "")                                               \
14139 _(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
14140 _(classify_table_info, "table_id <nn>")                                 \
14141 _(classify_session_dump, "table_id <nn>")                               \
14142 _(ipfix_enable, "collector_address <ip4> [collector_port <nn>] "        \
14143                 "src_address <ip4> [fib_id <nn>] [path_mtu <nn>] "      \
14144                 "[template_interval <nn>]")                             \
14145 _(ipfix_dump, "")                                                       \
14146 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
14147 _(pg_create_interface, "if_id <nn>")                                    \
14148 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
14149 _(pg_enable_disable, "[stream <id>] disable")                           \
14150 _(ip_source_and_port_range_check_add_del,                               \
14151   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
14152 _(ip_source_and_port_range_check_interface_add_del,                     \
14153   "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]"      \
14154   "[udp-in-vrf <id>] [udp-out-vrf <id>]")
14155
14156 /* List of command functions, CLI names map directly to functions */
14157 #define foreach_cli_function                                    \
14158 _(comment, "usage: comment <ignore-rest-of-line>")              \
14159 _(dump_interface_table, "usage: dump_interface_table")          \
14160 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
14161 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
14162 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
14163 _(dump_stats_table, "usage: dump_stats_table")                  \
14164 _(dump_macro_table, "usage: dump_macro_table ")                 \
14165 _(dump_node_table, "usage: dump_node_table")                    \
14166 _(echo, "usage: echo <message>")                                \
14167 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
14168 _(help, "usage: help")                                          \
14169 _(q, "usage: quit")                                             \
14170 _(quit, "usage: quit")                                          \
14171 _(search_node_table, "usage: search_node_table <name>...")      \
14172 _(set, "usage: set <variable-name> <value>")                    \
14173 _(script, "usage: script <file-name>")                          \
14174 _(unset, "usage: unset <variable-name>")
14175
14176 #define _(N,n)                                  \
14177     static void vl_api_##n##_t_handler_uni      \
14178     (vl_api_##n##_t * mp)                       \
14179     {                                           \
14180         vat_main_t * vam = &vat_main;           \
14181         if (vam->json_output) {                 \
14182             vl_api_##n##_t_handler_json(mp);    \
14183         } else {                                \
14184             vl_api_##n##_t_handler(mp);         \
14185         }                                       \
14186     }
14187 foreach_vpe_api_reply_msg;
14188 #undef _
14189
14190 void vat_api_hookup (vat_main_t *vam)
14191 {
14192 #define _(N,n)                                                  \
14193     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
14194                            vl_api_##n##_t_handler_uni,          \
14195                            vl_noop_handler,                     \
14196                            vl_api_##n##_t_endian,               \
14197                            vl_api_##n##_t_print,                \
14198                            sizeof(vl_api_##n##_t), 1);
14199     foreach_vpe_api_reply_msg;
14200 #undef _
14201
14202     vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
14203
14204     vam->sw_if_index_by_interface_name =
14205         hash_create_string (0, sizeof (uword));
14206
14207     vam->function_by_name =
14208         hash_create_string (0, sizeof(uword));
14209
14210     vam->help_by_name =
14211         hash_create_string (0, sizeof(uword));
14212
14213     /* API messages we can send */
14214 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
14215     foreach_vpe_api_msg;
14216 #undef _
14217
14218     /* Help strings */
14219 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
14220     foreach_vpe_api_msg;
14221 #undef _
14222
14223     /* CLI functions */
14224 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
14225     foreach_cli_function;
14226 #undef _
14227
14228     /* Help strings */
14229 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
14230     foreach_cli_function;
14231 #undef _
14232 }
14233
14234 #undef vl_api_version
14235 #define vl_api_version(n,v) static u32 vpe_api_version = v;
14236 #include <vpp-api/vpe.api.h>
14237 #undef vl_api_version
14238
14239 void vl_client_add_api_signatures (vl_api_memclnt_create_t *mp)
14240 {
14241     /*
14242      * Send the main API signature in slot 0. This bit of code must
14243      * match the checks in ../vpe/api/api.c: vl_msg_api_version_check().
14244      */
14245     mp->api_versions[0] = clib_host_to_net_u32 (vpe_api_version);
14246 }