LISP API/VAT 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
10962     mp->loc_num = vec_len (rmt_locs);
10963     clib_memcpy (mp->lcl_locs, lcl_locs,
10964                  (sizeof(rloc_t) * vec_len(lcl_locs)));
10965     clib_memcpy (mp->rmt_locs, rmt_locs,
10966                  (sizeof(rloc_t) * vec_len(rmt_locs)));
10967     vec_free(lcl_locs);
10968     vec_free(rmt_locs);
10969
10970     /* send it... */
10971     S;
10972
10973     /* Wait for a reply... */
10974     W;
10975
10976     /* NOTREACHED */
10977     return 0;
10978 }
10979
10980 static int
10981 api_lisp_add_del_map_resolver(vat_main_t * vam)
10982 {
10983     unformat_input_t * input = vam->input;
10984     vl_api_lisp_add_del_map_resolver_t *mp;
10985     f64 timeout = ~0;
10986     u8 is_add = 1;
10987     u8 ipv4_set = 0;
10988     u8 ipv6_set = 0;
10989     ip4_address_t ipv4;
10990     ip6_address_t ipv6;
10991
10992     /* Parse args required to build the message */
10993     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10994         if (unformat(input, "del")) {
10995             is_add = 0;
10996         } else if (unformat(input, "%U", unformat_ip4_address, &ipv4)) {
10997             ipv4_set = 1;
10998         } else if (unformat(input, "%U", unformat_ip6_address, &ipv6)) {
10999             ipv6_set = 1;
11000         } else
11001             break;
11002     }
11003
11004     if (ipv4_set && ipv6_set) {
11005         errmsg ("both eid v4 and v6 addresses set\n");
11006         return -99;
11007     }
11008
11009     if (!ipv4_set && !ipv6_set) {
11010         errmsg ("eid addresses not set\n");
11011         return -99;
11012     }
11013
11014     /* Construct the API message */
11015     M(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver);
11016
11017     mp->is_add = is_add;
11018     if (ipv6_set) {
11019         mp->is_ipv6 = 1;
11020         clib_memcpy(mp->ip_address, &ipv6, sizeof(ipv6));
11021     } else {
11022         mp->is_ipv6 = 0;
11023         clib_memcpy(mp->ip_address, &ipv4, sizeof(ipv4));
11024     }
11025
11026     /* send it... */
11027     S;
11028
11029     /* Wait for a reply... */
11030     W;
11031
11032     /* NOTREACHED */
11033     return 0;
11034 }
11035
11036 static int
11037 api_lisp_gpe_enable_disable (vat_main_t * vam)
11038 {
11039   unformat_input_t * input = vam->input;
11040   vl_api_lisp_gpe_enable_disable_t *mp;
11041   f64 timeout = ~0;
11042   u8 is_set = 0;
11043   u8 is_en = 1;
11044
11045   /* Parse args required to build the message */
11046   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11047       if (unformat(input, "enable")) {
11048           is_set = 1;
11049           is_en = 1;
11050       } else if (unformat(input, "disable")) {
11051           is_set = 1;
11052           is_en = 0;
11053       } else
11054           break;
11055   }
11056
11057   if (is_set == 0) {
11058       errmsg("Value not set\n");
11059       return -99;
11060   }
11061
11062   /* Construct the API message */
11063   M(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable);
11064
11065   mp->is_en = is_en;
11066
11067   /* send it... */
11068   S;
11069
11070   /* Wait for a reply... */
11071   W;
11072
11073   /* NOTREACHED */
11074   return 0;
11075 }
11076
11077 static int
11078 api_lisp_enable_disable (vat_main_t * vam)
11079 {
11080   unformat_input_t * input = vam->input;
11081   vl_api_lisp_enable_disable_t *mp;
11082   f64 timeout = ~0;
11083   u8 is_set = 0;
11084   u8 is_en = 0;
11085
11086   /* Parse args required to build the message */
11087   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11088     {
11089       if (unformat (input, "enable"))
11090         {
11091           is_set = 1;
11092           is_en = 1;
11093         }
11094       else if (unformat (input, "disable"))
11095         {
11096           is_set = 1;
11097         }
11098       else
11099           break;
11100     }
11101
11102   if (!is_set)
11103     {
11104       errmsg ("Value not set\n");
11105       return -99;
11106     }
11107
11108   /* Construct the API message */
11109   M(LISP_ENABLE_DISABLE, lisp_enable_disable);
11110
11111   mp->is_en = is_en;
11112
11113   /* send it... */
11114   S;
11115
11116   /* Wait for a reply... */
11117   W;
11118
11119   /* NOTREACHED */
11120   return 0;
11121 }
11122
11123 /**
11124  * Enable/disable LISP proxy ITR.
11125  *
11126  * @param vam vpp API test context
11127  * @return return code
11128  */
11129 static int
11130 api_lisp_pitr_set_locator_set (vat_main_t * vam)
11131 {
11132   f64 timeout = ~0;
11133   u8 ls_name_set = 0;
11134   unformat_input_t * input = vam->input;
11135   vl_api_lisp_pitr_set_locator_set_t * mp;
11136   u8 is_add = 1;
11137   u8 * ls_name = 0;
11138
11139   /* Parse args required to build the message */
11140   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11141     {
11142       if (unformat (input, "del"))
11143         is_add = 0;
11144       else if (unformat (input, "locator-set %s", &ls_name))
11145         ls_name_set = 1;
11146       else
11147         {
11148           errmsg ("parse error '%U'", format_unformat_error, input);
11149           return -99;
11150         }
11151     }
11152
11153   if (!ls_name_set)
11154     {
11155       errmsg ("locator-set name not set!");
11156       return -99;
11157     }
11158
11159   M(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set);
11160
11161   mp->is_add = is_add;
11162   clib_memcpy (mp->ls_name, ls_name, vec_len (ls_name));
11163   vec_free (ls_name);
11164
11165   /* send */
11166   S;
11167
11168   /* wait for reply */
11169   W;
11170
11171   /* notreached*/
11172   return 0;
11173 }
11174
11175 static int
11176 api_show_lisp_pitr (vat_main_t * vam)
11177 {
11178     vl_api_show_lisp_pitr_t *mp;
11179     f64 timeout = ~0;
11180
11181     if (!vam->json_output) {
11182         fformat(vam->ofp, "%=20s\n",
11183                 "lisp status:");
11184     }
11185
11186     M(SHOW_LISP_PITR, show_lisp_pitr);
11187     /* send it... */
11188     S;
11189
11190     /* Wait for a reply... */
11191     W;
11192
11193     /* NOTREACHED */
11194     return 0;
11195 }
11196
11197 /**
11198  * Add/delete mapping between vni and vrf
11199  */
11200 static int
11201 api_lisp_eid_table_add_del_map (vat_main_t * vam)
11202 {
11203   f64 timeout = ~0;
11204   unformat_input_t * input = vam->input;
11205   vl_api_lisp_eid_table_add_del_map_t *mp;
11206   u8 is_add = 1, vni_set = 0, vrf_set = 0, bd_index_set = 0;
11207   u32 vni, vrf, bd_index;
11208
11209   /* Parse args required to build the message */
11210   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
11211     {
11212       if (unformat (input, "del"))
11213         is_add = 0;
11214       else if (unformat(input, "vrf %d", &vrf))
11215         vrf_set = 1;
11216       else if (unformat(input, "bd_index %d", &bd_index))
11217         bd_index_set = 1;
11218       else if (unformat(input, "vni %d", &vni))
11219         vni_set = 1;
11220       else
11221         break;
11222     }
11223
11224   if (!vni_set || (!vrf_set && !bd_index_set))
11225     {
11226       errmsg ("missing arguments!");
11227       return -99;
11228     }
11229
11230   M(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map);
11231
11232   mp->is_add = is_add;
11233   mp->vni = htonl (vni);
11234   mp->dp_table = htonl (vrf);
11235   mp->is_l2 = bd_index_set;
11236
11237   /* send */
11238   S;
11239
11240   /* wait for reply */
11241   W;
11242
11243   /* notreached*/
11244   return 0;
11245 }
11246
11247 /**
11248  * Add/del remote mapping to/from LISP control plane
11249  *
11250  * @param vam vpp API test context
11251  * @return return code
11252  */
11253 static int
11254 api_lisp_add_del_remote_mapping (vat_main_t * vam)
11255 {
11256     unformat_input_t * input = vam->input;
11257     vl_api_lisp_add_del_remote_mapping_t *mp;
11258     f64 timeout = ~0;
11259     u32 vni = 0;
11260     //TODO: seid need remove
11261     lisp_eid_vat_t _eid, * eid = &_eid;
11262     lisp_eid_vat_t _seid, * seid = &_seid;
11263     u8 is_add = 1, del_all = 0, eid_set = 0;
11264     u32 action = ~0, p, w;
11265     ip4_address_t rloc4;
11266     ip6_address_t rloc6;
11267     rloc_t * rlocs = 0, rloc, * curr_rloc = 0;
11268
11269     /* Parse args required to build the message */
11270     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11271         if (unformat(input, "del-all")) {
11272             del_all = 1;
11273         } else if (unformat(input, "del")) {
11274             is_add = 0;
11275         } else if (unformat(input, "add")) {
11276             is_add = 1;
11277         } else if (unformat(input, "deid %U", unformat_lisp_eid_vat, eid)) {
11278             eid_set = 1;
11279         } else if (unformat(input, "seid %U", unformat_lisp_eid_vat, &seid)) {
11280             //TODO: Need remove, but first must be remove from CSIT test
11281         } else if (unformat(input, "vni %d", &vni)) {
11282             ;
11283         } else if (unformat(input, "p %d w %d", &p, &w)) {
11284             if (!curr_rloc) {
11285               errmsg ("No RLOC configured for setting priority/weight!");
11286               return -99;
11287             }
11288             curr_rloc->priority = p;
11289             curr_rloc->weight = w;
11290         } else if (unformat(input, "rloc %U", unformat_ip4_address, &rloc4)) {
11291             rloc.is_ip4 = 1;
11292             clib_memcpy (&rloc.addr, &rloc4, sizeof (rloc4));
11293             vec_add1 (rlocs, rloc);
11294             curr_rloc = &rlocs[vec_len (rlocs) - 1];
11295         } else if (unformat(input, "rloc %U", unformat_ip6_address, &rloc6)) {
11296             rloc.is_ip4 = 0;
11297             clib_memcpy (&rloc.addr, &rloc6, sizeof (rloc6));
11298             vec_add1 (rlocs, rloc);
11299             curr_rloc = &rlocs[vec_len (rlocs) - 1];
11300         } else if (unformat(input, "action %d", &action)) {
11301             ;
11302         } else {
11303             clib_warning ("parse error '%U'", format_unformat_error, input);
11304             return -99;
11305         }
11306     }
11307
11308     if (0 == eid_set) {
11309         errmsg ("missing params!");
11310         return -99;
11311     }
11312
11313     if (is_add && (~0 == action)
11314         && 0 == vec_len (rlocs)) {
11315           errmsg ("no action set for negative map-reply!");
11316           return -99;
11317     }
11318
11319     M(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping);
11320     mp->is_add = is_add;
11321     mp->vni = htonl (vni);
11322     mp->action = (u8) action;
11323     mp->eid_len = eid->len;
11324     mp->del_all = del_all;
11325     mp->eid_type = eid->type;
11326     lisp_eid_put_vat(mp->eid, eid->addr, eid->type);
11327
11328     mp->rloc_num = vec_len (rlocs);
11329     clib_memcpy (mp->rlocs, rlocs, (sizeof (rloc_t) * vec_len (rlocs)));
11330     vec_free (rlocs);
11331
11332     /* send it... */
11333     S;
11334
11335     /* Wait for a reply... */
11336     W;
11337
11338     /* NOTREACHED */
11339     return 0;
11340 }
11341
11342 /**
11343  * Add/del LISP adjacency. Saves mapping in LISP control plane and updates
11344  * forwarding entries in data-plane accordingly.
11345  *
11346  * @param vam vpp API test context
11347  * @return return code
11348  */
11349 static int
11350 api_lisp_add_del_adjacency (vat_main_t * vam)
11351 {
11352     unformat_input_t * input = vam->input;
11353     vl_api_lisp_add_del_adjacency_t *mp;
11354     f64 timeout = ~0;
11355     u32 vni = 0;
11356     ip4_address_t seid4, deid4;
11357     ip6_address_t seid6, deid6;
11358     u8 deid_mac[6] = {0};
11359     u8 seid_mac[6] = {0};
11360     u8 deid_type, seid_type;
11361     u32 seid_len = 0, deid_len = 0, len;
11362     u8 is_add = 1;
11363
11364     seid_type = deid_type =  (u8)~0;
11365
11366     /* Parse args required to build the message */
11367     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11368         if (unformat(input, "del")) {
11369             is_add = 0;
11370         } else if (unformat(input, "add")) {
11371             is_add = 1;
11372         } else if (unformat(input, "deid %U/%d", unformat_ip4_address,
11373                             &deid4, &len)) {
11374             deid_type = 0; /* ipv4 */
11375             deid_len = len;
11376         } else if (unformat(input, "deid %U/%d", unformat_ip6_address,
11377                             &deid6, &len)) {
11378             deid_type = 1; /* ipv6 */
11379             deid_len = len;
11380         } else if (unformat(input, "deid %U", unformat_ethernet_address,
11381                             deid_mac)) {
11382             deid_type = 2; /* mac */
11383         } else if (unformat(input, "seid %U/%d", unformat_ip4_address,
11384                             &seid4, &len)) {
11385             seid_type = 0; /* ipv4 */
11386             seid_len = len;
11387         } else if (unformat(input, "seid %U/%d", unformat_ip6_address,
11388                             &seid6, &len)) {
11389             seid_type = 1; /* ipv6 */
11390             seid_len = len;
11391         } else if (unformat(input, "seid %U", unformat_ethernet_address,
11392                             seid_mac)) {
11393             seid_type = 2; /* mac */
11394         } else if (unformat(input, "vni %d", &vni)) {
11395             ;
11396         } else {
11397             errmsg ("parse error '%U'", format_unformat_error, input);
11398             return -99;
11399         }
11400     }
11401
11402     if ((u8)~0 == deid_type) {
11403         errmsg ("missing params!");
11404         return -99;
11405     }
11406
11407     if (seid_type != deid_type) {
11408         errmsg ("source and destination EIDs are of different types!");
11409         return -99;
11410     }
11411
11412     M(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency);
11413     mp->is_add = is_add;
11414     mp->vni = htonl (vni);
11415     mp->seid_len = seid_len;
11416     mp->deid_len = deid_len;
11417     mp->eid_type = deid_type;
11418
11419     switch (mp->eid_type) {
11420     case 0:
11421         clib_memcpy (mp->seid, &seid4, sizeof (seid4));
11422         clib_memcpy (mp->deid, &deid4, sizeof (deid4));
11423         break;
11424     case 1:
11425         clib_memcpy (mp->seid, &seid6, sizeof (seid6));
11426         clib_memcpy (mp->deid, &deid6, sizeof (deid6));
11427         break;
11428     case 2:
11429         clib_memcpy (mp->seid, seid_mac, 6);
11430         clib_memcpy (mp->deid, deid_mac, 6);
11431         break;
11432     default:
11433         errmsg ("unknown EID type %d!", mp->eid_type);
11434         return 0;
11435     }
11436
11437     /* send it... */
11438     S;
11439
11440     /* Wait for a reply... */
11441     W;
11442
11443     /* NOTREACHED */
11444     return 0;
11445 }
11446
11447 static int
11448 api_lisp_gpe_add_del_iface(vat_main_t * vam)
11449 {
11450     unformat_input_t * input = vam->input;
11451     vl_api_lisp_gpe_add_del_iface_t *mp;
11452     f64 timeout = ~0;
11453     u8 is_set = 0, is_add = 1, is_l2 = 0;
11454     u32 dp_table, vni;
11455
11456     /* Parse args required to build the message */
11457     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11458         if (unformat(input, "up")) {
11459             is_set = 1;
11460             is_add = 1;
11461         } else if (unformat(input, "down")) {
11462             is_set = 1;
11463             is_add = 0;
11464         } else if (unformat(input, "table_id %d", &dp_table)) {
11465             ;
11466         } else if (unformat(input, "bd_id %d", &dp_table)) {
11467             is_l2 = 1;
11468         } else if (unformat(input, "vni %d", &vni)) {
11469             ;
11470         } else
11471             break;
11472     }
11473
11474     if (is_set == 0) {
11475         errmsg("Value not set\n");
11476         return -99;
11477     }
11478
11479     /* Construct the API message */
11480     M(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface);
11481
11482     mp->is_add = is_add;
11483     mp->dp_table = dp_table;
11484     mp->is_l2 = is_l2;
11485     mp->vni = vni;
11486
11487     /* send it... */
11488     S;
11489
11490     /* Wait for a reply... */
11491     W;
11492
11493     /* NOTREACHED */
11494     return 0;
11495 }
11496
11497 /**
11498  * Add/del map request itr rlocs from LISP control plane and updates
11499  *
11500  * @param vam vpp API test context
11501  * @return return code
11502  */
11503 static int
11504 api_lisp_add_del_map_request_itr_rlocs(vat_main_t * vam)
11505 {
11506     unformat_input_t * input = vam->input;
11507     vl_api_lisp_add_del_map_request_itr_rlocs_t *mp;
11508     f64 timeout = ~0;
11509     u8 *locator_set_name = 0;
11510     u8  locator_set_name_set = 0;
11511     u8 is_add = 1;
11512
11513     /* Parse args required to build the message */
11514     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11515         if (unformat(input, "del")) {
11516             is_add = 0;
11517         } else if (unformat(input, "%_%v%_", &locator_set_name)) {
11518             locator_set_name_set = 1;
11519         } else {
11520             clib_warning ("parse error '%U'", format_unformat_error, input);
11521             return -99;
11522         }
11523     }
11524
11525     if (is_add && !locator_set_name_set) {
11526         errmsg ("itr-rloc is not set!");
11527         return -99;
11528     }
11529
11530     if (is_add && vec_len(locator_set_name) > 64) {
11531         errmsg ("itr-rloc locator-set name too long\n");
11532         vec_free(locator_set_name);
11533         return -99;
11534     }
11535
11536     M(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS, lisp_add_del_map_request_itr_rlocs);
11537     mp->is_add = is_add;
11538     if (is_add) {
11539       clib_memcpy (mp->locator_set_name , locator_set_name,
11540                    vec_len(locator_set_name));
11541     } else {
11542       memset(mp->locator_set_name, 0, sizeof(mp->locator_set_name));
11543     }
11544     vec_free (locator_set_name);
11545
11546     /* send it... */
11547     S;
11548
11549     /* Wait for a reply... */
11550     W;
11551
11552     /* NOTREACHED */
11553     return 0;
11554 }
11555
11556 static int
11557 lisp_locator_dump_send_msg(vat_main_t * vam, u32 locator_set_index, u8 filter)
11558 {
11559     vl_api_lisp_locator_dump_t *mp;
11560     f64 timeout = ~0;
11561
11562     M(LISP_LOCATOR_DUMP, lisp_locator_dump);
11563
11564     mp->locator_set_index = htonl(locator_set_index);
11565     mp->filter = filter;
11566
11567     /* send it... */
11568     S;
11569
11570     /* Use a control ping for synchronization */
11571     {
11572       vl_api_noprint_control_ping_t * mp;
11573       M(NOPRINT_CONTROL_PING, noprint_control_ping);
11574       S;
11575     }
11576     /* Wait for a reply... */
11577     W;
11578 }
11579
11580 static inline void
11581 clean_locator_set_message(vat_main_t * vam)
11582 {
11583     locator_set_msg_t * ls = 0;
11584
11585     vec_foreach (ls, vam->locator_set_msg) {
11586         vec_free(ls->locator_set_name);
11587     }
11588
11589     vec_free(vam->locator_set_msg);
11590 }
11591
11592 static int
11593 print_locator_in_locator_set(vat_main_t * vam, u8 filter)
11594 {
11595     locator_set_msg_t * ls;
11596     locator_msg_t * loc;
11597     u8 * tmp_str = 0;
11598     int i = 0, ret = 0;
11599
11600     vec_foreach(ls, vam->locator_set_msg) {
11601         ret = lisp_locator_dump_send_msg(vam, ls->locator_set_index, filter);
11602         if (ret) {
11603             vec_free(vam->locator_msg);
11604             clean_locator_set_message(vam);
11605             return ret;
11606         }
11607
11608         tmp_str = format(0, "%=20s%=16d%s", ls->locator_set_name,
11609                          ls->locator_set_index,
11610                          vec_len(vam->locator_msg) ? "" : "\n");
11611         i = 0;
11612         vec_foreach(loc, vam->locator_msg) {
11613             if (i) {
11614                 tmp_str = format(tmp_str, "%=37s", " ");
11615             }
11616             if (loc->local) {
11617                 tmp_str = format(tmp_str, "%=16d%=16d%=16d\n",
11618                                  loc->sw_if_index,
11619                                  loc->priority,
11620                                  loc->weight);
11621             } else {
11622                 tmp_str = format(tmp_str, "%=16U%=16d%=16d\n",
11623                                  loc->is_ipv6 ? format_ip6_address :
11624                                  format_ip4_address,
11625                                  loc->ip_address,
11626                                  loc->priority,
11627                                  loc->weight);
11628             }
11629             i++;
11630         }
11631
11632         fformat(vam->ofp, "%s", tmp_str);
11633         vec_free(tmp_str);
11634         vec_free(vam->locator_msg);
11635     }
11636
11637     clean_locator_set_message(vam);
11638
11639     return ret;
11640 }
11641
11642 static int
11643 json_locator_in_locator_set(vat_main_t * vam, u8 filter)
11644 {
11645     locator_set_msg_t * ls;
11646     locator_msg_t * loc;
11647     vat_json_node_t * node = NULL;
11648     vat_json_node_t * locator_array;
11649     vat_json_node_t * locator;
11650     struct in6_addr ip6;
11651     struct in_addr ip4;
11652     int ret = 0;
11653
11654     if (!vec_len(vam->locator_set_msg)) {
11655         /* just print [] */
11656         vat_json_init_array(&vam->json_tree);
11657         vat_json_print(vam->ofp, &vam->json_tree);
11658         vam->json_tree.type = VAT_JSON_NONE;
11659         return ret;
11660     }
11661
11662     if (VAT_JSON_ARRAY != vam->json_tree.type) {
11663       ASSERT(VAT_JSON_NONE == vam->json_tree.type);
11664       vat_json_init_array(&vam->json_tree);
11665     }
11666
11667     vec_foreach(ls, vam->locator_set_msg) {
11668         ret = lisp_locator_dump_send_msg(vam, ls->locator_set_index, filter);
11669         if (ret) {
11670             vec_free(ls->locator_set_name);
11671             vec_free(vam->locator_msg);
11672             vec_free(vam->locator_set_msg);
11673             vat_json_free(&vam->json_tree);
11674             vam->json_tree.type = VAT_JSON_NONE;
11675             return ret;
11676         }
11677
11678         node = vat_json_array_add(&vam->json_tree);
11679         vat_json_init_object(node);
11680
11681         vat_json_object_add_uint(node, "locator-set-index",
11682                                  ls->locator_set_index);
11683         vat_json_object_add_string_copy(node, "locator-set",
11684                                         ls->locator_set_name);
11685         locator_array = vat_json_object_add_list(node, "locator");
11686         vec_foreach(loc, vam->locator_msg) {
11687             locator = vat_json_array_add(locator_array);
11688             vat_json_init_object(locator);
11689             if (loc->local) {
11690                 vat_json_object_add_uint(locator, "locator-index",
11691                                          loc->sw_if_index);
11692             } else {
11693                 if (loc->is_ipv6) {
11694                     clib_memcpy(&ip6, loc->ip_address, sizeof(ip6));
11695                     vat_json_object_add_ip6(locator, "locator", ip6);
11696                 } else {
11697                     clib_memcpy(&ip4, loc->ip_address, sizeof(ip4));
11698                     vat_json_object_add_ip4(locator, "locator", ip4);
11699                 }
11700             }
11701             vat_json_object_add_uint(locator, "priority", loc->priority);
11702             vat_json_object_add_uint(locator, "weight", loc->weight);
11703         }
11704
11705         vec_free(ls->locator_set_name);
11706         vec_free(vam->locator_msg);
11707     }
11708
11709     vat_json_print(vam->ofp, &vam->json_tree);
11710     vat_json_free(&vam->json_tree);
11711     vam->json_tree.type = VAT_JSON_NONE;
11712
11713     vec_free(vam->locator_set_msg);
11714
11715     return ret;
11716 }
11717
11718 static int
11719 get_locator_set_index_from_msg(vat_main_t * vam, u8 * locator_set,
11720                                u32 * locator_set_index)
11721 {
11722     locator_set_msg_t * ls;
11723     int ret = 0;
11724
11725     * locator_set_index = ~0;
11726
11727     if (!vec_len(vam->locator_set_msg)) {
11728       return ret;
11729     }
11730
11731     vec_foreach(ls, vam->locator_set_msg) {
11732         if (!strcmp((char *) locator_set, (char *) ls->locator_set_name)) {
11733             * locator_set_index = ls->locator_set_index;
11734             vec_free(vam->locator_set_msg);
11735             return ret;
11736         }
11737     }
11738
11739     vec_free(vam->locator_set_msg);
11740
11741     return ret;
11742 }
11743
11744 static int
11745 get_locator_set_index(vat_main_t * vam, u8 * locator_set,
11746                       u32 * locator_set_index)
11747 {
11748     vl_api_lisp_locator_set_dump_t *mp;
11749     f64 timeout = ~0;
11750
11751     M(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump);
11752     /* send it... */
11753     S;
11754
11755    /* Use a control ping for synchronization */
11756    {
11757      vl_api_noprint_control_ping_t * mp;
11758      M(NOPRINT_CONTROL_PING, noprint_control_ping);
11759      S;
11760    }
11761
11762    vam->noprint_msg = 1;
11763     /* Wait for a reply... */
11764     W_L({
11765       get_locator_set_index_from_msg(vam, locator_set, locator_set_index);
11766       vam->noprint_msg = 0;
11767     })
11768
11769     /* NOTREACHED */
11770     return 0;
11771 }
11772
11773 static inline int
11774 lisp_locator_dump(vat_main_t * vam, u32 locator_set_index, u8 * locator_set,
11775                   u8 filter)
11776 {
11777     int ret = 0;
11778
11779     ASSERT(vam);
11780
11781     if (!vam->json_output) {
11782       fformat(vam->ofp, "%=20s%=16s%=16s\n",
11783               "locator", "priority", "weight");
11784     }
11785
11786     if (locator_set) {
11787       ret = get_locator_set_index(vam, locator_set, &locator_set_index);
11788     }
11789
11790     if (!ret && ~0 == locator_set_index) {
11791       return -99;
11792     }
11793
11794     ret = lisp_locator_dump_send_msg(vam, locator_set_index, filter);
11795
11796     return ret;
11797 }
11798
11799 static int
11800 lisp_locator_set_dump(vat_main_t * vam, u8 filter)
11801 {
11802     vl_api_lisp_locator_set_dump_t *mp;
11803     f64 timeout = ~0;
11804
11805     if (!vam->json_output) {
11806         fformat(vam->ofp, "%=20s%=16s%=16s%=16s%=16s\n",
11807                 "locator-set", "locator-set-index", "locator", "priority",
11808                 "weight");
11809     }
11810
11811     vam->noprint_msg = 1;
11812
11813     M(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump);
11814
11815     mp->filter = filter;
11816
11817     /* send it... */
11818     S;
11819
11820    /* Use a control ping for synchronization */
11821    {
11822      vl_api_noprint_control_ping_t * mp;
11823      M(NOPRINT_CONTROL_PING, noprint_control_ping);
11824      S;
11825    }
11826
11827     /* Wait for a reply... */
11828     W_L({
11829       if (vam->noprint_msg) {
11830           if (!vam->json_output) {
11831               print_locator_in_locator_set(vam, filter);
11832           } else {
11833               json_locator_in_locator_set(vam, filter);
11834           }
11835       }
11836
11837       vam->noprint_msg = 0;
11838     });
11839
11840     /* NOTREACHED */
11841     return 0;
11842 }
11843
11844 static int
11845 api_lisp_locator_set_dump(vat_main_t *vam)
11846 {
11847     unformat_input_t * input = vam->input;
11848     vam->noprint_msg = 0;
11849     u32 locator_set_index = ~0;
11850     u8 locator_set_index_set = 0;
11851     u8 * locator_set = 0;
11852     u8 locator_set_set = 0;
11853     u8 filter = 0;
11854     int ret = 0;
11855
11856     /* Parse args required to build the message */
11857     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
11858         if (unformat(input, "locator-set-index %u", &locator_set_index)) {
11859             locator_set_index_set = 1;
11860         } else if (unformat(input, "locator-set %s", &locator_set)) {
11861             locator_set_set = 1;
11862         } else if (unformat(input, "local")) {
11863             filter = 1;
11864         } else if (unformat(input, "remote")) {
11865             filter = 2;
11866         } else {
11867             break;
11868         }
11869     }
11870
11871     if (locator_set_index_set && locator_set_set) {
11872         errmsg ("use only input parameter!\n");
11873         return -99;
11874     }
11875
11876     if (locator_set_index_set || locator_set_set) {
11877         ret = lisp_locator_dump(vam, locator_set_index, locator_set, filter);
11878     } else {
11879         ret = lisp_locator_set_dump(vam, filter);
11880     }
11881
11882     vec_free(locator_set);
11883
11884     return ret;
11885 }
11886
11887 static int
11888 api_lisp_eid_table_map_dump(vat_main_t *vam)
11889 {
11890     vl_api_lisp_eid_table_map_dump_t *mp;
11891     f64 timeout = ~0;
11892
11893     if (!vam->json_output) {
11894         fformat (vam->ofp, "%=10s%=10s\n", "VNI", "VRF");
11895     }
11896
11897     M(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump);
11898
11899     /* send it... */
11900     S;
11901
11902     /* Use a control ping for synchronization */
11903     {
11904         vl_api_control_ping_t * mp;
11905         M(CONTROL_PING, control_ping);
11906         S;
11907     }
11908     /* Wait for a reply... */
11909     W;
11910
11911     /* NOTREACHED */
11912     return 0;
11913 }
11914
11915 static int
11916 get_locator_set(vat_main_t * vam)
11917 {
11918     vl_api_lisp_locator_set_dump_t *mp;
11919     f64 timeout = ~0;
11920
11921     M(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump);
11922     /* send it... */
11923     S;
11924
11925    /* Use a control ping for synchronization */
11926    {
11927      vl_api_noprint_control_ping_t * mp;
11928      M(NOPRINT_CONTROL_PING, noprint_control_ping);
11929      S;
11930    }
11931
11932     /* Wait for a reply... */
11933     W;
11934
11935     /* NOTREACHED */
11936     return 0;
11937 }
11938
11939 static inline u8 *
11940 format_eid_for_eid_table(vat_main_t *vam, u8 * str, eid_table_t * eid_table,
11941                          int *ret)
11942 {
11943     u8 * (*format_eid)(u8 *, va_list *) = 0;
11944
11945     ASSERT(vam != NULL);
11946     ASSERT(eid_table != NULL);
11947
11948     if (ret) {
11949         *ret = 0;
11950     }
11951
11952     switch (eid_table->eid_type)
11953     {
11954       case 0:
11955       case 1:
11956         format_eid = (eid_table->eid_type ? format_ip6_address :
11957           format_ip4_address);
11958         str = format(0, "[%d] %U/%d",
11959                           clib_net_to_host_u32 (eid_table->vni),
11960                           format_eid, eid_table->eid, eid_table->eid_prefix_len);
11961         break;
11962       case 2:
11963         str = format(0, "[%d] %U",
11964                           clib_net_to_host_u32 (eid_table->vni),
11965                           format_ethernet_address, eid_table->eid);
11966         break;
11967       default:
11968         errmsg ("unknown EID type %d!", eid_table->eid_type);
11969         if (ret) {
11970             *ret = -99;
11971         }
11972         return 0;
11973     }
11974
11975     return str;
11976 }
11977
11978 static inline u8 *
11979 format_locator_set_for_eid_table(vat_main_t * vam, u8 * str,
11980                                  eid_table_t * eid_table)
11981 {
11982     locator_set_msg_t * ls = 0;
11983
11984     ASSERT(vam != NULL);
11985     ASSERT(eid_table != NULL);
11986
11987     if (eid_table->is_local) {
11988         vec_foreach (ls, vam->locator_set_msg) {
11989             if (ls->locator_set_index == eid_table->locator_set_index) {
11990                 str = format(0, "local(%s)", ls->locator_set_name);
11991                 return str;
11992             }
11993         }
11994
11995         str = format(0, "local(N/A)");
11996     } else {
11997         str = format(0, "remote");
11998     }
11999
12000     return str;
12001 }
12002
12003 static inline u8 *
12004 format_locator_for_eid_table(vat_main_t * vam, u8 * str,
12005                              eid_table_t * eid_table)
12006 {
12007     locator_msg_t * loc = 0;
12008     int first_line = 1;
12009
12010     ASSERT(vam != NULL);
12011     ASSERT(eid_table != NULL);
12012
12013     vec_foreach(loc, vam->locator_msg) {
12014         if (!first_line) {
12015             if (loc->local) {
12016                 str = format(str, "%-55s%-d\n", " ", loc->sw_if_index);
12017             } else {
12018                 str = format(str, "%=55s%-U\n", " ",
12019                              loc->is_ipv6 ? format_ip6_address :
12020                              format_ip4_address,
12021                                loc->ip_address);
12022             }
12023
12024             continue;
12025         }
12026
12027         if (loc->local) {
12028             str = format(str, "%-30d%-20u%-u\n", loc->sw_if_index,
12029                          eid_table->ttl, eid_table->authoritative);
12030         } else {
12031             str = format(str, "%-30U%-20u%-u\n",
12032                          loc->is_ipv6 ? format_ip6_address :
12033                          format_ip4_address,
12034                          loc->ip_address, eid_table->ttl,
12035                          eid_table->authoritative);
12036         }
12037         first_line = 0;
12038     }
12039
12040     return str;
12041 }
12042
12043 static int
12044 print_lisp_eid_table_dump(vat_main_t * vam)
12045 {
12046     eid_table_t * eid_table = 0;
12047     u8 * tmp_str = 0, * tmp_str2 = 0;
12048     int ret = 0;
12049
12050     ASSERT(vam != NULL);
12051
12052     ret = get_locator_set(vam);
12053     if (ret) {
12054         vec_free(vam->eid_tables);
12055         return ret;
12056     }
12057
12058     fformat(vam->ofp, "%-35s%-20s%-30s%-20s%-s\n", "EID", "type", "locators",
12059                                                    "ttl", "authoritative");
12060
12061     vec_foreach(eid_table, vam->eid_tables) {
12062         ret = lisp_locator_dump_send_msg(vam, eid_table->locator_set_index, 0);
12063         if (ret) {
12064           vec_free(vam->locator_msg);
12065           clean_locator_set_message(vam);
12066           vec_free(vam->eid_tables);
12067           return ret;
12068         }
12069
12070         tmp_str2 = format_eid_for_eid_table(vam, tmp_str2, eid_table, &ret);
12071         if (ret) {
12072           vec_free(vam->locator_msg);
12073           clean_locator_set_message(vam);
12074           vec_free(vam->eid_tables);
12075           return ret;
12076         }
12077
12078         tmp_str = format(0, "%-35s", tmp_str2);
12079         vec_free(tmp_str2);
12080
12081         tmp_str2 = format_locator_set_for_eid_table(vam, tmp_str2, eid_table);
12082         tmp_str = format(tmp_str, "%-20s", tmp_str2);
12083         vec_free(tmp_str2);
12084
12085         tmp_str2 = format_locator_for_eid_table(vam, tmp_str2, eid_table);
12086         tmp_str = format(tmp_str, "%-s", tmp_str2);
12087         vec_free(tmp_str2);
12088
12089         fformat(vam->ofp, "%s", tmp_str);
12090         vec_free(tmp_str);
12091         vec_free(vam->locator_msg);
12092     }
12093
12094     clean_locator_set_message(vam);
12095     vec_free(vam->eid_tables);
12096
12097     return ret;
12098 }
12099
12100 static inline void
12101 json_locator_set_for_eid_table(vat_main_t * vam, vat_json_node_t * node,
12102                                eid_table_t * eid_table)
12103 {
12104     locator_set_msg_t * ls = 0;
12105     u8 * s = 0;
12106
12107     ASSERT(vam != NULL);
12108     ASSERT(node != NULL);
12109     ASSERT(eid_table != NULL);
12110
12111     if (eid_table->is_local) {
12112         vec_foreach (ls, vam->locator_set_msg) {
12113             if (ls->locator_set_index == eid_table->locator_set_index) {
12114                 vat_json_object_add_string_copy(node, "locator-set",
12115                                                 ls->locator_set_name);
12116                 return;
12117             }
12118         }
12119
12120         s = format(0, "N/A");
12121         vec_add1(s, 0);
12122         vat_json_object_add_string_copy(node, "locator-set", s);
12123         vec_free(s);
12124     } else {
12125         s = format(0, "remote");
12126         vec_add1(s, 0);
12127         vat_json_object_add_string_copy(node, "locator-set", s);
12128         vec_free(s);
12129     }
12130 }
12131
12132 static inline int
12133 json_eid_for_eid_table(vat_main_t * vam, vat_json_node_t * node,
12134                        eid_table_t * eid_table)
12135 {
12136     u8 * s = 0;
12137     struct in6_addr ip6;
12138     struct in_addr ip4;
12139
12140     ASSERT(vam != NULL);
12141     ASSERT(node != NULL);
12142     ASSERT(eid_table != NULL);
12143
12144     switch (eid_table->eid_type)
12145     {
12146       case 0:
12147         clib_memcpy(&ip4, eid_table->eid, sizeof(ip4));
12148         vat_json_object_add_ip4(node, "eid", ip4);
12149         vat_json_object_add_uint(node, "eid-prefix-len",
12150                                  eid_table->eid_prefix_len);
12151         break;
12152       case 1:
12153         clib_memcpy(&ip6, eid_table->eid, sizeof(ip6));
12154         vat_json_object_add_ip6(node, "eid", ip6);
12155         vat_json_object_add_uint(node, "eid-prefix-len",
12156                                  eid_table->eid_prefix_len);
12157         break;
12158       case 2:
12159         s = format (0, "%U", format_ethernet_address, eid_table->eid);
12160         vec_add1(s, 0);
12161         vat_json_object_add_string_copy(node, "eid", s);
12162         vec_free(s);
12163         break;
12164       default:
12165         errmsg ("unknown EID type %d!", eid_table->eid_type);
12166         return -99;
12167     }
12168
12169     return 0;
12170 }
12171
12172 static inline void
12173 json_locator_for_eid_table(vat_main_t * vam, vat_json_node_t * node,
12174                            eid_table_t * eid_table)
12175 {
12176     locator_msg_t * loc = 0;
12177     vat_json_node_t * locator_array = 0;
12178     vat_json_node_t * locator = 0;
12179     struct in6_addr ip6;
12180     struct in_addr ip4;
12181
12182     ASSERT(vam != NULL);
12183     ASSERT(node != NULL);
12184     ASSERT(eid_table != NULL);
12185
12186     locator_array = vat_json_object_add_list(node, "locator");
12187     vec_foreach(loc, vam->locator_msg) {
12188         locator = vat_json_array_add(locator_array);
12189         vat_json_init_object(locator);
12190         if (loc->local) {
12191             vat_json_object_add_uint(locator, "locator-index",
12192                                      loc->sw_if_index);
12193         } else {
12194             if (loc->is_ipv6) {
12195                 clib_memcpy(&ip6, loc->ip_address, sizeof(ip6));
12196                 vat_json_object_add_ip6(locator, "locator", ip6);
12197             } else {
12198                 clib_memcpy(&ip4, loc->ip_address, sizeof(ip4));
12199                 vat_json_object_add_ip4(locator, "locator", ip4);
12200             }
12201         }
12202     }
12203 }
12204
12205 static int
12206 json_lisp_eid_table_dump(vat_main_t * vam)
12207 {
12208     eid_table_t * eid_table;
12209     vat_json_node_t * node = 0;
12210     int ret = 0;
12211
12212     ASSERT(vam != NULL);
12213
12214     ret = get_locator_set(vam);
12215     if (ret) {
12216         vec_free(vam->eid_tables);
12217         return ret;
12218     }
12219
12220     if (!vec_len(vam->eid_tables)) {
12221         /* just print [] */
12222         vat_json_init_array(&vam->json_tree);
12223         vat_json_print(vam->ofp, &vam->json_tree);
12224         vam->json_tree.type = VAT_JSON_NONE;
12225         return ret;
12226     }
12227
12228     if (VAT_JSON_ARRAY != vam->json_tree.type) {
12229       ASSERT(VAT_JSON_NONE == vam->json_tree.type);
12230       vat_json_init_array(&vam->json_tree);
12231     }
12232
12233     vec_foreach(eid_table, vam->eid_tables) {
12234         ret = lisp_locator_dump_send_msg(vam, eid_table->locator_set_index, 0);
12235         if (ret) {
12236             vec_free(vam->locator_msg);
12237             vec_free(vam->eid_tables);
12238             clean_locator_set_message(vam);
12239             vat_json_free(&vam->json_tree);
12240             vam->json_tree.type = VAT_JSON_NONE;
12241             return ret;
12242         }
12243
12244         node = vat_json_array_add(&vam->json_tree);
12245         vat_json_init_object(node);
12246
12247         vat_json_object_add_uint(node, "vni", eid_table->vni);
12248
12249         json_locator_set_for_eid_table(vam, node, eid_table);
12250         ret = json_eid_for_eid_table(vam, node, eid_table);
12251         if (ret) {
12252             vec_free(vam->locator_msg);
12253             vec_free(vam->eid_tables);
12254             clean_locator_set_message(vam);
12255             vat_json_free(&vam->json_tree);
12256             vam->json_tree.type = VAT_JSON_NONE;
12257             return ret;
12258         }
12259
12260         json_locator_for_eid_table(vam, node, eid_table);
12261
12262         vat_json_object_add_uint(node, "ttl", eid_table->ttl);
12263         vat_json_object_add_uint(node, "authoritative",
12264                                 eid_table->authoritative);
12265
12266         vec_free(vam->locator_msg);
12267     }
12268
12269     vat_json_print(vam->ofp, &vam->json_tree);
12270     vat_json_free(&vam->json_tree);
12271     vam->json_tree.type = VAT_JSON_NONE;
12272
12273     clean_locator_set_message(vam);
12274     vec_free(vam->eid_tables);
12275
12276     return ret;
12277 }
12278
12279 static int
12280 api_lisp_eid_table_dump(vat_main_t *vam)
12281 {
12282     unformat_input_t * i = vam->input;
12283     vl_api_lisp_eid_table_dump_t *mp;
12284     f64 timeout = ~0;
12285     struct in_addr ip4;
12286     struct in6_addr ip6;
12287     u8 mac[6];
12288     u8 eid_type = ~0, eid_set = 0;
12289     u32 prefix_length = ~0, t, vni = 0;
12290     u8 filter = 0;
12291
12292     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12293         if (unformat (i, "eid %U/%d", unformat_ip4_address, &ip4, &t)) {
12294             eid_set = 1;
12295             eid_type = 0;
12296             prefix_length = t;
12297         } else if (unformat (i, "eid %U/%d", unformat_ip6_address, &ip6, &t)) {
12298             eid_set = 1;
12299             eid_type = 1;
12300             prefix_length = t;
12301         } else if (unformat (i, "eid %U", unformat_ethernet_address, mac)) {
12302             eid_set = 1;
12303             eid_type = 2;
12304         } else if (unformat (i, "vni %d", &t)) {
12305             vni = t;
12306         } else if (unformat (i, "local")) {
12307             filter = 1;
12308         } else if (unformat (i, "remote")) {
12309             filter = 2;
12310         } else {
12311             errmsg ("parse error '%U'", format_unformat_error, i);
12312             return -99;
12313         }
12314     }
12315
12316     M(LISP_EID_TABLE_DUMP, lisp_eid_table_dump);
12317
12318     mp->filter = filter;
12319     if (eid_set) {
12320         mp->eid_set = 1;
12321         mp->vni = htonl (vni);
12322         mp->eid_type = eid_type;
12323         switch (eid_type) {
12324         case 0:
12325             mp->prefix_length = prefix_length;
12326             clib_memcpy (mp->eid, &ip4, sizeof (ip4));
12327             break;
12328         case 1:
12329             mp->prefix_length = prefix_length;
12330             clib_memcpy (mp->eid, &ip6, sizeof (ip6));
12331             break;
12332         case 2:
12333             clib_memcpy (mp->eid, mac, sizeof (mac));
12334             break;
12335         default:
12336             errmsg ("unknown EID type %d!", eid_type);
12337             return -99;
12338         }
12339     }
12340
12341     vam->noprint_msg = 1;
12342
12343     /* send it... */
12344     S;
12345
12346     /* Use a control ping for synchronization */
12347     {
12348         vl_api_noprint_control_ping_t * mp;
12349         M(NOPRINT_CONTROL_PING, noprint_control_ping);
12350         S;
12351     }
12352
12353     /* Wait for a reply... */
12354     W_L({
12355       if (vam->noprint_msg) {
12356           if (!vam->json_output) {
12357               vam->retval = print_lisp_eid_table_dump(vam);
12358           } else {
12359               vam->retval = json_lisp_eid_table_dump(vam);
12360           }
12361       }
12362
12363       vam->noprint_msg = 0;
12364     });
12365
12366     /* NOTREACHED */
12367     return 0;
12368 }
12369
12370 static int
12371 api_lisp_gpe_tunnel_dump(vat_main_t *vam)
12372 {
12373     vl_api_lisp_gpe_tunnel_dump_t *mp;
12374     f64 timeout = ~0;
12375
12376     if (!vam->json_output) {
12377         fformat(vam->ofp, "%=20s%=30s%=16s%=16s%=16s%=16s"
12378                 "%=16s%=16s%=16s%=16s%=16s\n",
12379                 "Tunel", "Source", "Destination", "Fib encap", "Fib decap",
12380                 "Decap next", "Lisp version", "Flags", "Next protocol",
12381                 "ver_res", "res", "iid");
12382     }
12383
12384     M(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump);
12385     /* send it... */
12386     S;
12387
12388     /* Use a control ping for synchronization */
12389     {
12390         vl_api_control_ping_t * mp;
12391         M(CONTROL_PING, control_ping);
12392         S;
12393     }
12394     /* Wait for a reply... */
12395     W;
12396
12397     /* NOTREACHED */
12398     return 0;
12399 }
12400
12401 static int
12402 api_lisp_map_resolver_dump(vat_main_t *vam)
12403 {
12404     vl_api_lisp_map_resolver_dump_t *mp;
12405     f64 timeout = ~0;
12406
12407     if (!vam->json_output) {
12408         fformat(vam->ofp, "%=20s\n",
12409                 "Map resolver");
12410     }
12411
12412     M(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump);
12413     /* send it... */
12414     S;
12415
12416     /* Use a control ping for synchronization */
12417     {
12418         vl_api_control_ping_t * mp;
12419         M(CONTROL_PING, control_ping);
12420         S;
12421     }
12422     /* Wait for a reply... */
12423     W;
12424
12425     /* NOTREACHED */
12426     return 0;
12427 }
12428
12429 static int
12430 api_show_lisp_status(vat_main_t *vam)
12431 {
12432     vl_api_show_lisp_status_t *mp;
12433     f64 timeout = ~0;
12434
12435     if (!vam->json_output) {
12436         fformat(vam->ofp, "%-20s%-16s\n",
12437                 "lisp status", "locator-set");
12438     }
12439
12440     M(SHOW_LISP_STATUS, show_lisp_status);
12441     /* send it... */
12442     S;
12443     /* Wait for a reply... */
12444     W;
12445
12446     /* NOTREACHED */
12447     return 0;
12448 }
12449
12450 static int
12451 api_lisp_get_map_request_itr_rlocs(vat_main_t *vam)
12452 {
12453     vl_api_lisp_get_map_request_itr_rlocs_t *mp;
12454     f64 timeout = ~0;
12455
12456     if (!vam->json_output) {
12457         fformat(vam->ofp, "%=20s\n",
12458                 "itr-rlocs:");
12459     }
12460
12461     M(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs);
12462     /* send it... */
12463     S;
12464     /* Wait for a reply... */
12465     W;
12466
12467     /* NOTREACHED */
12468     return 0;
12469 }
12470
12471 static int
12472 api_af_packet_create (vat_main_t * vam)
12473 {
12474     unformat_input_t * i = vam->input;
12475     vl_api_af_packet_create_t * mp;
12476     f64 timeout;
12477     u8 * host_if_name = 0;
12478     u8 hw_addr[6];
12479     u8 random_hw_addr = 1;
12480
12481     memset (hw_addr, 0, sizeof (hw_addr));
12482
12483     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12484         if (unformat (i, "name %s", &host_if_name))
12485             vec_add1 (host_if_name, 0);
12486         else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
12487             random_hw_addr = 0;
12488         else
12489           break;
12490     }
12491
12492     if (!vec_len (host_if_name)) {
12493         errmsg ("host-interface name must be specified");
12494         return -99;
12495     }
12496
12497     if (vec_len (host_if_name) > 64) {
12498         errmsg ("host-interface name too long");
12499         return -99;
12500     }
12501
12502     M(AF_PACKET_CREATE, af_packet_create);
12503
12504     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
12505     clib_memcpy (mp->hw_addr, hw_addr, 6);
12506     mp->use_random_hw_addr = random_hw_addr;
12507     vec_free (host_if_name);
12508
12509     S; W2(fprintf(vam->ofp," new sw_if_index = %d ", vam->sw_if_index));
12510     /* NOTREACHED */
12511     return 0;
12512 }
12513
12514 static int
12515 api_af_packet_delete (vat_main_t * vam)
12516 {
12517     unformat_input_t * i = vam->input;
12518     vl_api_af_packet_delete_t * mp;
12519     f64 timeout;
12520     u8 * host_if_name = 0;
12521
12522     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12523         if (unformat (i, "name %s", &host_if_name))
12524             vec_add1 (host_if_name, 0);
12525         else
12526           break;
12527     }
12528
12529     if (!vec_len (host_if_name)) {
12530         errmsg ("host-interface name must be specified");
12531         return -99;
12532     }
12533
12534     if (vec_len (host_if_name) > 64) {
12535         errmsg ("host-interface name too long");
12536         return -99;
12537     }
12538
12539     M(AF_PACKET_DELETE, af_packet_delete);
12540
12541     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
12542     vec_free (host_if_name);
12543
12544     S; W;
12545     /* NOTREACHED */
12546     return 0;
12547 }
12548
12549 static int
12550 api_policer_add_del (vat_main_t * vam)
12551 {
12552     unformat_input_t * i = vam->input;
12553     vl_api_policer_add_del_t * mp;
12554     f64 timeout;
12555     u8 is_add = 1;
12556     u8 * name = 0;
12557     u32 cir = 0;
12558     u32 eir = 0;
12559     u64 cb = 0;
12560     u64 eb = 0;
12561     u8 rate_type = 0;
12562     u8 round_type = 0;
12563     u8 type = 0;
12564     u8 color_aware = 0;
12565     sse2_qos_pol_action_params_st conform_action, exceed_action, violate_action;
12566
12567     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12568         if (unformat (i, "del"))
12569             is_add = 0;
12570         else if (unformat (i, "name %s", &name))
12571             vec_add1 (name, 0);
12572         else if (unformat (i, "cir %u", &cir))
12573             ;
12574         else if (unformat (i, "eir %u", &eir))
12575             ;
12576         else if (unformat (i, "cb %u", &cb))
12577             ;
12578         else if (unformat (i, "eb %u", &eb))
12579             ;
12580         else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
12581                            &rate_type))
12582             ;
12583         else if (unformat (i, "round_type %U", unformat_policer_round_type,
12584                            &round_type))
12585             ;
12586         else if (unformat (i, "type %U", unformat_policer_type, &type))
12587             ;
12588         else if (unformat (i, "conform_action %U", unformat_policer_action_type,
12589                            &conform_action))
12590             ;
12591         else if (unformat (i, "exceed_action %U", unformat_policer_action_type,
12592                            &exceed_action))
12593             ;
12594         else if (unformat (i, "violate_action %U", unformat_policer_action_type,
12595                            &violate_action))
12596             ;
12597         else if (unformat (i, "color-aware"))
12598             color_aware = 1;
12599         else
12600           break;
12601     }
12602
12603     if (!vec_len (name)) {
12604         errmsg ("policer name must be specified");
12605         return -99;
12606     }
12607
12608     if (vec_len (name) > 64) {
12609         errmsg ("policer name too long");
12610         return -99;
12611     }
12612
12613     M(POLICER_ADD_DEL, policer_add_del);
12614
12615     clib_memcpy (mp->name, name, vec_len (name));
12616     vec_free (name);
12617     mp->is_add = is_add;
12618     mp->cir = cir;
12619     mp->eir = eir;
12620     mp->cb = cb;
12621     mp->eb = eb;
12622     mp->rate_type = rate_type;
12623     mp->round_type = round_type;
12624     mp->type = type;
12625     mp->conform_action_type = conform_action.action_type;
12626     mp->conform_dscp = conform_action.dscp;
12627     mp->exceed_action_type = exceed_action.action_type;
12628     mp->exceed_dscp = exceed_action.dscp;
12629     mp->violate_action_type = violate_action.action_type;
12630     mp->violate_dscp = violate_action.dscp;
12631     mp->color_aware = color_aware;
12632
12633     S; W;
12634     /* NOTREACHED */
12635     return 0;
12636 }
12637
12638 static int
12639 api_policer_dump(vat_main_t *vam)
12640 {
12641     unformat_input_t * i = vam->input;
12642     vl_api_policer_dump_t *mp;
12643     f64 timeout = ~0;
12644     u8 *match_name = 0;
12645     u8 match_name_valid = 0;
12646
12647     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12648         if (unformat (i, "name %s", &match_name)) {
12649             vec_add1 (match_name, 0);
12650             match_name_valid = 1;
12651         } else
12652             break;
12653     }
12654
12655     M(POLICER_DUMP, policer_dump);
12656     mp->match_name_valid = match_name_valid;
12657     clib_memcpy (mp->match_name, match_name, vec_len (match_name));
12658     vec_free (match_name);
12659     /* send it... */
12660     S;
12661
12662     /* Use a control ping for synchronization */
12663     {
12664         vl_api_control_ping_t * mp;
12665         M(CONTROL_PING, control_ping);
12666         S;
12667     }
12668     /* Wait for a reply... */
12669     W;
12670
12671     /* NOTREACHED */
12672     return 0;
12673 }
12674
12675 static int
12676 api_policer_classify_set_interface (vat_main_t * vam)
12677 {
12678     unformat_input_t * i = vam->input;
12679     vl_api_policer_classify_set_interface_t *mp;
12680     f64 timeout;
12681     u32 sw_if_index;
12682     int sw_if_index_set;
12683     u32 ip4_table_index = ~0;
12684     u32 ip6_table_index = ~0;
12685     u32 l2_table_index = ~0;
12686     u8 is_add = 1;
12687
12688     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12689         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
12690             sw_if_index_set = 1;
12691         else if (unformat (i, "sw_if_index %d", &sw_if_index))
12692             sw_if_index_set = 1;
12693         else if (unformat (i, "del"))
12694             is_add = 0;
12695         else if (unformat (i, "ip4-table %d", &ip4_table_index))
12696             ;
12697         else if (unformat (i, "ip6-table %d", &ip6_table_index))
12698             ;
12699         else if (unformat (i, "l2-table %d", &l2_table_index))
12700             ;
12701         else {
12702             clib_warning ("parse error '%U'", format_unformat_error, i);
12703             return -99;
12704         }
12705     }
12706
12707     if (sw_if_index_set == 0) {
12708         errmsg ("missing interface name or sw_if_index\n");
12709         return -99;
12710     }
12711
12712     M(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface);
12713
12714     mp->sw_if_index = ntohl(sw_if_index);
12715     mp->ip4_table_index = ntohl(ip4_table_index);
12716     mp->ip6_table_index = ntohl(ip6_table_index);
12717     mp->l2_table_index = ntohl(l2_table_index);
12718     mp->is_add = is_add;
12719
12720     S; W;
12721     /* NOTREACHED */
12722     return 0;
12723 }
12724
12725 static int
12726 api_policer_classify_dump(vat_main_t *vam)
12727 {
12728     unformat_input_t * i = vam->input;
12729     vl_api_policer_classify_dump_t *mp;
12730     f64 timeout = ~0;
12731     u8 type = POLICER_CLASSIFY_N_TABLES;
12732
12733     if (unformat (i, "type %U", unformat_classify_table_type, &type))
12734         ;
12735     else {
12736         errmsg ("classify table type must be specified\n");
12737         return -99;
12738     }
12739
12740     if (!vam->json_output) {
12741         fformat(vam->ofp, "%10s%20s\n", "Intfc idx", "Classify table");
12742     }
12743
12744     M(POLICER_CLASSIFY_DUMP, policer_classify_dump);
12745     mp->type = type;
12746     /* send it... */
12747     S;
12748
12749     /* Use a control ping for synchronization */
12750     {
12751         vl_api_control_ping_t * mp;
12752         M(CONTROL_PING, control_ping);
12753         S;
12754     }
12755     /* Wait for a reply... */
12756     W;
12757
12758     /* NOTREACHED */
12759     return 0;
12760 }
12761
12762 static int
12763 api_netmap_create (vat_main_t * vam)
12764 {
12765     unformat_input_t * i = vam->input;
12766     vl_api_netmap_create_t * mp;
12767     f64 timeout;
12768     u8 * if_name = 0;
12769     u8 hw_addr[6];
12770     u8 random_hw_addr = 1;
12771     u8 is_pipe = 0;
12772     u8 is_master = 0;
12773
12774     memset (hw_addr, 0, sizeof (hw_addr));
12775
12776     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12777         if (unformat (i, "name %s", &if_name))
12778             vec_add1 (if_name, 0);
12779         else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
12780             random_hw_addr = 0;
12781         else if (unformat (i, "pipe"))
12782             is_pipe = 1;
12783         else if (unformat (i, "master"))
12784             is_master = 1;
12785         else if (unformat (i, "slave"))
12786             is_master = 0;
12787         else
12788           break;
12789     }
12790
12791     if (!vec_len (if_name)) {
12792         errmsg ("interface name must be specified");
12793         return -99;
12794     }
12795
12796     if (vec_len (if_name) > 64) {
12797         errmsg ("interface name too long");
12798         return -99;
12799     }
12800
12801     M(NETMAP_CREATE, netmap_create);
12802
12803     clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name));
12804     clib_memcpy (mp->hw_addr, hw_addr, 6);
12805     mp->use_random_hw_addr = random_hw_addr;
12806     mp->is_pipe = is_pipe;
12807     mp->is_master = is_master;
12808     vec_free (if_name);
12809
12810     S; W;
12811     /* NOTREACHED */
12812     return 0;
12813 }
12814
12815 static int
12816 api_netmap_delete (vat_main_t * vam)
12817 {
12818     unformat_input_t * i = vam->input;
12819     vl_api_netmap_delete_t * mp;
12820     f64 timeout;
12821     u8 * if_name = 0;
12822
12823     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
12824         if (unformat (i, "name %s", &if_name))
12825             vec_add1 (if_name, 0);
12826         else
12827             break;
12828     }
12829
12830     if (!vec_len (if_name)) {
12831         errmsg ("interface name must be specified");
12832         return -99;
12833     }
12834
12835     if (vec_len (if_name) > 64) {
12836         errmsg ("interface name too long");
12837         return -99;
12838     }
12839
12840     M(NETMAP_DELETE, netmap_delete);
12841
12842     clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name));
12843     vec_free (if_name);
12844
12845     S; W;
12846     /* NOTREACHED */
12847     return 0;
12848 }
12849
12850 static void vl_api_mpls_gre_tunnel_details_t_handler
12851 (vl_api_mpls_gre_tunnel_details_t * mp)
12852 {
12853     vat_main_t * vam = &vat_main;
12854     i32 i;
12855     i32 len = ntohl(mp->nlabels);
12856
12857     if (mp->l2_only == 0) {
12858         fformat(vam->ofp, "[%d]: src %U, dst %U, adj %U/%d, labels ",
12859                 ntohl(mp->tunnel_index),
12860                 format_ip4_address, &mp->tunnel_src,
12861                 format_ip4_address, &mp->tunnel_dst,
12862                 format_ip4_address, &mp->intfc_address,
12863                 ntohl(mp->mask_width));
12864         for (i = 0; i < len; i++) {
12865             fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
12866         }
12867         fformat(vam->ofp, "\n");
12868         fformat(vam->ofp, "      inner fib index %d, outer fib index %d\n",
12869                 ntohl(mp->inner_fib_index), ntohl(mp->outer_fib_index));
12870     } else {
12871         fformat(vam->ofp, "[%d]: src %U, dst %U, key %U, labels ",
12872                 ntohl(mp->tunnel_index),
12873                 format_ip4_address, &mp->tunnel_src,
12874                 format_ip4_address, &mp->tunnel_dst,
12875                 format_ip4_address, &mp->intfc_address);
12876         for (i = 0; i < len; i++) {
12877             fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
12878         }
12879         fformat(vam->ofp, "\n");
12880         fformat(vam->ofp, "      l2 interface %d, outer fib index %d\n",
12881                 ntohl(mp->hw_if_index), ntohl(mp->outer_fib_index));
12882     }
12883 }
12884
12885 static void vl_api_mpls_gre_tunnel_details_t_handler_json
12886 (vl_api_mpls_gre_tunnel_details_t * mp)
12887 {
12888     vat_main_t * vam = &vat_main;
12889     vat_json_node_t *node = NULL;
12890     struct in_addr ip4;
12891     i32 i;
12892     i32 len = ntohl(mp->nlabels);
12893
12894     if (VAT_JSON_ARRAY != vam->json_tree.type) {
12895         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
12896         vat_json_init_array(&vam->json_tree);
12897     }
12898     node = vat_json_array_add(&vam->json_tree);
12899
12900     vat_json_init_object(node);
12901     vat_json_object_add_uint(node, "tunnel_index", ntohl(mp->tunnel_index));
12902     clib_memcpy(&ip4, &(mp->intfc_address), sizeof(ip4));
12903     vat_json_object_add_ip4(node, "intfc_address", ip4);
12904     vat_json_object_add_uint(node, "inner_fib_index", ntohl(mp->inner_fib_index));
12905     vat_json_object_add_uint(node, "mask_width", ntohl(mp->mask_width));
12906     vat_json_object_add_uint(node, "encap_index", ntohl(mp->encap_index));
12907     vat_json_object_add_uint(node, "hw_if_index", ntohl(mp->hw_if_index));
12908     vat_json_object_add_uint(node, "l2_only", ntohl(mp->l2_only));
12909     clib_memcpy(&ip4, &(mp->tunnel_src), sizeof(ip4));
12910     vat_json_object_add_ip4(node, "tunnel_src", ip4);
12911     clib_memcpy(&ip4, &(mp->tunnel_dst), sizeof(ip4));
12912     vat_json_object_add_ip4(node, "tunnel_dst", ip4);
12913     vat_json_object_add_uint(node, "outer_fib_index", ntohl(mp->outer_fib_index));
12914     vat_json_object_add_uint(node, "label_count", len);
12915     for (i = 0; i < len; i++) {
12916         vat_json_object_add_uint(node, "label", ntohl(mp->labels[i]));
12917     }
12918 }
12919
12920 static int api_mpls_gre_tunnel_dump (vat_main_t * vam)
12921 {
12922     vl_api_mpls_gre_tunnel_dump_t *mp;
12923     f64 timeout;
12924     i32 index = -1;
12925
12926     /* Parse args required to build the message */
12927     while (unformat_check_input (vam->input) != UNFORMAT_END_OF_INPUT) {
12928         if (!unformat (vam->input, "tunnel_index %d", &index)) {
12929             index = -1;
12930             break;
12931         }
12932     }
12933
12934     fformat(vam->ofp, "  tunnel_index %d\n", index);
12935
12936     M(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump);
12937     mp->tunnel_index = htonl(index);
12938     S;
12939
12940     /* Use a control ping for synchronization */
12941     {
12942         vl_api_control_ping_t * mp;
12943         M(CONTROL_PING, control_ping);
12944         S;
12945     }
12946     W;
12947 }
12948
12949 static void vl_api_mpls_eth_tunnel_details_t_handler
12950 (vl_api_mpls_eth_tunnel_details_t * mp)
12951 {
12952     vat_main_t * vam = &vat_main;
12953     i32 i;
12954     i32 len = ntohl(mp->nlabels);
12955
12956     fformat(vam->ofp, "[%d]: dst %U, adj %U/%d, labels ",
12957             ntohl(mp->tunnel_index),
12958             format_ethernet_address, &mp->tunnel_dst_mac,
12959             format_ip4_address, &mp->intfc_address,
12960             ntohl(mp->mask_width));
12961     for (i = 0; i < len; i++) {
12962         fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
12963     }
12964     fformat(vam->ofp, "\n");
12965     fformat(vam->ofp, "      tx on %d, rx fib index %d\n",
12966             ntohl(mp->tx_sw_if_index),
12967             ntohl(mp->inner_fib_index));
12968 }
12969
12970 static void vl_api_mpls_eth_tunnel_details_t_handler_json
12971 (vl_api_mpls_eth_tunnel_details_t * mp)
12972 {
12973     vat_main_t * vam = &vat_main;
12974     vat_json_node_t *node = NULL;
12975     struct in_addr ip4;
12976     i32 i;
12977     i32 len = ntohl(mp->nlabels);
12978
12979     if (VAT_JSON_ARRAY != vam->json_tree.type) {
12980         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
12981         vat_json_init_array(&vam->json_tree);
12982     }
12983     node = vat_json_array_add(&vam->json_tree);
12984
12985     vat_json_init_object(node);
12986     vat_json_object_add_uint(node, "tunnel_index", ntohl(mp->tunnel_index));
12987     clib_memcpy(&ip4, &(mp->intfc_address), sizeof(ip4));
12988     vat_json_object_add_ip4(node, "intfc_address", ip4);
12989     vat_json_object_add_uint(node, "inner_fib_index", ntohl(mp->inner_fib_index));
12990     vat_json_object_add_uint(node, "mask_width", ntohl(mp->mask_width));
12991     vat_json_object_add_uint(node, "encap_index", ntohl(mp->encap_index));
12992     vat_json_object_add_uint(node, "hw_if_index", ntohl(mp->hw_if_index));
12993     vat_json_object_add_uint(node, "l2_only", ntohl(mp->l2_only));
12994     vat_json_object_add_string_copy(node, "tunnel_dst_mac",
12995             format(0, "%U", format_ethernet_address, &mp->tunnel_dst_mac));
12996     vat_json_object_add_uint(node, "tx_sw_if_index", ntohl(mp->tx_sw_if_index));
12997     vat_json_object_add_uint(node, "label_count", len);
12998     for (i = 0; i < len; i++) {
12999         vat_json_object_add_uint(node, "label", ntohl(mp->labels[i]));
13000     }
13001 }
13002
13003 static int api_mpls_eth_tunnel_dump (vat_main_t * vam)
13004 {
13005     vl_api_mpls_eth_tunnel_dump_t *mp;
13006     f64 timeout;
13007     i32 index = -1;
13008
13009     /* Parse args required to build the message */
13010     while (unformat_check_input (vam->input) != UNFORMAT_END_OF_INPUT) {
13011         if (!unformat (vam->input, "tunnel_index %d", &index)) {
13012             index = -1;
13013             break;
13014         }
13015     }
13016
13017     fformat(vam->ofp, "  tunnel_index %d\n", index);
13018
13019     M(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump);
13020     mp->tunnel_index = htonl(index);
13021     S;
13022
13023     /* Use a control ping for synchronization */
13024     {
13025         vl_api_control_ping_t * mp;
13026         M(CONTROL_PING, control_ping);
13027         S;
13028     }
13029     W;
13030 }
13031
13032 static void vl_api_mpls_fib_encap_details_t_handler
13033 (vl_api_mpls_fib_encap_details_t * mp)
13034 {
13035     vat_main_t * vam = &vat_main;
13036     i32 i;
13037     i32 len = ntohl(mp->nlabels);
13038
13039     fformat(vam->ofp, "table %d, dest %U, label ",
13040             ntohl(mp->fib_index),
13041             format_ip4_address, &mp->dest,
13042             len);
13043     for (i = 0; i < len; i++) {
13044         fformat(vam->ofp, "%u ", ntohl(mp->labels[i]));
13045     }
13046     fformat(vam->ofp, "\n");
13047 }
13048
13049 static void vl_api_mpls_fib_encap_details_t_handler_json
13050 (vl_api_mpls_fib_encap_details_t * mp)
13051 {
13052     vat_main_t * vam = &vat_main;
13053     vat_json_node_t *node = NULL;
13054     i32 i;
13055     i32 len = ntohl(mp->nlabels);
13056     struct in_addr ip4;
13057
13058     if (VAT_JSON_ARRAY != vam->json_tree.type) {
13059         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
13060         vat_json_init_array(&vam->json_tree);
13061     }
13062     node = vat_json_array_add(&vam->json_tree);
13063
13064     vat_json_init_object(node);
13065     vat_json_object_add_uint(node, "table", ntohl(mp->fib_index));
13066     vat_json_object_add_uint(node, "entry_index", ntohl(mp->entry_index));
13067     clib_memcpy(&ip4, &(mp->dest), sizeof(ip4));
13068     vat_json_object_add_ip4(node, "dest", ip4);
13069     vat_json_object_add_uint(node, "s_bit", ntohl(mp->s_bit));
13070     vat_json_object_add_uint(node, "label_count", len);
13071     for (i = 0; i < len; i++) {
13072         vat_json_object_add_uint(node, "label", ntohl(mp->labels[i]));
13073     }
13074 }
13075
13076 static int api_mpls_fib_encap_dump (vat_main_t * vam)
13077 {
13078     vl_api_mpls_fib_encap_dump_t *mp;
13079     f64 timeout;
13080
13081     M(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump);
13082     S;
13083
13084     /* Use a control ping for synchronization */
13085     {
13086         vl_api_control_ping_t * mp;
13087         M(CONTROL_PING, control_ping);
13088         S;
13089     }
13090     W;
13091 }
13092
13093 static void vl_api_mpls_fib_decap_details_t_handler
13094 (vl_api_mpls_fib_decap_details_t * mp)
13095 {
13096     vat_main_t * vam = &vat_main;
13097
13098     fformat(vam->ofp, "RX table %d, TX table/intfc %u, swif_tag '%s', label %u, s_bit %u\n",
13099             ntohl(mp->rx_table_id),
13100             ntohl(mp->tx_table_id),
13101             mp->swif_tag,
13102             ntohl(mp->label),
13103             ntohl(mp->s_bit));
13104 }
13105
13106 static void vl_api_mpls_fib_decap_details_t_handler_json
13107 (vl_api_mpls_fib_decap_details_t * mp)
13108 {
13109     vat_main_t * vam = &vat_main;
13110     vat_json_node_t *node = NULL;
13111     struct in_addr ip4;
13112
13113     if (VAT_JSON_ARRAY != vam->json_tree.type) {
13114         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
13115         vat_json_init_array(&vam->json_tree);
13116     }
13117     node = vat_json_array_add(&vam->json_tree);
13118
13119     vat_json_init_object(node);
13120     vat_json_object_add_uint(node, "table", ntohl(mp->fib_index));
13121     vat_json_object_add_uint(node, "entry_index", ntohl(mp->entry_index));
13122     clib_memcpy(&ip4, &(mp->dest), sizeof(ip4));
13123     vat_json_object_add_ip4(node, "dest", ip4);
13124     vat_json_object_add_uint(node, "s_bit", ntohl(mp->s_bit));
13125     vat_json_object_add_uint(node, "label", ntohl(mp->label));
13126     vat_json_object_add_uint(node, "rx_table_id", ntohl(mp->rx_table_id));
13127     vat_json_object_add_uint(node, "tx_table_id", ntohl(mp->tx_table_id));
13128     vat_json_object_add_string_copy(node, "swif_tag", mp->swif_tag);
13129 }
13130
13131 static int api_mpls_fib_decap_dump (vat_main_t * vam)
13132 {
13133     vl_api_mpls_fib_decap_dump_t *mp;
13134     f64 timeout;
13135
13136     M(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump);
13137     S;
13138
13139     /* Use a control ping for synchronization */
13140     {
13141         vl_api_control_ping_t * mp;
13142         M(CONTROL_PING, control_ping);
13143         S;
13144     }
13145     W;
13146 }
13147
13148 int api_classify_table_ids (vat_main_t *vam)
13149 {
13150     vl_api_classify_table_ids_t *mp;
13151     f64 timeout;
13152
13153     /* Construct the API message */
13154     M(CLASSIFY_TABLE_IDS, classify_table_ids);
13155     mp->context = 0;
13156
13157     S; W;
13158     /* NOTREACHED */
13159     return 0;
13160 }
13161
13162 int api_classify_table_by_interface (vat_main_t *vam)
13163 {
13164     unformat_input_t * input = vam->input;
13165     vl_api_classify_table_by_interface_t *mp;
13166     f64 timeout;
13167
13168     u32 sw_if_index = ~0;
13169     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13170         if (unformat (input, "%U", unformat_sw_if_index, vam, &sw_if_index))
13171             ;
13172         else if (unformat (input, "sw_if_index %d", &sw_if_index))
13173             ;
13174         else
13175             break;
13176     }
13177     if (sw_if_index == ~0) {
13178         errmsg ("missing interface name or sw_if_index\n");
13179         return -99;
13180     }
13181
13182     /* Construct the API message */
13183     M(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface);
13184     mp->context = 0;
13185     mp->sw_if_index = ntohl(sw_if_index);
13186
13187     S; W;
13188     /* NOTREACHED */
13189     return 0;
13190 }
13191
13192 int api_classify_table_info (vat_main_t *vam)
13193 {
13194     unformat_input_t * input = vam->input;
13195     vl_api_classify_table_info_t *mp;
13196     f64 timeout;
13197
13198     u32 table_id = ~0;
13199     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13200         if (unformat (input, "table_id %d", &table_id))
13201             ;
13202         else
13203             break;
13204     }
13205     if (table_id == ~0) {
13206         errmsg ("missing table id\n");
13207         return -99;
13208     }
13209
13210     /* Construct the API message */
13211     M(CLASSIFY_TABLE_INFO, classify_table_info);
13212     mp->context = 0;
13213     mp->table_id = ntohl(table_id);
13214
13215     S; W;
13216     /* NOTREACHED */
13217     return 0;
13218 }
13219
13220 int api_classify_session_dump (vat_main_t *vam)
13221 {
13222     unformat_input_t * input = vam->input;
13223     vl_api_classify_session_dump_t *mp;
13224     f64 timeout;
13225
13226     u32 table_id = ~0;
13227     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13228         if (unformat (input, "table_id %d", &table_id))
13229             ;
13230         else
13231             break;
13232     }
13233     if (table_id == ~0) {
13234         errmsg ("missing table id\n");
13235         return -99;
13236     }
13237
13238     /* Construct the API message */
13239     M(CLASSIFY_SESSION_DUMP, classify_session_dump);
13240     mp->context = 0;
13241     mp->table_id = ntohl(table_id);
13242     S;
13243
13244     /* Use a control ping for synchronization */
13245     {
13246         vl_api_control_ping_t * mp;
13247         M(CONTROL_PING, control_ping);
13248         S;
13249     }
13250     W;
13251     /* NOTREACHED */
13252     return 0;
13253 }
13254
13255 static void vl_api_ipfix_details_t_handler (vl_api_ipfix_details_t * mp)
13256 {
13257     vat_main_t * vam = &vat_main;
13258
13259     fformat(vam->ofp, "collector_address %U, collector_port %d, "
13260                       "src_address %U, fib_index %u, path_mtu %u, "
13261                       "template_interval %u\n",
13262             format_ip4_address, mp->collector_address,
13263             ntohs(mp->collector_port),
13264             format_ip4_address, mp->src_address,
13265             ntohl(mp->fib_index),
13266             ntohl(mp->path_mtu),
13267             ntohl(mp->template_interval));
13268
13269     vam->retval = 0;
13270     vam->result_ready = 1;
13271 }
13272
13273 static void vl_api_ipfix_details_t_handler_json
13274 (vl_api_ipfix_details_t * mp)
13275 {
13276     vat_main_t * vam = &vat_main;
13277     vat_json_node_t node;
13278     struct in_addr collector_address;
13279     struct in_addr src_address;
13280
13281     vat_json_init_object(&node);
13282     clib_memcpy(&collector_address, &mp->collector_address,
13283                 sizeof(collector_address));
13284     vat_json_object_add_ip4(&node, "collector_address", collector_address);
13285     vat_json_object_add_uint(&node, "collector_port",
13286                              ntohs(mp->collector_port));
13287     clib_memcpy(&src_address, &mp->src_address, sizeof(src_address));
13288     vat_json_object_add_ip4(&node, "src_address", src_address);
13289     vat_json_object_add_uint(&node, "fib_index", ntohl(mp->fib_index));
13290     vat_json_object_add_uint(&node, "path_mtu", ntohl(mp->path_mtu));
13291     vat_json_object_add_uint(&node, "template_interval",
13292                              ntohl(mp->template_interval));
13293
13294     vat_json_print(vam->ofp, &node);
13295     vat_json_free(&node);
13296     vam->retval = 0;
13297     vam->result_ready = 1;
13298 }
13299
13300 int api_ipfix_dump (vat_main_t *vam)
13301 {
13302     vl_api_ipfix_dump_t *mp;
13303     f64 timeout;
13304
13305     /* Construct the API message */
13306     M(IPFIX_DUMP, ipfix_dump);
13307     mp->context = 0;
13308
13309     S; W;
13310     /* NOTREACHED */
13311     return 0;
13312 }
13313
13314 int api_pg_create_interface (vat_main_t *vam)
13315 {
13316     unformat_input_t * input = vam->input;
13317     vl_api_pg_create_interface_t *mp;
13318     f64 timeout;
13319
13320     u32 if_id = ~0;
13321     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13322         if (unformat (input, "if_id %d", &if_id))
13323             ;
13324         else
13325             break;
13326     }
13327     if (if_id == ~0) {
13328         errmsg ("missing pg interface index\n");
13329         return -99;
13330     }
13331
13332     /* Construct the API message */
13333     M(PG_CREATE_INTERFACE, pg_create_interface);
13334     mp->context = 0;
13335     mp->interface_id = ntohl(if_id);
13336
13337     S; W;
13338     /* NOTREACHED */
13339     return 0;
13340 }
13341
13342 int api_pg_capture (vat_main_t *vam)
13343 {
13344     unformat_input_t * input = vam->input;
13345     vl_api_pg_capture_t *mp;
13346     f64 timeout;
13347
13348     u32 if_id = ~0;
13349     u8 enable = 1;
13350     u32 count = 1;
13351     u8 pcap_file_set = 0;
13352     u8 * pcap_file = 0;
13353     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13354         if (unformat (input, "if_id %d", &if_id))
13355             ;
13356         else if (unformat (input, "pcap %s", &pcap_file))
13357             pcap_file_set = 1;
13358         else if (unformat (input, "count %d", &count))
13359             ;
13360         else if (unformat (input, "disable"))
13361             enable = 0;
13362         else
13363             break;
13364     }
13365     if (if_id == ~0) {
13366         errmsg ("missing pg interface index\n");
13367         return -99;
13368     }
13369     if (pcap_file_set>0) {
13370         if (vec_len (pcap_file) > 255) {
13371             errmsg ("pcap file name is too long\n");
13372             return -99;
13373         }
13374     }
13375
13376     u32 name_len = vec_len(pcap_file);
13377     /* Construct the API message */
13378     M(PG_CAPTURE, pg_capture);
13379     mp->context = 0;
13380     mp->interface_id = ntohl(if_id);
13381     mp->is_enabled = enable;
13382     mp->count = ntohl(count);
13383     mp->pcap_name_length = ntohl(name_len);
13384     if (pcap_file_set != 0) {
13385         clib_memcpy(mp->pcap_file_name, pcap_file, name_len);
13386     }
13387     vec_free(pcap_file);
13388
13389     S; W;
13390     /* NOTREACHED */
13391     return 0;
13392 }
13393
13394 int api_pg_enable_disable (vat_main_t *vam)
13395 {
13396     unformat_input_t * input = vam->input;
13397     vl_api_pg_enable_disable_t *mp;
13398     f64 timeout;
13399
13400     u8 enable = 1;
13401     u8 stream_name_set = 0;
13402     u8 * stream_name = 0;
13403     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
13404         if (unformat (input, "stream %s", &stream_name))
13405             stream_name_set = 1;
13406         else if (unformat (input, "disable"))
13407             enable = 0;
13408         else
13409             break;
13410     }
13411
13412     if (stream_name_set>0) {
13413         if (vec_len (stream_name) > 255) {
13414             errmsg ("stream name too long\n");
13415             return -99;
13416         }
13417     }
13418
13419     u32 name_len = vec_len(stream_name);
13420     /* Construct the API message */
13421     M(PG_ENABLE_DISABLE, pg_enable_disable);
13422     mp->context = 0;
13423     mp->is_enabled = enable;
13424     if (stream_name_set != 0) {
13425         mp->stream_name_length = ntohl(name_len);
13426         clib_memcpy(mp->stream_name, stream_name, name_len);
13427     }
13428     vec_free(stream_name);
13429
13430     S; W;
13431     /* NOTREACHED */
13432     return 0;
13433 }
13434
13435 int api_ip_source_and_port_range_check_add_del (vat_main_t *vam)
13436 {
13437     unformat_input_t * input = vam->input;
13438     vl_api_ip_source_and_port_range_check_add_del_t *mp;
13439     f64 timeout;
13440
13441     u16 * low_ports = 0;
13442     u16 * high_ports = 0;
13443     u16 this_low;
13444     u16 this_hi;
13445     ip4_address_t ip4_addr;
13446     ip6_address_t ip6_addr;
13447     u32 length;
13448     u32 tmp, tmp2;
13449     u8 prefix_set = 0;
13450     u32 vrf_id =~0;
13451     u8 is_add = 1;
13452     u8 is_ipv6 = 0;
13453
13454     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13455         {
13456             if (unformat (input, "%U/%d", unformat_ip4_address, &ip4_addr, &length))
13457                 {
13458                     prefix_set = 1;
13459                 }
13460             else if (unformat (input, "%U/%d", unformat_ip6_address, &ip6_addr, &length))
13461                 {
13462                     prefix_set = 1;
13463                     is_ipv6 = 1;
13464                 }
13465             else if (unformat (input, "vrf %d", &vrf_id))
13466                 ;
13467             else if (unformat (input, "del"))
13468                 is_add = 0;
13469             else if (unformat (input, "port %d", &tmp))
13470                 {
13471                     if (tmp == 0 || tmp > 65535) {
13472                         errmsg ("port %d out of range", tmp);
13473                         return -99;
13474                     }
13475                     this_low = tmp;
13476                     this_hi = this_low + 1;
13477                     vec_add1 (low_ports, this_low);
13478                     vec_add1 (high_ports, this_hi);
13479                 }
13480             else if (unformat (input, "range %d - %d", &tmp, &tmp2))
13481                 {
13482                     if ((tmp > tmp2) ||
13483                         (tmp == 0) ||
13484                         (tmp2 > 65535)) {
13485                         errmsg ("incorrect range parameters\n");
13486                         return -99;
13487                     }
13488                     this_low = tmp;
13489                     /* Note: in debug CLI +1 is added to high before
13490                        passing to real fn that does "the work"
13491                        (ip_source_and_port_range_check_add_del).
13492                        This fn is a wrapper around the binary API fn a
13493                        control plane will call, which expects this increment
13494                        to have occurred. Hence letting the binary API control
13495                        plane fn do the increment for consistency between VAT
13496                        and other control planes.
13497                      */
13498                     this_hi = tmp2;
13499                     vec_add1 (low_ports, this_low);
13500                     vec_add1 (high_ports, this_hi);
13501                 }
13502             else
13503                 break;
13504         }
13505
13506     if (prefix_set == 0) {
13507         errmsg ("<address>/<mask> not specified\n");
13508         return -99;
13509     }
13510
13511     if (vrf_id == ~0) {
13512         errmsg ("VRF ID required, not specified\n");
13513         return -99;
13514     }
13515
13516     if (vrf_id == 0) {
13517         errmsg ("VRF ID should not be default. Should be distinct VRF for this purpose.\n");
13518         return -99;
13519     }
13520
13521     if (vec_len(low_ports) == 0) {
13522         errmsg ("At least one port or port range required\n");
13523         return -99;
13524     }
13525
13526     M(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, ip_source_and_port_range_check_add_del);
13527
13528     mp->is_add = is_add;
13529
13530     if (is_ipv6) {
13531         mp->is_ipv6 = 1;
13532         clib_memcpy (mp->address, &ip6_addr, sizeof (ip6_addr));
13533     } else {
13534         mp->is_ipv6 = 0;
13535         clib_memcpy (mp->address, &ip4_addr, sizeof (ip4_addr));
13536     }
13537
13538     mp->mask_length = length;
13539     mp->number_of_ranges = vec_len (low_ports);
13540
13541     clib_memcpy (mp->low_ports, low_ports, vec_len(low_ports));
13542     vec_free(low_ports);
13543
13544     clib_memcpy (mp->high_ports, high_ports, vec_len(high_ports));
13545     vec_free (high_ports);
13546
13547     mp->vrf_id = ntohl(vrf_id);
13548
13549     S; W;
13550     /* NOTREACHED */
13551     return 0;
13552 }
13553
13554 int api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
13555 {
13556     unformat_input_t * input = vam->input;
13557     vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
13558     f64 timeout;
13559     u32 sw_if_index = ~0;
13560     u32 vrf_id = ~0;
13561     u8 is_add = 1;
13562
13563     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
13564         {
13565             if (unformat (input, "%U", unformat_sw_if_index, vam, &sw_if_index))
13566             ;
13567             else if (unformat (input, "sw_if_index %d", &sw_if_index))
13568             ;
13569             else if (unformat (input, "vrf %d", &vrf_id))
13570                 ;
13571             else if (unformat (input, "del"))
13572                 is_add = 0;
13573             else
13574                 break;
13575         }
13576
13577     if (sw_if_index == ~0) {
13578         errmsg ("Interface required but not specified\n");
13579         return -99;
13580     }
13581
13582     if (vrf_id == ~0) {
13583         errmsg ("VRF ID required but not specified\n");
13584         return -99;
13585     }
13586
13587     if (vrf_id == 0) {
13588         errmsg ("VRF ID should not be default. Should be distinct VRF for this purpose.\n");
13589         return -99;
13590     }
13591
13592     /* Construct the API message */
13593     M(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, ip_source_and_port_range_check_interface_add_del);
13594
13595     mp->sw_if_index = ntohl (sw_if_index);
13596     mp->is_add = is_add;
13597     mp->vrf_id = ntohl (vrf_id);
13598
13599     /* send it... */
13600     S;
13601
13602     /* Wait for a reply... */
13603     W;
13604 }
13605
13606 static int q_or_quit (vat_main_t * vam)
13607 {
13608     longjmp (vam->jump_buf, 1);
13609     return 0; /* not so much */
13610 }
13611 static int q (vat_main_t * vam) {return q_or_quit (vam);}
13612 static int quit (vat_main_t * vam) {return q_or_quit (vam);}
13613
13614 static int comment (vat_main_t * vam)
13615 {
13616     return 0;
13617 }
13618
13619 static int cmd_cmp (void * a1, void * a2)
13620 {
13621   u8 ** c1 = a1;
13622   u8 ** c2 = a2;
13623
13624   return strcmp ((char *)(c1[0]), (char *)(c2[0]));
13625 }
13626
13627 static int help (vat_main_t * vam)
13628 {
13629     u8 ** cmds = 0;
13630     u8 * name = 0;
13631     hash_pair_t * p;
13632     unformat_input_t * i = vam->input;
13633     int j;
13634
13635     if (unformat (i, "%s", &name)) {
13636         uword *hs;
13637
13638         vec_add1(name, 0);
13639
13640         hs = hash_get_mem (vam->help_by_name, name);
13641         if (hs)
13642             fformat (vam->ofp, "usage: %s %s\n", name, hs[0]);
13643         else
13644             fformat (vam->ofp, "No such msg / command '%s'\n", name);
13645         vec_free(name);
13646         return 0;
13647     }
13648
13649     fformat(vam->ofp, "Help is available for the following:\n");
13650
13651     hash_foreach_pair (p, vam->function_by_name,
13652     ({
13653         vec_add1 (cmds, (u8 *)(p->key));
13654     }));
13655
13656     vec_sort_with_function (cmds, cmd_cmp);
13657
13658     for (j = 0; j < vec_len(cmds); j++)
13659         fformat (vam->ofp, "%s\n", cmds[j]);
13660
13661     vec_free (cmds);
13662     return 0;
13663 }
13664
13665 static int set (vat_main_t * vam)
13666 {
13667     u8 * name = 0, * value = 0;
13668     unformat_input_t * i = vam->input;
13669
13670     if (unformat (i, "%s", &name)) {
13671         /* The input buffer is a vector, not a string. */
13672         value = vec_dup (i->buffer);
13673         vec_delete (value, i->index, 0);
13674         /* Almost certainly has a trailing newline */
13675         if (value[vec_len(value)-1] == '\n')
13676             value[vec_len(value)-1] = 0;
13677         /* Make sure it's a proper string, one way or the other */
13678         vec_add1 (value, 0);
13679         (void) clib_macro_set_value (&vam->macro_main,
13680                                      (char *)name, (char *)value);
13681     }
13682     else
13683         errmsg ("usage: set <name> <value>\n");
13684
13685     vec_free (name);
13686     vec_free (value);
13687     return 0;
13688 }
13689
13690 static int unset (vat_main_t * vam)
13691 {
13692     u8 * name = 0;
13693
13694     if (unformat (vam->input, "%s", &name))
13695         if (clib_macro_unset (&vam->macro_main, (char *)name) == 1)
13696             errmsg ("unset: %s wasn't set\n", name);
13697     vec_free (name);
13698     return 0;
13699 }
13700
13701 typedef struct {
13702     u8 * name;
13703     u8 * value;
13704 } macro_sort_t;
13705
13706
13707 static int macro_sort_cmp (void * a1, void * a2)
13708 {
13709   macro_sort_t * s1 = a1;
13710   macro_sort_t * s2 = a2;
13711
13712   return strcmp ((char *)(s1->name), (char *)(s2->name));
13713 }
13714
13715 static int dump_macro_table (vat_main_t * vam)
13716 {
13717     macro_sort_t * sort_me = 0, * sm;
13718     int i;
13719     hash_pair_t * p;
13720
13721     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
13722     ({
13723         vec_add2 (sort_me, sm, 1);
13724         sm->name = (u8 *)(p->key);
13725         sm->value = (u8 *) (p->value[0]);
13726     }));
13727
13728     vec_sort_with_function (sort_me, macro_sort_cmp);
13729
13730     if (vec_len(sort_me))
13731         fformat (vam->ofp, "%-15s%s\n", "Name", "Value");
13732     else
13733         fformat (vam->ofp, "The macro table is empty...\n");
13734
13735     for (i = 0; i < vec_len (sort_me); i++)
13736         fformat (vam->ofp, "%-15s%s\n", sort_me[i].name,
13737                  sort_me[i].value);
13738     return 0;
13739 }
13740
13741 static int dump_node_table (vat_main_t * vam)
13742 {
13743     int i, j;
13744     vlib_node_t * node, * next_node;
13745
13746     if (vec_len (vam->graph_nodes) == 0) {
13747         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
13748         return 0;
13749     }
13750
13751     for (i = 0; i < vec_len (vam->graph_nodes); i++) {
13752         node = vam->graph_nodes[i];
13753         fformat (vam->ofp, "[%d] %s\n", i, node->name);
13754         for (j = 0; j < vec_len (node->next_nodes); j++) {
13755             if (node->next_nodes[j] != ~0) {
13756                 next_node = vam->graph_nodes[node->next_nodes[j]];
13757                 fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
13758             }
13759         }
13760     }
13761     return 0;
13762 }
13763
13764 static int search_node_table (vat_main_t * vam)
13765 {
13766     unformat_input_t * line_input = vam->input;
13767     u8 * node_to_find;
13768     int j;
13769     vlib_node_t * node, * next_node;
13770     uword * p;
13771
13772     if (vam->graph_node_index_by_name == 0) {
13773         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
13774         return 0;
13775     }
13776
13777     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
13778         if (unformat (line_input, "%s", &node_to_find)) {
13779             vec_add1 (node_to_find, 0);
13780             p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
13781             if (p == 0) {
13782                 fformat (vam->ofp, "%s not found...\n", node_to_find);
13783                 goto out;
13784             }
13785             node = vam->graph_nodes[p[0]];
13786             fformat (vam->ofp, "[%d] %s\n", p[0], node->name);
13787             for (j = 0; j < vec_len (node->next_nodes); j++) {
13788                 if (node->next_nodes[j] != ~0) {
13789                     next_node = vam->graph_nodes[node->next_nodes[j]];
13790                     fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
13791                 }
13792             }
13793         }
13794
13795         else {
13796             clib_warning ("parse error '%U'", format_unformat_error,
13797                           line_input);
13798             return -99;
13799         }
13800
13801     out:
13802         vec_free(node_to_find);
13803
13804     }
13805
13806     return 0;
13807 }
13808
13809
13810 static int script (vat_main_t * vam)
13811 {
13812     u8 * s = 0;
13813     char * save_current_file;
13814     unformat_input_t save_input;
13815     jmp_buf save_jump_buf;
13816     u32 save_line_number;
13817
13818     FILE * new_fp, * save_ifp;
13819
13820     if (unformat (vam->input, "%s", &s)) {
13821         new_fp = fopen ((char *)s, "r");
13822         if (new_fp == 0) {
13823             errmsg ("Couldn't open script file %s\n", s);
13824             vec_free (s);
13825             return -99;
13826         }
13827     } else {
13828         errmsg ("Missing script name\n");
13829         return -99;
13830     }
13831
13832     clib_memcpy (&save_input, &vam->input, sizeof (save_input));
13833     clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
13834     save_ifp = vam->ifp;
13835     save_line_number = vam->input_line_number;
13836     save_current_file = (char *) vam->current_file;
13837
13838     vam->input_line_number = 0;
13839     vam->ifp = new_fp;
13840     vam->current_file = s;
13841     do_one_file (vam);
13842
13843     clib_memcpy (&vam->input, &save_input, sizeof (vam->input));
13844     clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
13845     vam->ifp = save_ifp;
13846     vam->input_line_number = save_line_number;
13847     vam->current_file = (u8 *) save_current_file;
13848     vec_free (s);
13849
13850     return 0;
13851 }
13852
13853 static int echo (vat_main_t * vam)
13854 {
13855     fformat (vam->ofp, "%v", vam->input->buffer);
13856     return 0;
13857 }
13858
13859 /* List of API message constructors, CLI names map to api_xxx */
13860 #define foreach_vpe_api_msg                                             \
13861 _(create_loopback,"[mac <mac-addr>]")                                   \
13862 _(sw_interface_dump,"")                                                 \
13863 _(sw_interface_set_flags,                                               \
13864   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
13865 _(sw_interface_add_del_address,                                         \
13866   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
13867 _(sw_interface_set_table,                                               \
13868   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
13869 _(sw_interface_set_vpath,                                               \
13870   "<intfc> | sw_if_index <id> enable | disable")                        \
13871 _(sw_interface_set_l2_xconnect,                                         \
13872   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
13873   "enable | disable")                                                   \
13874 _(sw_interface_set_l2_bridge,                                           \
13875   "rx <intfc> | rx_sw_if_index <id> bd_id <bridge-domain-id>\n"         \
13876   "[shg <split-horizon-group>] [bvi]\n"                                 \
13877   "enable | disable")                                                   \
13878 _(bridge_domain_add_del,                                                \
13879   "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [del]\n")\
13880 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")     \
13881 _(l2fib_add_del,                                                        \
13882   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
13883 _(l2_flags,                                                             \
13884   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood]\n")       \
13885 _(bridge_flags,                                                         \
13886   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
13887 _(tap_connect,                                                          \
13888   "tapname <name> mac <mac-addr> | random-mac")                         \
13889 _(tap_modify,                                                           \
13890   "<vpp-if-name> | sw_if_index <id> tapname <name> mac <mac-addr> | random-mac") \
13891 _(tap_delete,                                                           \
13892   "<vpp-if-name> | sw_if_index <id>")                                   \
13893 _(sw_interface_tap_dump, "")                                            \
13894 _(ip_add_del_route,                                                     \
13895   "<addr>/<mask> via <addr> [vrf <n>]\n"                                \
13896   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
13897   "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
13898   "[multipath] [count <n>]")                                            \
13899 _(proxy_arp_add_del,                                                    \
13900   "<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]")                      \
13901 _(proxy_arp_intfc_enable_disable,                                       \
13902   "<intfc> | sw_if_index <id> enable | disable")                        \
13903 _(mpls_add_del_encap,                                                   \
13904   "label <n> dst <ip4-addr> [vrf <n>] [del]")                           \
13905 _(mpls_add_del_decap,                                                   \
13906   "label <n> [rx_vrf_id <n>] [tx_vrf_id] [s-bit-clear][del]")           \
13907 _(mpls_gre_add_del_tunnel,                                              \
13908   "inner_vrf_id <n> outer_vrf_id <n> src <ip4-address> dst <ip4-address>\n" \
13909   "adj <ip4-address>/<mask-width> [del]")                               \
13910 _(sw_interface_set_unnumbered,                                          \
13911   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
13912 _(ip_neighbor_add_del,                                                  \
13913   "(<intfc> | sw_if_index <id>) dst <ip46-address> "                    \
13914   "[mac <mac-addr>] [vrf <vrf-id>] [is_static] [del]")                  \
13915 _(reset_vrf, "vrf <id> [ipv6]")                                         \
13916 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
13917 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
13918   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
13919   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
13920   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
13921 _(oam_add_del, "src <ip4-address> dst <ip4-address> [vrf <n>] [del]")   \
13922 _(reset_fib, "vrf <n> [ipv6]")                                          \
13923 _(dhcp_proxy_config,                                                    \
13924   "svr <v46-address> src <v46-address>\n"                               \
13925    "insert-cid <n> [del]")                                              \
13926 _(dhcp_proxy_config_2,                                                  \
13927   "svr <v46-address> src <v46-address>\n"                               \
13928    "rx_vrf_id <nn> server_vrf_id <nn> insert-cid <n> [del]")            \
13929 _(dhcp_proxy_set_vss,                                                   \
13930   "tbl_id <n> fib_id <n> oui <n> [ipv6] [del]")                         \
13931 _(dhcp_client_config,                                                   \
13932   "<intfc> | sw_if_index <id> [hostname <name>] [disable_event] [del]") \
13933 _(set_ip_flow_hash,                                                     \
13934   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
13935 _(sw_interface_ip6_enable_disable,                                      \
13936   "<intfc> | sw_if_index <id> enable | disable")                        \
13937 _(sw_interface_ip6_set_link_local_address,                              \
13938   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>")              \
13939 _(sw_interface_ip6nd_ra_prefix,                                         \
13940   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>\n"             \
13941   "val_life <n> pref_life <n> [def] [noadv] [offl] [noauto]\n"          \
13942   "[nolink] [isno]")                                                    \
13943 _(sw_interface_ip6nd_ra_config,                                         \
13944   "<intfc> | sw_if_index <id> [maxint <n>] [minint <n>]\n"              \
13945   "[life <n>] [count <n>] [interval <n>] [suppress]\n"                  \
13946   "[managed] [other] [ll] [send] [cease] [isno] [def]")                 \
13947 _(set_arp_neighbor_limit, "arp_nbr_limit <n> [ipv6]")                   \
13948 _(l2_patch_add_del,                                                     \
13949   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
13950   "enable | disable")                                                   \
13951 _(mpls_ethernet_add_del_tunnel,                                         \
13952   "tx <intfc> | tx_sw_if_index <n> dst <mac-addr>\n"                    \
13953   "adj <ip4-addr>/<mw> dst <mac-addr> [del]")                           \
13954 _(mpls_ethernet_add_del_tunnel_2,                                       \
13955   "inner_vrf_id <n> outer_vrf_id <n> next-hop <ip4-addr>\n"             \
13956   "resolve-attempts <n> resolve-if-needed 0 | 1 [del]")                 \
13957 _(sr_tunnel_add_del,                                                    \
13958   "[name <name>] src <ip6-addr> dst <ip6-addr>/<mw> \n"                 \
13959   "(next <ip6-addr>)+ [tag <ip6-addr>]* [clean] [reroute] \n"           \
13960   "[policy <policy_name>]")                                             \
13961 _(sr_policy_add_del,                                                    \
13962   "name <name> tunnel <tunnel-name> [tunnel <tunnel-name>]* [del]")     \
13963 _(sr_multicast_map_add_del,                                             \
13964   "address [ip6 multicast address] sr-policy [policy name] [del]")      \
13965 _(classify_add_del_table,                                               \
13966   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
13967   "[del] mask <mask-value>\n"                                           \
13968   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>")              \
13969 _(classify_add_del_session,                                             \
13970   "[hit-next|l2-hit-next|acl-hit-next|policer-hit-next] <name|nn>\n"    \
13971   "  table-index <nn> skip_n <nn> match_n <nn> match [hex] [l2]\n"      \
13972   "  [l3 [ip4|ip6]]")                                                   \
13973 _(classify_set_interface_ip_table,                                      \
13974   "<intfc> | sw_if_index <nn> table <nn>")                              \
13975 _(classify_set_interface_l2_tables,                                     \
13976   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
13977   "  [other-table <nn>]")                                               \
13978 _(get_node_index, "node <node-name")                                    \
13979 _(add_node_next, "node <node-name> next <next-node-name>")              \
13980 _(l2tpv3_create_tunnel,                                                 \
13981   "client_address <ip6-addr> our_address <ip6-addr>\n"                  \
13982   "[local_session_id <nn>][remote_session_id <nn>][local_cookie <nn>]\n"\
13983   "[remote_cookie <nn>]\n[l2-sublayer-preset]\n")                       \
13984 _(l2tpv3_set_tunnel_cookies,                                            \
13985   "<intfc> | sw_if_index <nn> [new_local_cookie <nn>]\n"                \
13986   "[new_remote_cookie <nn>]\n")                                         \
13987 _(l2tpv3_interface_enable_disable,                                      \
13988   "<intfc> | sw_if_index <nn> enable | disable")                        \
13989 _(l2tpv3_set_lookup_key,                                                \
13990   "lookup_v6_src | lookup_v6_dst | lookup_session_id")                  \
13991 _(sw_if_l2tpv3_tunnel_dump, "")                                         \
13992 _(vxlan_add_del_tunnel,                                                 \
13993   "src <ip-addr> dst <ip-addr> vni <vni> [encap-vrf-id <nn>]\n"         \
13994   " [decap-next l2|ip4|ip6] [del]")                                     \
13995 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
13996 _(gre_add_del_tunnel,                                                   \
13997   "src <ip4-addr> dst <ip4-addr> [outer-fib-id <nn>] [del]\n")          \
13998 _(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                      \
13999 _(l2_fib_clear_table, "")                                               \
14000 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
14001 _(l2_interface_vlan_tag_rewrite,                                        \
14002   "<intfc> | sw_if_index <nn> \n"                                       \
14003   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
14004   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
14005 _(create_vhost_user_if,                                                 \
14006         "socket <filename> [server] [renumber <dev_instance>] "         \
14007         "[mac <mac_address>]")                                          \
14008 _(modify_vhost_user_if,                                                 \
14009         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
14010         "[server] [renumber <dev_instance>]")                           \
14011 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
14012 _(sw_interface_vhost_user_dump, "")                                     \
14013 _(show_version, "")                                                     \
14014 _(vxlan_gpe_add_del_tunnel,                                             \
14015   "local <addr> remote <addr> vni <nn>\n"                               \
14016     "[encap-vrf-id <nn>] [decap-vrf-id <nn>] [next-ip4][next-ip6]"      \
14017   "[next-ethernet] [next-nsh]\n")                                       \
14018 _(vxlan_gpe_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                \
14019 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
14020 _(interface_name_renumber,                                              \
14021   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
14022 _(input_acl_set_interface,                                              \
14023   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
14024   "  [l2-table <nn>] [del]")                                            \
14025 _(want_ip4_arp_events, "address <ip4-address> [del]")                   \
14026 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
14027 _(ip_dump, "ipv4 | ipv6")                                               \
14028 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
14029 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
14030   "  spid_id <n> ")                                                     \
14031 _(ipsec_sad_add_del_entry, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
14032   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
14033   "  integ_alg <alg> integ_key <hex>")                                  \
14034 _(ipsec_spd_add_del_entry, "spd_id <n> priority <n> action <action>\n"  \
14035   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
14036   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
14037   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" )\
14038 _(ipsec_sa_set_key, "sa_id <n> crypto_key <hex> integ_key <hex>")       \
14039 _(ikev2_profile_add_del, "name <profile_name> [del]")                   \
14040 _(ikev2_profile_set_auth, "name <profile_name> auth_method <method>\n"  \
14041   "(auth_data 0x<data> | auth_data <data>)")                            \
14042 _(ikev2_profile_set_id, "name <profile_name> id_type <type>\n"          \
14043   "(id_data 0x<data> | id_data <data>) (local|remote)")                 \
14044 _(ikev2_profile_set_ts, "name <profile_name> protocol <proto>\n"        \
14045   "start_port <port> end_port <port> start_addr <ip4> end_addr <ip4>\n" \
14046   "(local|remote)")                                                     \
14047 _(ikev2_set_local_key, "file <absolute_file_path>")                     \
14048 _(delete_loopback,"sw_if_index <nn>")                                   \
14049 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
14050 _(map_add_domain,                                                       \
14051   "ip4-pfx <ip4pfx> ip6-pfx <ip6pfx> "                                  \
14052   "ip6-src <ip6addr> "                                                  \
14053   "ea-bits-len <n> psid-offset <n> psid-len <n>")                       \
14054 _(map_del_domain, "index <n>")                                          \
14055 _(map_add_del_rule,                                                     \
14056   "index <n> psid <n> dst <ip6addr> [del]")                             \
14057 _(map_domain_dump, "")                                                  \
14058 _(map_rule_dump, "index <map-domain>")                                  \
14059 _(want_interface_events,  "enable|disable")                             \
14060 _(want_stats,"enable|disable")                                          \
14061 _(get_first_msg_id, "client <name>")                                    \
14062 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
14063 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
14064   "fib-id <nn> [ip4][ip6][default]")                                    \
14065 _(get_node_graph, " ")                                                  \
14066 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
14067 _(trace_profile_add, "id <nn> trace-type <0x1f|0x3|0x9|0x11|0x19> "     \
14068   "trace-elts <nn> trace-tsp <0|1|2|3> node-id <node id in hex> "       \
14069   "app-data <app_data in hex> [pow] [ppc <encap|decap>]")               \
14070 _(trace_profile_apply, "id <nn> <ip6-address>/<width>"                  \
14071   " vrf_id <nn>  add | pop | none")                                     \
14072 _(trace_profile_del, "")                                                \
14073 _(lisp_add_del_locator_set, "locator-set <locator_name> [iface <intf> |"\
14074                             " sw_if_index <sw_if_index> p <priority> "  \
14075                             "w <weight>] [del]")                        \
14076 _(lisp_add_del_locator, "locator-set <locator_name> "                   \
14077                         "iface <intf> | sw_if_index <sw_if_index> "     \
14078                         "p <priority> w <weight> [del]")                \
14079 _(lisp_add_del_local_eid,"vni <vni> eid "                               \
14080                          "<ipv4|ipv6>/<prefix> | <L2 address> "         \
14081                           "locator-set <locator_name> [del]")           \
14082 _(lisp_gpe_add_del_fwd_entry, "rmt_eid <eid> [lcl_eid <eid>] vni <vni>" \
14083   "dp_table <table> loc-pair <lcl_loc> <rmt_loc> ... [del]")            \
14084 _(lisp_add_del_map_resolver, "<ip4|6-addr> [del]")                      \
14085 _(lisp_gpe_enable_disable, "enable|disable")                            \
14086 _(lisp_enable_disable, "enable|disable")                                \
14087 _(lisp_gpe_add_del_iface, "up|down")                                    \
14088 _(lisp_add_del_remote_mapping, "add|del vni <vni> deid <dest-eid> "     \
14089                                "rloc <locator> p <prio> "               \
14090                                "w <weight> [rloc <loc> ... ] "          \
14091                                "action <action> [del-all]")             \
14092 _(lisp_add_del_adjacency, "add|del vni <vni> deid <dest-eid> seid "     \
14093                           "<src-eid> rloc <locator> p <prio> w <weight>"\
14094                           "[rloc <loc> ... ] action <action>")          \
14095 _(lisp_pitr_set_locator_set, "locator-set <loc-set-name> | del")        \
14096 _(lisp_add_del_map_request_itr_rlocs, "<loc-set-name> [del]")           \
14097 _(lisp_eid_table_add_del_map, "[del] vni <vni> vrf <vrf>")              \
14098 _(lisp_locator_set_dump, "[locator-set-index <ls-index> | "             \
14099                          "locator-set <loc-set-name>] [local | remote]")\
14100 _(lisp_eid_table_dump, "[eid <ipv4|ipv6>/<prefix> | <mac>] [vni] "      \
14101                        "[local] | [remote]")                            \
14102 _(lisp_eid_table_map_dump, "")                                          \
14103 _(lisp_gpe_tunnel_dump, "")                                             \
14104 _(lisp_map_resolver_dump, "")                                           \
14105 _(show_lisp_status, "")                                                 \
14106 _(lisp_get_map_request_itr_rlocs, "")                                   \
14107 _(show_lisp_pitr, "")                                                   \
14108 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
14109 _(af_packet_delete, "name <host interface name>")                       \
14110 _(policer_add_del, "name <policer name> <params> [del]")                \
14111 _(policer_dump, "[name <policer name>]")                                \
14112 _(policer_classify_set_interface,                                       \
14113   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
14114   "  [l2-table <nn>] [del]")                                            \
14115 _(policer_classify_dump, "type [ip4|ip6|l2]")                           \
14116 _(netmap_create, "name <interface name> [hw-addr <mac>] [pipe] "        \
14117     "[master|slave]")                                                   \
14118 _(netmap_delete, "name <interface name>")                               \
14119 _(mpls_gre_tunnel_dump, "tunnel_index <tunnel-id>")                     \
14120 _(mpls_eth_tunnel_dump, "tunnel_index <tunnel-id>")                     \
14121 _(mpls_fib_encap_dump, "")                                              \
14122 _(mpls_fib_decap_dump, "")                                              \
14123 _(classify_table_ids, "")                                               \
14124 _(classify_table_by_interface, "sw_if_index <sw_if_index>")             \
14125 _(classify_table_info, "table_id <nn>")                                 \
14126 _(classify_session_dump, "table_id <nn>")                               \
14127 _(ipfix_enable, "collector_address <ip4> [collector_port <nn>] "        \
14128                 "src_address <ip4> [fib_id <nn>] [path_mtu <nn>] "      \
14129                 "[template_interval <nn>]")                             \
14130 _(ipfix_dump, "")                                                       \
14131 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
14132 _(pg_create_interface, "if_id <nn>")                                    \
14133 _(pg_capture, "if_id <nnn> pcap <file_name> count <nnn> [disable]")     \
14134 _(pg_enable_disable, "[stream <id>] disable")                           \
14135 _(ip_source_and_port_range_check_add_del,                               \
14136   "<ip-addr>/<mask> range <nn>-<nn> vrf <id>")                          \
14137 _(ip_source_and_port_range_check_interface_add_del,                     \
14138   "<intf> | sw_if_index <nn> vrf <id>")
14139
14140 /* List of command functions, CLI names map directly to functions */
14141 #define foreach_cli_function                                    \
14142 _(comment, "usage: comment <ignore-rest-of-line>")              \
14143 _(dump_interface_table, "usage: dump_interface_table")          \
14144 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
14145 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
14146 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
14147 _(dump_stats_table, "usage: dump_stats_table")                  \
14148 _(dump_macro_table, "usage: dump_macro_table ")                 \
14149 _(dump_node_table, "usage: dump_node_table")                    \
14150 _(echo, "usage: echo <message>")                                \
14151 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
14152 _(help, "usage: help")                                          \
14153 _(q, "usage: quit")                                             \
14154 _(quit, "usage: quit")                                          \
14155 _(search_node_table, "usage: search_node_table <name>...")      \
14156 _(set, "usage: set <variable-name> <value>")                    \
14157 _(script, "usage: script <file-name>")                          \
14158 _(unset, "usage: unset <variable-name>")
14159
14160 #define _(N,n)                                  \
14161     static void vl_api_##n##_t_handler_uni      \
14162     (vl_api_##n##_t * mp)                       \
14163     {                                           \
14164         vat_main_t * vam = &vat_main;           \
14165         if (vam->json_output) {                 \
14166             vl_api_##n##_t_handler_json(mp);    \
14167         } else {                                \
14168             vl_api_##n##_t_handler(mp);         \
14169         }                                       \
14170     }
14171 foreach_vpe_api_reply_msg;
14172 #undef _
14173
14174 void vat_api_hookup (vat_main_t *vam)
14175 {
14176 #define _(N,n)                                                  \
14177     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
14178                            vl_api_##n##_t_handler_uni,          \
14179                            vl_noop_handler,                     \
14180                            vl_api_##n##_t_endian,               \
14181                            vl_api_##n##_t_print,                \
14182                            sizeof(vl_api_##n##_t), 1);
14183     foreach_vpe_api_reply_msg;
14184 #undef _
14185
14186     vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
14187
14188     vam->sw_if_index_by_interface_name =
14189         hash_create_string (0, sizeof (uword));
14190
14191     vam->function_by_name =
14192         hash_create_string (0, sizeof(uword));
14193
14194     vam->help_by_name =
14195         hash_create_string (0, sizeof(uword));
14196
14197     /* API messages we can send */
14198 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
14199     foreach_vpe_api_msg;
14200 #undef _
14201
14202     /* Help strings */
14203 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
14204     foreach_vpe_api_msg;
14205 #undef _
14206
14207     /* CLI functions */
14208 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
14209     foreach_cli_function;
14210 #undef _
14211
14212     /* Help strings */
14213 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
14214     foreach_cli_function;
14215 #undef _
14216 }
14217
14218 #undef vl_api_version
14219 #define vl_api_version(n,v) static u32 vpe_api_version = v;
14220 #include <vpp-api/vpe.api.h>
14221 #undef vl_api_version
14222
14223 void vl_client_add_api_signatures (vl_api_memclnt_create_t *mp)
14224 {
14225     /*
14226      * Send the main API signature in slot 0. This bit of code must
14227      * match the checks in ../vpe/api/api.c: vl_msg_api_version_check().
14228      */
14229     mp->api_versions[0] = clib_host_to_net_u32 (vpe_api_version);
14230 }