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