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