Add vxlan-gpe tunnel to sw_interface_dump
[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
3120     /* and vxlan-gpe tunnel interfaces */
3121     M(SW_INTERFACE_DUMP, sw_interface_dump);
3122     mp->name_filter_valid = 1;
3123     strncpy ((char *) mp->name_filter, "vxlan_gpe", sizeof(mp->name_filter)-1);
3124     S;
3125
3126     /* and vxlan tunnel interfaces */
3127     M(SW_INTERFACE_DUMP, sw_interface_dump);
3128     mp->name_filter_valid = 1;
3129     strncpy ((char *) mp->name_filter, "vxlan", sizeof(mp->name_filter)-1);
3130     S;
3131
3132     /* and host (af_packet) interfaces */
3133     M(SW_INTERFACE_DUMP, sw_interface_dump);
3134     mp->name_filter_valid = 1;
3135     strncpy ((char *) mp->name_filter, "host", sizeof(mp->name_filter)-1);
3136     S;
3137
3138     /* and l2tpv3 tunnel interfaces */
3139     M(SW_INTERFACE_DUMP, sw_interface_dump);
3140     mp->name_filter_valid = 1;
3141     strncpy ((char *) mp->name_filter, "l2tpv3_tunnel", sizeof(mp->name_filter)-1);
3142     S;
3143
3144     /* and GRE tunnel interfaces */
3145     M(SW_INTERFACE_DUMP, sw_interface_dump);
3146     mp->name_filter_valid = 1;
3147     strncpy ((char *) mp->name_filter, "gre", sizeof(mp->name_filter)-1);
3148     S;
3149
3150     /* Use a control ping for synchronization */
3151     {
3152         vl_api_control_ping_t * mp;
3153         M(CONTROL_PING, control_ping);
3154         S;
3155     }
3156     W;
3157 }
3158
3159 static int api_sw_interface_set_flags (vat_main_t * vam)
3160 {
3161     unformat_input_t * i = vam->input;
3162     vl_api_sw_interface_set_flags_t *mp;
3163     f64 timeout;
3164     u32 sw_if_index;
3165     u8 sw_if_index_set = 0;
3166     u8 admin_up = 0, link_up = 0;
3167     
3168     /* Parse args required to build the message */
3169     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3170         if (unformat (i, "admin-up"))
3171             admin_up = 1;
3172         else if (unformat (i, "admin-down"))
3173             admin_up = 0;
3174         else if (unformat (i, "link-up"))
3175             link_up = 1;
3176         else if (unformat (i, "link-down"))
3177             link_up = 0;
3178         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3179             sw_if_index_set = 1;
3180         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3181             sw_if_index_set = 1;
3182         else
3183             break;
3184     }
3185
3186     if (sw_if_index_set == 0) {
3187         errmsg ("missing interface name or sw_if_index\n");
3188         return -99;
3189     }
3190
3191     /* Construct the API message */
3192     M(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags);
3193     mp->sw_if_index = ntohl (sw_if_index);
3194     mp->admin_up_down = admin_up;
3195     mp->link_up_down = link_up;
3196
3197     /* send it... */
3198     S;
3199
3200     /* Wait for a reply, return the good/bad news... */
3201     W;
3202 }
3203
3204 static int api_sw_interface_clear_stats (vat_main_t * vam)
3205 {
3206     unformat_input_t * i = vam->input;
3207     vl_api_sw_interface_clear_stats_t *mp;
3208     f64 timeout;
3209     u32 sw_if_index;
3210     u8 sw_if_index_set = 0;
3211
3212     /* Parse args required to build the message */
3213     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3214         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3215             sw_if_index_set = 1;
3216         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3217             sw_if_index_set = 1;
3218         else
3219             break;
3220     }
3221
3222     /* Construct the API message */
3223     M(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats);
3224
3225     if (sw_if_index_set == 1)
3226         mp->sw_if_index = ntohl (sw_if_index);
3227     else
3228         mp->sw_if_index = ~0;
3229
3230     /* send it... */
3231     S;
3232
3233     /* Wait for a reply, return the good/bad news... */
3234     W;
3235 }
3236
3237 static int api_sw_interface_add_del_address (vat_main_t * vam)
3238 {
3239     unformat_input_t * i = vam->input;
3240     vl_api_sw_interface_add_del_address_t *mp;
3241     f64 timeout;
3242     u32 sw_if_index;
3243     u8 sw_if_index_set = 0;
3244     u8 is_add = 1, del_all = 0;
3245     u32 address_length = 0;
3246     u8 v4_address_set = 0;
3247     u8 v6_address_set = 0;
3248     ip4_address_t v4address;
3249     ip6_address_t v6address;
3250     
3251     /* Parse args required to build the message */
3252     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3253         if (unformat (i, "del-all"))
3254             del_all = 1;
3255         else if (unformat (i, "del"))
3256             is_add = 0;
3257         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3258             sw_if_index_set = 1;
3259         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3260             sw_if_index_set = 1;
3261         else if (unformat (i, "%U/%d", 
3262                            unformat_ip4_address, &v4address, 
3263                            &address_length))
3264             v4_address_set = 1;
3265         else if (unformat (i, "%U/%d", 
3266                            unformat_ip6_address, &v6address, 
3267                            &address_length))
3268             v6_address_set = 1;
3269         else
3270             break;
3271     }
3272
3273     if (sw_if_index_set == 0) {
3274         errmsg ("missing interface name or sw_if_index\n");
3275         return -99;
3276     }
3277     if (v4_address_set && v6_address_set) {
3278         errmsg ("both v4 and v6 addresses set\n");
3279         return -99;
3280     }
3281     if (!v4_address_set && !v6_address_set && !del_all) {
3282         errmsg ("no addresses set\n");
3283         return -99;
3284     }
3285
3286     /* Construct the API message */
3287     M(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address);
3288
3289     mp->sw_if_index = ntohl (sw_if_index);
3290     mp->is_add = is_add;
3291     mp->del_all = del_all;
3292     if (v6_address_set) {
3293         mp->is_ipv6 = 1;
3294         clib_memcpy (mp->address, &v6address, sizeof (v6address));
3295     } else {
3296         clib_memcpy (mp->address, &v4address, sizeof (v4address));
3297     }
3298     mp->address_length = address_length;
3299
3300     /* send it... */
3301     S;
3302
3303     /* Wait for a reply, return good/bad news  */
3304     W;
3305 }
3306
3307 static int api_sw_interface_set_table (vat_main_t * vam)
3308 {
3309     unformat_input_t * i = vam->input;
3310     vl_api_sw_interface_set_table_t *mp;
3311     f64 timeout;
3312     u32 sw_if_index, vrf_id = 0;
3313     u8 sw_if_index_set = 0;
3314     u8 is_ipv6 = 0;
3315     
3316     /* Parse args required to build the message */
3317     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3318         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3319             sw_if_index_set = 1;
3320         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3321             sw_if_index_set = 1;
3322         else if (unformat (i, "vrf %d", &vrf_id))
3323             ;
3324         else if (unformat (i, "ipv6"))
3325             is_ipv6 = 1;
3326         else
3327             break;
3328     }
3329
3330     if (sw_if_index_set == 0) {
3331         errmsg ("missing interface name or sw_if_index\n");
3332         return -99;
3333     }
3334
3335     /* Construct the API message */
3336     M(SW_INTERFACE_SET_TABLE, sw_interface_set_table);
3337
3338     mp->sw_if_index = ntohl (sw_if_index);
3339     mp->is_ipv6 = is_ipv6;
3340     mp->vrf_id = ntohl (vrf_id);
3341
3342     /* send it... */
3343     S;
3344
3345     /* Wait for a reply... */
3346     W;
3347 }
3348
3349 static int api_sw_interface_set_vpath (vat_main_t * vam)
3350 {
3351     unformat_input_t * i = vam->input;
3352     vl_api_sw_interface_set_vpath_t *mp;
3353     f64 timeout;
3354     u32 sw_if_index = 0;
3355     u8 sw_if_index_set = 0;
3356     u8 is_enable = 0;
3357     
3358     /* Parse args required to build the message */
3359     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3360         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3361             sw_if_index_set = 1;
3362         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3363             sw_if_index_set = 1;
3364         else if (unformat (i, "enable"))
3365             is_enable = 1;
3366         else if (unformat (i, "disable"))
3367             is_enable = 0;
3368         else
3369             break;
3370     }
3371
3372     if (sw_if_index_set == 0) {
3373         errmsg ("missing interface name or sw_if_index\n");
3374         return -99;
3375     }
3376
3377     /* Construct the API message */
3378     M(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath);
3379
3380     mp->sw_if_index = ntohl (sw_if_index);
3381     mp->enable = is_enable;
3382
3383     /* send it... */
3384     S;
3385
3386     /* Wait for a reply... */
3387     W;
3388 }
3389
3390 static int api_sw_interface_set_l2_xconnect (vat_main_t * vam)
3391 {
3392     unformat_input_t * i = vam->input;
3393     vl_api_sw_interface_set_l2_xconnect_t *mp;
3394     f64 timeout;
3395     u32 rx_sw_if_index;
3396     u8 rx_sw_if_index_set = 0;
3397     u32 tx_sw_if_index;
3398     u8 tx_sw_if_index_set = 0;
3399     u8 enable = 1;
3400     
3401     /* Parse args required to build the message */
3402     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3403         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
3404             rx_sw_if_index_set = 1;     
3405         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
3406             tx_sw_if_index_set = 1;
3407         else if (unformat (i, "rx")) {
3408             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3409                 if (unformat (i, "%U", unformat_sw_if_index, vam,
3410                               &rx_sw_if_index))
3411                     rx_sw_if_index_set = 1;
3412             } else
3413                 break;
3414         } else if (unformat (i, "tx")) {
3415             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3416                 if (unformat (i, "%U", unformat_sw_if_index, vam,
3417                               &tx_sw_if_index))
3418                     tx_sw_if_index_set = 1;
3419             } else
3420                 break;
3421         } else if (unformat (i, "enable"))
3422             enable = 1;
3423         else if (unformat (i, "disable")) 
3424             enable = 0;
3425         else
3426             break;
3427     }
3428
3429     if (rx_sw_if_index_set == 0) {
3430         errmsg ("missing rx interface name or rx_sw_if_index\n");
3431         return -99;
3432     }
3433
3434     if (enable && (tx_sw_if_index_set == 0)) {
3435         errmsg ("missing tx interface name or tx_sw_if_index\n");
3436         return -99;
3437     }
3438     
3439     M(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect);
3440
3441     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
3442     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
3443     mp->enable = enable;
3444
3445     S; W;
3446     /* NOTREACHED */
3447     return 0;
3448 }
3449
3450 static int api_sw_interface_set_l2_bridge (vat_main_t * vam)
3451 {
3452     unformat_input_t * i = vam->input;
3453     vl_api_sw_interface_set_l2_bridge_t *mp;
3454     f64 timeout;
3455     u32 rx_sw_if_index;
3456     u8 rx_sw_if_index_set = 0;
3457     u32 bd_id;
3458     u8 bd_id_set = 0;
3459     u8 bvi = 0;
3460     u32 shg = 0;
3461     u8 enable = 1;
3462     
3463     /* Parse args required to build the message */
3464     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3465         if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
3466             rx_sw_if_index_set = 1;     
3467         else if (unformat (i, "bd_id %d", &bd_id))
3468             bd_id_set = 1;
3469         else if (unformat (i, "%U", unformat_sw_if_index, vam,
3470                            &rx_sw_if_index))
3471             rx_sw_if_index_set = 1;
3472         else if (unformat (i, "shg %d", &shg)) 
3473             ;
3474         else if (unformat (i, "bvi"))
3475             bvi = 1;
3476         else if (unformat (i, "enable"))
3477             enable = 1;
3478         else if (unformat (i, "disable")) 
3479             enable = 0;
3480         else
3481             break;
3482     }
3483
3484     if (rx_sw_if_index_set == 0) {
3485         errmsg ("missing rx interface name or sw_if_index\n");
3486         return -99;
3487     }
3488
3489     if (enable && (bd_id_set == 0)) {
3490         errmsg ("missing bridge domain\n");
3491         return -99;
3492     }
3493     
3494     M(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge);
3495
3496     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
3497     mp->bd_id = ntohl(bd_id);
3498     mp->shg = (u8)shg;
3499     mp->bvi = bvi;
3500     mp->enable = enable;
3501
3502     S; W;
3503     /* NOTREACHED */
3504     return 0;
3505 }
3506
3507 static int api_bridge_domain_dump (vat_main_t * vam)
3508 {
3509     unformat_input_t * i = vam->input;
3510     vl_api_bridge_domain_dump_t *mp;
3511     f64 timeout;
3512     u32 bd_id = ~0;
3513
3514     /* Parse args required to build the message */
3515     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3516         if (unformat (i, "bd_id %d", &bd_id))
3517             ;
3518         else
3519             break;
3520     }
3521
3522     M(BRIDGE_DOMAIN_DUMP, bridge_domain_dump);
3523     mp->bd_id = ntohl(bd_id);
3524     S;
3525
3526     /* Use a control ping for synchronization */
3527     {
3528         vl_api_control_ping_t * mp;
3529         M(CONTROL_PING, control_ping);
3530         S;
3531     }
3532
3533     W;
3534     /* NOTREACHED */
3535     return 0;
3536 }
3537
3538 static int api_bridge_domain_add_del (vat_main_t * vam)
3539 {
3540     unformat_input_t * i = vam->input;
3541     vl_api_bridge_domain_add_del_t *mp;
3542     f64 timeout;
3543     u32 bd_id = ~0;
3544     u8 is_add = 1;
3545     u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
3546
3547     /* Parse args required to build the message */
3548     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3549         if (unformat (i, "bd_id %d", &bd_id))
3550             ;
3551         else if (unformat (i, "flood %d", &flood))
3552              ;
3553         else if (unformat (i, "uu-flood %d", &uu_flood))
3554              ;
3555         else if (unformat (i, "forward %d", &forward))
3556              ;
3557         else if (unformat (i, "learn %d", &learn))
3558              ;
3559         else if (unformat (i, "arp-term %d", &arp_term))
3560              ;
3561         else if (unformat (i, "del")) {
3562              is_add = 0;
3563              flood = uu_flood = forward = learn = 0;
3564         }
3565         else
3566             break;
3567     }
3568
3569     if (bd_id == ~0) {
3570         errmsg ("missing bridge domain\n");
3571         return -99;
3572     }
3573
3574     M(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del);
3575
3576     mp->bd_id = ntohl(bd_id);
3577     mp->flood = flood;
3578     mp->uu_flood = uu_flood;
3579     mp->forward = forward;
3580     mp->learn = learn;
3581     mp->arp_term = arp_term;
3582     mp->is_add = is_add;
3583
3584     S; W;
3585     /* NOTREACHED */
3586     return 0;
3587 }
3588
3589 static int api_l2fib_add_del (vat_main_t * vam)
3590 {
3591     unformat_input_t * i = vam->input;
3592     vl_api_l2fib_add_del_t *mp;
3593     f64 timeout;
3594     u64 mac = 0;
3595     u8 mac_set = 0;
3596     u32 bd_id;
3597     u8 bd_id_set = 0;
3598     u32 sw_if_index;
3599     u8 sw_if_index_set = 0;
3600     u8 is_add = 1;
3601     u8 static_mac = 0;
3602     u8 filter_mac = 0;
3603
3604     /* Parse args required to build the message */
3605     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3606         if (unformat (i, "mac %U", unformat_ethernet_address, &mac))
3607             mac_set = 1;
3608         else if (unformat (i, "bd_id %d", &bd_id))
3609             bd_id_set = 1;
3610         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3611             sw_if_index_set = 1;        
3612         else if (unformat (i, "sw_if")) {
3613             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3614                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3615                     sw_if_index_set = 1;
3616             } else
3617                 break;
3618         } else if (unformat (i, "static"))
3619                 static_mac = 1;
3620         else if (unformat (i, "filter")) {
3621                 filter_mac = 1;
3622                 static_mac = 1;
3623         } else if (unformat (i, "del"))
3624                 is_add = 0;
3625         else
3626             break;
3627     }
3628
3629     if (mac_set == 0) {
3630         errmsg ("missing mac address\n");
3631         return -99;
3632     }
3633
3634     if (bd_id_set == 0) {
3635         errmsg ("missing bridge domain\n");
3636         return -99;
3637     }
3638
3639     if (is_add && (sw_if_index_set == 0)) {
3640         errmsg ("missing interface name or sw_if_index\n");
3641         return -99;
3642     }
3643
3644     M(L2FIB_ADD_DEL, l2fib_add_del);
3645
3646     mp->mac = mac;
3647     mp->bd_id = ntohl(bd_id);
3648     mp->is_add = is_add;
3649
3650     if (is_add) {
3651         mp->sw_if_index = ntohl(sw_if_index);
3652         mp->static_mac = static_mac;
3653         mp->filter_mac = filter_mac;
3654     }
3655     
3656     S; W;
3657     /* NOTREACHED */
3658     return 0;
3659 }
3660
3661 static int api_l2_flags (vat_main_t * vam)
3662 {
3663     unformat_input_t * i = vam->input;
3664     vl_api_l2_flags_t *mp;
3665     f64 timeout;
3666     u32 sw_if_index;
3667     u32 feature_bitmap = 0;
3668     u8 sw_if_index_set = 0;
3669
3670     /* Parse args required to build the message */
3671     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3672         if (unformat (i, "sw_if_index %d", &sw_if_index))
3673             sw_if_index_set = 1;        
3674         else if (unformat (i, "sw_if")) {
3675             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3676                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3677                     sw_if_index_set = 1;
3678             } else
3679                 break;
3680         } else if (unformat (i, "learn"))
3681             feature_bitmap |= L2INPUT_FEAT_LEARN;
3682         else if (unformat (i, "forward"))
3683             feature_bitmap |= L2INPUT_FEAT_FWD;
3684         else if (unformat (i, "flood"))
3685             feature_bitmap |= L2INPUT_FEAT_FLOOD;
3686         else if (unformat (i, "uu-flood"))
3687             feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
3688         else
3689             break;
3690     }
3691
3692     if (sw_if_index_set == 0) {
3693         errmsg ("missing interface name or sw_if_index\n");
3694         return -99;
3695     }
3696
3697     M(L2_FLAGS, l2_flags);
3698
3699     mp->sw_if_index = ntohl(sw_if_index);
3700     mp->feature_bitmap = ntohl(feature_bitmap);
3701
3702     S; W;
3703     /* NOTREACHED */
3704     return 0;
3705 }
3706
3707 static int api_bridge_flags (vat_main_t * vam)
3708 {
3709     unformat_input_t * i = vam->input;
3710     vl_api_bridge_flags_t *mp;
3711     f64 timeout;
3712     u32 bd_id;
3713     u8 bd_id_set = 0;
3714     u8 is_set = 1;
3715     u32 flags = 0;
3716
3717     /* Parse args required to build the message */
3718     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3719         if (unformat (i, "bd_id %d", &bd_id))
3720             bd_id_set = 1;
3721         else if (unformat (i, "learn"))
3722             flags |= L2_LEARN;
3723         else if (unformat (i, "forward"))
3724             flags |= L2_FWD;
3725         else if (unformat (i, "flood"))
3726             flags |= L2_FLOOD;
3727         else if (unformat (i, "uu-flood"))
3728             flags |= L2_UU_FLOOD;
3729         else if (unformat (i, "arp-term"))
3730             flags |= L2_ARP_TERM;
3731         else if (unformat (i, "off"))
3732             is_set = 0;
3733         else if (unformat (i, "disable"))
3734             is_set = 0;
3735         else
3736             break;
3737     }
3738
3739     if (bd_id_set == 0) {
3740         errmsg ("missing bridge domain\n");
3741         return -99;
3742     }
3743
3744     M(BRIDGE_FLAGS, bridge_flags);
3745
3746     mp->bd_id = ntohl(bd_id);
3747     mp->feature_bitmap = ntohl(flags);
3748     mp->is_set = is_set;
3749
3750     S; W;
3751     /* NOTREACHED */
3752     return 0;
3753 }
3754
3755 static int api_bd_ip_mac_add_del (vat_main_t * vam)
3756 {
3757     unformat_input_t * i = vam->input;
3758     vl_api_bd_ip_mac_add_del_t *mp;
3759     f64 timeout;
3760     u32 bd_id;
3761     u8 is_ipv6 = 0;
3762     u8 is_add = 1;
3763     u8 bd_id_set = 0;
3764     u8 ip_set = 0;
3765     u8 mac_set = 0;
3766     ip4_address_t v4addr;
3767     ip6_address_t v6addr;
3768     u8 macaddr[6];
3769     
3770
3771     /* Parse args required to build the message */
3772     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3773         if (unformat (i, "bd_id %d", &bd_id)) {
3774             bd_id_set++;
3775         } else if (unformat (i, "%U", unformat_ip4_address, &v4addr)) {
3776             ip_set++;
3777         } else if (unformat (i, "%U", unformat_ip6_address, &v6addr)) {
3778             ip_set++;
3779             is_ipv6++;
3780         } else if (unformat (i, "%U", unformat_ethernet_address, macaddr)) {
3781             mac_set++;
3782         } else if (unformat (i, "del"))
3783             is_add = 0;
3784         else
3785             break;
3786     }
3787
3788     if (bd_id_set == 0) {
3789         errmsg ("missing bridge domain\n");
3790         return -99;
3791     } else if (ip_set == 0) {
3792         errmsg ("missing IP address\n");
3793         return -99;
3794     } else if (mac_set == 0) {
3795         errmsg ("missing MAC address\n");
3796         return -99;
3797     }
3798
3799     M(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del);
3800
3801     mp->bd_id = ntohl(bd_id);
3802     mp->is_ipv6 = is_ipv6;
3803     mp->is_add = is_add;
3804     if (is_ipv6)
3805          clib_memcpy (mp->ip_address, &v6addr, sizeof (v6addr));
3806     else clib_memcpy (mp->ip_address, &v4addr, sizeof (v4addr));
3807     clib_memcpy (mp->mac_address, macaddr, 6);
3808     S; W;
3809     /* NOTREACHED */
3810     return 0;
3811 }
3812
3813 static int api_tap_connect (vat_main_t * vam)
3814 {
3815     unformat_input_t * i = vam->input;
3816     vl_api_tap_connect_t *mp;
3817     f64 timeout;
3818     u8 mac_address[6];
3819     u8 random_mac = 1;
3820     u8 name_set = 0;
3821     u8 * tap_name;
3822
3823     memset (mac_address, 0, sizeof (mac_address));
3824     
3825     /* Parse args required to build the message */
3826     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3827         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
3828             random_mac = 0;
3829         }
3830         else if (unformat (i, "random-mac"))
3831             random_mac = 1;
3832         else if (unformat (i, "tapname %s", &tap_name))
3833             name_set = 1;
3834         else
3835             break;
3836     }
3837
3838     if (name_set == 0) {
3839         errmsg ("missing tap name\n");
3840         return -99;
3841     }
3842     if (vec_len (tap_name) > 63) {
3843         errmsg ("tap name too long\n");
3844     }
3845     vec_add1 (tap_name, 0);
3846         
3847     /* Construct the API message */
3848     M(TAP_CONNECT, tap_connect);
3849
3850     mp->use_random_mac = random_mac;
3851     clib_memcpy (mp->mac_address, mac_address, 6);
3852     clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name));
3853     vec_free (tap_name);
3854
3855     /* send it... */
3856     S;
3857
3858     /* Wait for a reply... */
3859     W;
3860 }
3861
3862 static int api_tap_modify (vat_main_t * vam)
3863 {
3864     unformat_input_t * i = vam->input;
3865     vl_api_tap_modify_t *mp;
3866     f64 timeout;
3867     u8 mac_address[6];
3868     u8 random_mac = 1;
3869     u8 name_set = 0;
3870     u8 * tap_name;
3871     u32 sw_if_index = ~0;
3872     u8 sw_if_index_set = 0;
3873
3874     memset (mac_address, 0, sizeof (mac_address));
3875     
3876     /* Parse args required to build the message */
3877     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3878         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3879             sw_if_index_set = 1;
3880         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3881             sw_if_index_set = 1;
3882         else if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
3883             random_mac = 0;
3884         }
3885         else if (unformat (i, "random-mac"))
3886             random_mac = 1;
3887         else if (unformat (i, "tapname %s", &tap_name))
3888             name_set = 1;
3889         else
3890             break;
3891     }
3892
3893     if (sw_if_index_set == 0) {
3894         errmsg ("missing vpp interface name");
3895         return -99;
3896     }
3897     if (name_set == 0) {
3898         errmsg ("missing tap name\n");
3899         return -99;
3900     }
3901     if (vec_len (tap_name) > 63) {
3902         errmsg ("tap name too long\n");
3903     }
3904     vec_add1 (tap_name, 0);
3905         
3906     /* Construct the API message */
3907     M(TAP_MODIFY, tap_modify);
3908
3909     mp->use_random_mac = random_mac;
3910     mp->sw_if_index = ntohl(sw_if_index);
3911     clib_memcpy (mp->mac_address, mac_address, 6);
3912     clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name));
3913     vec_free (tap_name);
3914
3915     /* send it... */
3916     S;
3917
3918     /* Wait for a reply... */
3919     W;
3920 }
3921
3922 static int api_tap_delete (vat_main_t * vam)
3923 {
3924     unformat_input_t * i = vam->input;
3925     vl_api_tap_delete_t *mp;
3926     f64 timeout;
3927     u32 sw_if_index = ~0;
3928     u8 sw_if_index_set = 0;
3929
3930     /* Parse args required to build the message */
3931     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3932         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3933             sw_if_index_set = 1;
3934         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3935             sw_if_index_set = 1;
3936         else
3937             break;
3938     }
3939
3940     if (sw_if_index_set == 0) {
3941         errmsg ("missing vpp interface name");
3942         return -99;
3943     }
3944         
3945     /* Construct the API message */
3946     M(TAP_DELETE, tap_delete);
3947
3948     mp->sw_if_index = ntohl(sw_if_index);
3949
3950     /* send it... */
3951     S;
3952
3953     /* Wait for a reply... */
3954     W;
3955 }
3956
3957 static int api_ip_add_del_route (vat_main_t * vam)
3958 {
3959     unformat_input_t * i = vam->input;
3960     vl_api_ip_add_del_route_t *mp;
3961     f64 timeout;
3962     u32 sw_if_index = 0, vrf_id = 0;
3963     u8 sw_if_index_set = 0;
3964     u8 is_ipv6 = 0;
3965     u8 is_local = 0, is_drop = 0;
3966     u8 create_vrf_if_needed = 0;
3967     u8 is_add = 1;
3968     u8 next_hop_weight = 1;
3969     u8 not_last = 0;
3970     u8 is_multipath = 0;
3971     u8 address_set = 0;
3972     u8 address_length_set = 0;
3973     u32 lookup_in_vrf = 0;
3974     u32 resolve_attempts = 0;
3975     u32 dst_address_length = 0;
3976     u8 next_hop_set = 0;
3977     ip4_address_t v4_dst_address, v4_next_hop_address;
3978     ip6_address_t v6_dst_address, v6_next_hop_address;
3979     int count = 1;
3980     int j;
3981     f64 before = 0;
3982     u32 random_add_del = 0;
3983     u32 * random_vector = 0;
3984     uword * random_hash;
3985     u32 random_seed = 0xdeaddabe;
3986     u32 classify_table_index = ~0;
3987     u8 is_classify = 0;
3988     
3989     /* Parse args required to build the message */
3990     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3991         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3992             sw_if_index_set = 1;
3993         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3994             sw_if_index_set = 1;
3995         else if (unformat (i, "%U", unformat_ip4_address,
3996                            &v4_dst_address)) {
3997             address_set = 1;
3998             is_ipv6 = 0;
3999         }
4000         else if (unformat (i, "%U", unformat_ip6_address, &v6_dst_address)) {
4001             address_set = 1;
4002             is_ipv6 = 1;
4003         }
4004         else if (unformat (i, "/%d", &dst_address_length)) {
4005             address_length_set = 1;
4006         }
4007         
4008         else if (is_ipv6 == 0 && unformat (i, "via %U", unformat_ip4_address, 
4009                                            &v4_next_hop_address)) {
4010             next_hop_set = 1;
4011         }
4012         else if (is_ipv6 == 1 && unformat (i, "via %U", unformat_ip6_address, 
4013                                            &v6_next_hop_address)) {
4014             next_hop_set = 1;
4015         }
4016         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
4017             ;
4018         else if (unformat (i, "weight %d", &next_hop_weight))
4019             ;
4020         else if (unformat (i, "drop")) {
4021             is_drop = 1;
4022         } else if (unformat (i, "local")) {
4023             is_local = 1;
4024         } else if (unformat (i, "classify %d", &classify_table_index)) {
4025             is_classify = 1;
4026         } else if (unformat (i, "del"))
4027             is_add = 0;
4028         else if (unformat (i, "add"))
4029             is_add = 1;
4030         else if (unformat (i, "not-last"))
4031             not_last = 1;
4032         else if (unformat (i, "multipath"))
4033             is_multipath = 1;
4034         else if (unformat (i, "vrf %d", &vrf_id))
4035             ;
4036         else if (unformat (i, "create-vrf"))
4037             create_vrf_if_needed = 1;
4038         else if (unformat (i, "count %d", &count))
4039             ;
4040         else if (unformat (i, "lookup-in-vrf %d", &lookup_in_vrf))
4041             ;
4042         else if (unformat (i, "random"))
4043             random_add_del = 1;
4044         else if (unformat (i, "seed %d", &random_seed))
4045             ;
4046         else {
4047             clib_warning ("parse error '%U'", format_unformat_error, i);
4048             return -99;
4049         }
4050     }
4051
4052     if (resolve_attempts > 0 && sw_if_index_set == 0) {
4053         errmsg ("ARP resolution needs explicit interface or sw_if_index\n");
4054         return -99;
4055     }
4056     
4057     if (!next_hop_set && !is_drop && !is_local && !is_classify) {
4058         errmsg ("next hop / local / drop / classify not set\n");
4059         return -99;
4060     }
4061
4062     if (address_set == 0) {
4063         errmsg ("missing addresses\n");
4064         return -99;
4065     }
4066
4067     if (address_length_set == 0) {
4068         errmsg ("missing address length\n");
4069         return -99;
4070     }
4071     
4072     /* Generate a pile of unique, random routes */
4073     if (random_add_del) {
4074         u32 this_random_address;
4075         random_hash = hash_create (count, sizeof(uword));
4076
4077         hash_set (random_hash, v4_next_hop_address.as_u32, 1);
4078         for (j = 0; j <= count; j++) {
4079             do {
4080                 this_random_address = random_u32 (&random_seed);
4081                 this_random_address = 
4082                     clib_host_to_net_u32 (this_random_address);
4083             } while (hash_get (random_hash, this_random_address));
4084             vec_add1 (random_vector, this_random_address);
4085             hash_set (random_hash, this_random_address, 1);
4086         }
4087         hash_free (random_hash);
4088         v4_dst_address.as_u32 = random_vector[0];
4089     }
4090
4091     if (count > 1) {
4092         /* Turn on async mode */
4093         vam->async_mode = 1;
4094         vam->async_errors = 0;
4095         before = vat_time_now(vam);
4096     }
4097
4098     for (j = 0; j < count; j++) {
4099         /* Construct the API message */
4100         M(IP_ADD_DEL_ROUTE, ip_add_del_route);
4101     
4102         mp->next_hop_sw_if_index = ntohl (sw_if_index);
4103         mp->vrf_id = ntohl (vrf_id);
4104         if (resolve_attempts > 0) {
4105             mp->resolve_attempts = ntohl (resolve_attempts);
4106             mp->resolve_if_needed = 1;
4107         }
4108         mp->create_vrf_if_needed = create_vrf_if_needed;
4109     
4110         mp->is_add = is_add;
4111         mp->is_drop = is_drop;
4112         mp->is_ipv6 = is_ipv6;
4113         mp->is_local = is_local;
4114         mp->is_classify = is_classify;
4115         mp->is_multipath = is_multipath;
4116         mp->not_last = not_last;
4117         mp->next_hop_weight = next_hop_weight;
4118         mp->dst_address_length = dst_address_length;
4119         mp->lookup_in_vrf = ntohl(lookup_in_vrf);
4120         mp->classify_table_index = ntohl(classify_table_index);
4121
4122         if (is_ipv6){
4123             clib_memcpy (mp->dst_address, &v6_dst_address, sizeof (v6_dst_address));
4124             if (next_hop_set)
4125                 clib_memcpy (mp->next_hop_address, &v6_next_hop_address, 
4126                         sizeof (v6_next_hop_address));
4127             increment_v6_address (&v6_dst_address);
4128         } else {
4129             clib_memcpy (mp->dst_address, &v4_dst_address, sizeof (v4_dst_address));
4130             if (next_hop_set)
4131                 clib_memcpy (mp->next_hop_address, &v4_next_hop_address, 
4132                         sizeof (v4_next_hop_address));
4133             if (random_add_del)
4134                 v4_dst_address.as_u32 = random_vector[j+1];
4135             else
4136                 increment_v4_address (&v4_dst_address);
4137         }
4138         /* send it... */
4139         S;
4140     }
4141
4142     /* When testing multiple add/del ops, use a control-ping to sync */
4143     if (count > 1) {
4144         vl_api_control_ping_t * mp;
4145         f64 after;
4146
4147         /* Shut off async mode */
4148         vam->async_mode = 0;
4149
4150         M(CONTROL_PING, control_ping);
4151         S;
4152
4153         timeout = vat_time_now(vam) + 1.0;
4154         while (vat_time_now (vam) < timeout)
4155             if (vam->result_ready == 1)
4156                 goto out;
4157         vam->retval = -99;
4158
4159     out:
4160         if (vam->retval == -99)
4161             errmsg ("timeout\n");
4162
4163         if (vam->async_errors > 0) {
4164             errmsg ("%d asynchronous errors\n", vam->async_errors);
4165             vam->retval = -98;
4166         }
4167         vam->async_errors = 0;
4168         after = vat_time_now(vam);
4169
4170         fformat(vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
4171                 count, after - before, count / (after - before));
4172     } else {
4173         /* Wait for a reply... */
4174         W;
4175     }
4176
4177     /* Return the good/bad news */
4178     return (vam->retval);
4179 }
4180
4181 static int api_proxy_arp_add_del (vat_main_t * vam)
4182 {
4183     unformat_input_t * i = vam->input;
4184     vl_api_proxy_arp_add_del_t *mp;
4185     f64 timeout;
4186     u32 vrf_id = 0;
4187     u8 is_add = 1;
4188     ip4_address_t lo, hi;
4189     u8 range_set = 0;
4190
4191     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4192         if (unformat (i, "vrf %d", &vrf_id))
4193             ;
4194         else if (unformat (i, "%U - %U", unformat_ip4_address, &lo, 
4195                            unformat_ip4_address, &hi))
4196             range_set = 1;
4197         else if (unformat (i, "del"))
4198             is_add = 0;
4199         else {
4200             clib_warning ("parse error '%U'", format_unformat_error, i);
4201             return -99;
4202         }
4203     }
4204     
4205     if (range_set == 0) {
4206         errmsg ("address range not set\n");
4207         return -99;
4208     }
4209
4210     M(PROXY_ARP_ADD_DEL, proxy_arp_add_del);
4211
4212     mp->vrf_id = ntohl(vrf_id);
4213     mp->is_add = is_add;
4214     clib_memcpy(mp->low_address, &lo, sizeof (mp->low_address));
4215     clib_memcpy(mp->hi_address, &hi, sizeof (mp->hi_address));
4216
4217     S; W;
4218     /* NOTREACHED */
4219     return 0;
4220 }
4221
4222 static int api_proxy_arp_intfc_enable_disable (vat_main_t * vam)
4223 {
4224     unformat_input_t * i = vam->input;
4225     vl_api_proxy_arp_intfc_enable_disable_t *mp;
4226     f64 timeout;
4227     u32 sw_if_index;
4228     u8 enable = 1;
4229     u8 sw_if_index_set = 0;
4230
4231     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4232         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4233             sw_if_index_set = 1;
4234         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4235             sw_if_index_set = 1;
4236         else if (unformat (i, "enable"))
4237             enable = 1;
4238         else if (unformat (i, "disable"))
4239             enable = 0;
4240         else {
4241             clib_warning ("parse error '%U'", format_unformat_error, i);
4242             return -99;
4243         }
4244     }
4245     
4246     if (sw_if_index_set == 0) {
4247         errmsg ("missing interface name or sw_if_index\n");
4248         return -99;
4249     }
4250
4251     M(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable);
4252
4253     mp->sw_if_index = ntohl(sw_if_index);
4254     mp->enable_disable = enable;
4255
4256     S; W;
4257     /* NOTREACHED */
4258     return 0;
4259 }
4260
4261 static int api_mpls_add_del_decap (vat_main_t * vam)
4262 {
4263     unformat_input_t * i = vam->input;
4264     vl_api_mpls_add_del_decap_t *mp;
4265     f64 timeout;
4266     u32 rx_vrf_id = 0;
4267     u32 tx_vrf_id = 0;
4268     u32 label = 0;
4269     u8 is_add = 1;
4270     u8 s_bit = 1;
4271     u32 next_index = 1;
4272
4273     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4274         if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
4275             ;
4276         else if (unformat (i, "tx_vrf_id %d", &tx_vrf_id))
4277             ;
4278         else if (unformat (i, "label %d", &label))
4279             ;
4280         else if (unformat (i, "next-index %d", &next_index))
4281             ;
4282         else if (unformat (i, "del"))
4283             is_add = 0;
4284         else if (unformat (i, "s-bit-clear"))
4285             s_bit = 0;
4286         else {
4287             clib_warning ("parse error '%U'", format_unformat_error, i);
4288             return -99;
4289         }
4290     }
4291     
4292     M(MPLS_ADD_DEL_DECAP, mpls_add_del_decap);
4293
4294     mp->rx_vrf_id = ntohl(rx_vrf_id);
4295     mp->tx_vrf_id = ntohl(tx_vrf_id);
4296     mp->label = ntohl(label);
4297     mp->next_index = ntohl(next_index);
4298     mp->s_bit = s_bit;
4299     mp->is_add = is_add;
4300
4301     S; W;
4302     /* NOTREACHED */
4303     return 0;
4304 }
4305
4306 static int api_mpls_add_del_encap (vat_main_t * vam)
4307 {
4308     unformat_input_t * i = vam->input;
4309     vl_api_mpls_add_del_encap_t *mp;
4310     f64 timeout;
4311     u32 vrf_id = 0;
4312     u32 *labels = 0;
4313     u32 label;
4314     ip4_address_t dst_address;
4315     u8 is_add = 1;
4316
4317     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4318         if (unformat (i, "vrf %d", &vrf_id))
4319             ;
4320         else if (unformat (i, "label %d", &label))
4321             vec_add1 (labels, ntohl(label));
4322         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
4323             ;
4324         else if (unformat (i, "del"))
4325             is_add = 0;
4326         else {
4327             clib_warning ("parse error '%U'", format_unformat_error, i);
4328             return -99;
4329         }
4330     }
4331
4332     if (vec_len (labels) == 0) {
4333         errmsg ("missing encap label stack\n");
4334         return -99;
4335     }
4336     
4337     M2(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap, 
4338        sizeof (u32) * vec_len (labels));
4339
4340     mp->vrf_id = ntohl(vrf_id);
4341     clib_memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
4342     mp->is_add = is_add;
4343     mp->nlabels = vec_len (labels);
4344     clib_memcpy(mp->labels, labels, sizeof(u32)*mp->nlabels);
4345
4346     vec_free(labels);
4347
4348     S; W;
4349     /* NOTREACHED */
4350     return 0;
4351 }
4352
4353 static int api_mpls_gre_add_del_tunnel (vat_main_t * vam)
4354 {
4355     unformat_input_t * i = vam->input;
4356     vl_api_mpls_gre_add_del_tunnel_t *mp;
4357     f64 timeout;
4358     u32 inner_vrf_id = 0;
4359     u32 outer_vrf_id = 0;
4360     ip4_address_t src_address;
4361     ip4_address_t dst_address;
4362     ip4_address_t intfc_address;
4363     u32 tmp;
4364     u8 intfc_address_length = 0;
4365     u8 is_add = 1;
4366     u8 l2_only = 0;
4367     
4368     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4369         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
4370             ;
4371         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
4372             ;
4373         else if (unformat (i, "src %U", unformat_ip4_address, &src_address))
4374             ;
4375         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
4376             ;
4377         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
4378                            &intfc_address, &tmp))
4379             intfc_address_length = tmp;
4380         else if (unformat (i, "l2-only"))
4381             l2_only = 1;
4382         else if (unformat (i, "del"))
4383             is_add = 0;
4384         else {
4385             clib_warning ("parse error '%U'", format_unformat_error, i);
4386             return -99;
4387         }
4388     }
4389     
4390     M(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel);
4391
4392     mp->inner_vrf_id = ntohl(inner_vrf_id);
4393     mp->outer_vrf_id = ntohl(outer_vrf_id);
4394     clib_memcpy(mp->src_address, &src_address, sizeof (src_address));
4395     clib_memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
4396     clib_memcpy(mp->intfc_address, &intfc_address, sizeof (intfc_address));
4397     mp->intfc_address_length = intfc_address_length;
4398     mp->l2_only = l2_only;
4399     mp->is_add = is_add;
4400
4401     S; W;
4402     /* NOTREACHED */
4403     return 0;
4404 }
4405
4406 static int api_mpls_ethernet_add_del_tunnel (vat_main_t * vam)
4407 {
4408     unformat_input_t * i = vam->input;
4409     vl_api_mpls_ethernet_add_del_tunnel_t *mp;
4410     f64 timeout;
4411     u32 inner_vrf_id = 0;
4412     ip4_address_t intfc_address;
4413     u8 dst_mac_address[6];
4414     int dst_set = 1;
4415     u32 tmp;
4416     u8 intfc_address_length = 0;
4417     u8 is_add = 1;
4418     u8 l2_only = 0;
4419     u32 tx_sw_if_index;
4420     int tx_sw_if_index_set = 0;
4421     
4422     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4423         if (unformat (i, "vrf %d", &inner_vrf_id))
4424             ;
4425         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
4426                            &intfc_address, &tmp))
4427             intfc_address_length = tmp;
4428         else if (unformat (i, "%U", 
4429                            unformat_sw_if_index, vam, &tx_sw_if_index))
4430             tx_sw_if_index_set = 1;
4431         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4432             tx_sw_if_index_set = 1;
4433         else if (unformat (i, "dst %U", unformat_ethernet_address, 
4434                            dst_mac_address))
4435             dst_set = 1;
4436         else if (unformat (i, "l2-only"))
4437             l2_only = 1;
4438         else if (unformat (i, "del"))
4439             is_add = 0;
4440         else {
4441             clib_warning ("parse error '%U'", format_unformat_error, i);
4442             return -99;
4443         }
4444     }
4445
4446     if (!dst_set) {
4447         errmsg ("dst (mac address) not set\n");
4448         return -99;
4449     }
4450     if (!tx_sw_if_index_set) {
4451         errmsg ("tx-intfc not set\n");
4452         return -99;
4453     }
4454     
4455     M(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel);
4456
4457     mp->vrf_id = ntohl(inner_vrf_id);
4458     clib_memcpy (mp->adj_address, &intfc_address, sizeof (intfc_address));
4459     mp->adj_address_length = intfc_address_length;
4460     clib_memcpy (mp->dst_mac_address, dst_mac_address, sizeof (dst_mac_address));
4461     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
4462     mp->l2_only = l2_only;
4463     mp->is_add = is_add;
4464
4465     S; W;
4466     /* NOTREACHED */
4467     return 0;
4468 }
4469
4470 static int api_mpls_ethernet_add_del_tunnel_2 (vat_main_t * vam)
4471 {
4472     unformat_input_t * i = vam->input;
4473     vl_api_mpls_ethernet_add_del_tunnel_2_t *mp;
4474     f64 timeout;
4475     u32 inner_vrf_id = 0;
4476     u32 outer_vrf_id = 0;
4477     ip4_address_t adj_address;
4478     int adj_address_set = 0;
4479     ip4_address_t next_hop_address;
4480     int next_hop_address_set = 0;
4481     u32 tmp;
4482     u8 adj_address_length = 0;
4483     u8 l2_only = 0;
4484     u8 is_add = 1;
4485     u32 resolve_attempts = 5;
4486     u8 resolve_if_needed = 1;
4487     
4488     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4489         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
4490             ;
4491         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
4492             ;
4493         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
4494                            &adj_address, &tmp)) {
4495             adj_address_length = tmp;
4496             adj_address_set = 1;
4497         }
4498         else if (unformat (i, "next-hop %U", unformat_ip4_address,
4499                            &next_hop_address))
4500             next_hop_address_set = 1;
4501         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
4502             ;
4503         else if (unformat (i, "resolve-if-needed %d", &tmp))
4504             resolve_if_needed = tmp;
4505         else if (unformat (i, "l2-only"))
4506             l2_only = 1;
4507         else if (unformat (i, "del"))
4508             is_add = 0;
4509         else {
4510             clib_warning ("parse error '%U'", format_unformat_error, i);
4511             return -99;
4512         }
4513     }
4514     
4515     if (!adj_address_set) {
4516         errmsg ("adjacency address/mask not set\n");
4517         return -99;
4518     }
4519     if (!next_hop_address_set) {
4520         errmsg ("ip4 next hop address (in outer fib) not set\n");
4521         return -99;
4522     }
4523     
4524     M(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2);
4525     
4526     mp->inner_vrf_id = ntohl(inner_vrf_id);
4527     mp->outer_vrf_id = ntohl(outer_vrf_id);
4528     mp->resolve_attempts = ntohl(resolve_attempts);
4529     mp->resolve_if_needed = resolve_if_needed;
4530     mp->is_add = is_add;
4531     mp->l2_only = l2_only;
4532     clib_memcpy (mp->adj_address, &adj_address, sizeof (adj_address));
4533     mp->adj_address_length = adj_address_length;
4534     clib_memcpy (mp->next_hop_ip4_address_in_outer_vrf, &next_hop_address, 
4535             sizeof (next_hop_address));
4536
4537     S; W;
4538     /* NOTREACHED */
4539     return 0;
4540 }
4541
4542 static int api_sw_interface_set_unnumbered (vat_main_t * vam)
4543 {
4544     unformat_input_t * i = vam->input;
4545     vl_api_sw_interface_set_unnumbered_t *mp;
4546     f64 timeout;
4547     u32 sw_if_index;
4548     u32 unnum_sw_index;
4549     u8  is_add = 1;
4550     u8 sw_if_index_set = 0;
4551
4552     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4553         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4554             sw_if_index_set = 1;
4555         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4556             sw_if_index_set = 1;
4557         else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
4558             ;
4559         else if (unformat (i, "del"))
4560             is_add = 0;
4561         else {
4562             clib_warning ("parse error '%U'", format_unformat_error, i);
4563             return -99;
4564         }
4565     }
4566     
4567     if (sw_if_index_set == 0) {
4568         errmsg ("missing interface name or sw_if_index\n");
4569         return -99;
4570     }
4571
4572     M(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered);
4573
4574     mp->sw_if_index = ntohl(sw_if_index);
4575     mp->unnumbered_sw_if_index = ntohl(unnum_sw_index);
4576     mp->is_add = is_add;
4577
4578     S; W;
4579     /* NOTREACHED */
4580     return 0;
4581 }
4582
4583 static int api_ip_neighbor_add_del (vat_main_t * vam)
4584 {
4585     unformat_input_t * i = vam->input;
4586     vl_api_ip_neighbor_add_del_t *mp;
4587     f64 timeout;
4588     u32 sw_if_index;
4589     u8 sw_if_index_set = 0;
4590     u32 vrf_id = 0;
4591     u8 is_add = 1;
4592     u8 is_static = 0;
4593     u8 mac_address[6];
4594     u8 mac_set = 0;
4595     u8 v4_address_set = 0;
4596     u8 v6_address_set = 0;
4597     ip4_address_t v4address;
4598     ip6_address_t v6address;
4599     
4600     memset (mac_address, 0, sizeof (mac_address));
4601     
4602     /* Parse args required to build the message */
4603     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4604         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
4605             mac_set = 1;
4606         }
4607         else if (unformat (i, "del"))
4608             is_add = 0;
4609         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4610             sw_if_index_set = 1;
4611         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4612             sw_if_index_set = 1;
4613         else if (unformat (i, "is_static"))
4614             is_static = 1;
4615         else if (unformat (i, "vrf %d", &vrf_id))
4616             ;
4617         else if (unformat (i, "dst %U", 
4618                            unformat_ip4_address, &v4address))
4619                 v4_address_set = 1;
4620         else if (unformat (i, "dst %U", 
4621                            unformat_ip6_address, &v6address))
4622                 v6_address_set = 1;
4623         else {
4624             clib_warning ("parse error '%U'", format_unformat_error, i);
4625             return -99;
4626         }
4627     }
4628
4629     if (sw_if_index_set == 0) {
4630         errmsg ("missing interface name or sw_if_index\n");
4631         return -99;
4632     }
4633     if (v4_address_set && v6_address_set) {
4634         errmsg ("both v4 and v6 addresses set\n");
4635         return -99;
4636     }
4637     if (!v4_address_set && !v6_address_set) {
4638         errmsg ("no addresses set\n");
4639         return -99;
4640     }
4641
4642     /* Construct the API message */
4643     M(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del);
4644
4645     mp->sw_if_index = ntohl (sw_if_index);
4646     mp->is_add = is_add;
4647     mp->vrf_id = ntohl (vrf_id);
4648     mp->is_static = is_static;
4649     if (mac_set)
4650         clib_memcpy (mp->mac_address, mac_address, 6);
4651     if (v6_address_set) {
4652         mp->is_ipv6 = 1;
4653         clib_memcpy (mp->dst_address, &v6address, sizeof (v6address));
4654     } else {
4655         /* mp->is_ipv6 = 0; via memset in M macro above */
4656         clib_memcpy (mp->dst_address, &v4address, sizeof (v4address));
4657     }
4658
4659     /* send it... */
4660     S;
4661
4662     /* Wait for a reply, return good/bad news  */
4663     W;
4664
4665     /* NOTREACHED */
4666     return 0;
4667 }
4668
4669 static int api_reset_vrf (vat_main_t * vam)
4670 {
4671     unformat_input_t * i = vam->input;
4672     vl_api_reset_vrf_t *mp;
4673     f64 timeout;
4674     u32 vrf_id = 0;
4675     u8 is_ipv6 = 0;
4676     u8 vrf_id_set = 0;
4677
4678     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4679         if (unformat (i, "vrf %d", &vrf_id))
4680             vrf_id_set = 1;
4681         else if (unformat (i, "ipv6"))
4682             is_ipv6 = 1;
4683         else {
4684             clib_warning ("parse error '%U'", format_unformat_error, i);
4685             return -99;
4686         }
4687     }
4688
4689     if (vrf_id_set == 0) {
4690         errmsg ("missing vrf id\n");
4691         return -99;
4692     }
4693     
4694     M(RESET_VRF, reset_vrf);
4695
4696     mp->vrf_id = ntohl(vrf_id);
4697     mp->is_ipv6 = is_ipv6;
4698
4699     S; W;
4700     /* NOTREACHED */
4701     return 0;
4702 }
4703
4704 static int api_create_vlan_subif (vat_main_t * vam)
4705 {
4706     unformat_input_t * i = vam->input;
4707     vl_api_create_vlan_subif_t *mp;
4708     f64 timeout;
4709     u32 sw_if_index;
4710     u8  sw_if_index_set = 0;
4711     u32 vlan_id;
4712     u8  vlan_id_set = 0;
4713
4714     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4715         if (unformat (i, "sw_if_index %d", &sw_if_index))
4716             sw_if_index_set = 1;
4717         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4718             sw_if_index_set = 1;
4719         else if (unformat (i, "vlan %d", &vlan_id))
4720             vlan_id_set = 1;
4721         else {
4722             clib_warning ("parse error '%U'", format_unformat_error, i);
4723             return -99;
4724         }
4725     }
4726     
4727     if (sw_if_index_set == 0) {
4728         errmsg ("missing interface name or sw_if_index\n");
4729         return -99;
4730     }
4731
4732     if (vlan_id_set == 0) {
4733         errmsg ("missing vlan_id\n");
4734         return -99;
4735     }
4736     M(CREATE_VLAN_SUBIF, create_vlan_subif);
4737
4738     mp->sw_if_index = ntohl(sw_if_index);
4739     mp->vlan_id = ntohl(vlan_id);
4740
4741     S; W;
4742     /* NOTREACHED */
4743     return 0;
4744 }
4745
4746 #define foreach_create_subif_bit                \
4747 _(no_tags)                                      \
4748 _(one_tag)                                      \
4749 _(two_tags)                                     \
4750 _(dot1ad)                                       \
4751 _(exact_match)                                  \
4752 _(default_sub)                                  \
4753 _(outer_vlan_id_any)                            \
4754 _(inner_vlan_id_any)
4755
4756 static int api_create_subif (vat_main_t * vam)
4757 {
4758     unformat_input_t * i = vam->input;
4759     vl_api_create_subif_t *mp;
4760     f64 timeout;
4761     u32 sw_if_index;
4762     u8  sw_if_index_set = 0;
4763     u32 sub_id;
4764     u8  sub_id_set = 0;
4765     u32 no_tags = 0;
4766     u32 one_tag = 0;
4767     u32 two_tags = 0;
4768     u32 dot1ad = 0;
4769     u32 exact_match = 0;
4770     u32 default_sub = 0;
4771     u32 outer_vlan_id_any = 0;
4772     u32 inner_vlan_id_any = 0;
4773     u32 tmp;
4774     u16 outer_vlan_id = 0;
4775     u16 inner_vlan_id = 0;
4776
4777     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4778         if (unformat (i, "sw_if_index %d", &sw_if_index))
4779             sw_if_index_set = 1;
4780         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4781             sw_if_index_set = 1;
4782         else if (unformat (i, "sub_id %d", &sub_id))
4783             sub_id_set = 1;
4784         else if (unformat (i, "outer_vlan_id %d", &tmp))
4785             outer_vlan_id = tmp;
4786         else if (unformat (i, "inner_vlan_id %d", &tmp))
4787             inner_vlan_id = tmp;
4788
4789 #define _(a) else if (unformat (i, #a)) a = 1 ;
4790         foreach_create_subif_bit
4791 #undef _
4792
4793         else {
4794             clib_warning ("parse error '%U'", format_unformat_error, i);
4795             return -99;
4796         }
4797     }
4798     
4799     if (sw_if_index_set == 0) {
4800         errmsg ("missing interface name or sw_if_index\n");
4801         return -99;
4802     }
4803
4804     if (sub_id_set == 0) {
4805         errmsg ("missing sub_id\n");
4806         return -99;
4807     }
4808     M(CREATE_SUBIF, create_subif);
4809
4810     mp->sw_if_index = ntohl(sw_if_index);
4811     mp->sub_id = ntohl(sub_id);
4812     
4813 #define _(a) mp->a = a;
4814     foreach_create_subif_bit;
4815 #undef _
4816         
4817     mp->outer_vlan_id = ntohs (outer_vlan_id);
4818     mp->inner_vlan_id = ntohs (inner_vlan_id);
4819
4820     S; W;
4821     /* NOTREACHED */
4822     return 0;
4823 }
4824
4825 static int api_oam_add_del (vat_main_t * vam)
4826 {
4827     unformat_input_t * i = vam->input;
4828     vl_api_oam_add_del_t *mp;
4829     f64 timeout;
4830     u32 vrf_id = 0;
4831     u8 is_add = 1;
4832     ip4_address_t src, dst;
4833     u8 src_set = 0;
4834     u8 dst_set = 0;
4835     
4836     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4837         if (unformat (i, "vrf %d", &vrf_id))
4838             ;
4839         else if (unformat (i, "src %U", unformat_ip4_address, &src))
4840             src_set = 1;
4841         else if (unformat (i, "dst %U", unformat_ip4_address, &dst))
4842             dst_set = 1;
4843         else if (unformat (i, "del"))
4844             is_add = 0;
4845         else {
4846             clib_warning ("parse error '%U'", format_unformat_error, i);
4847             return -99;
4848         }
4849     }
4850     
4851     if (src_set == 0) {
4852         errmsg ("missing src addr\n");
4853         return -99;
4854     }
4855
4856     if (dst_set == 0) {
4857         errmsg ("missing dst addr\n");
4858         return -99;
4859     }
4860
4861     M(OAM_ADD_DEL, oam_add_del);
4862
4863     mp->vrf_id = ntohl(vrf_id);
4864     mp->is_add = is_add;
4865     clib_memcpy(mp->src_address, &src, sizeof (mp->src_address));
4866     clib_memcpy(mp->dst_address, &dst, sizeof (mp->dst_address));
4867
4868     S; W;
4869     /* NOTREACHED */
4870     return 0;
4871 }
4872
4873 static int api_reset_fib (vat_main_t * vam)
4874 {
4875     unformat_input_t * i = vam->input;
4876     vl_api_reset_fib_t *mp;
4877     f64 timeout;
4878     u32 vrf_id = 0;
4879     u8 is_ipv6 = 0;
4880     u8 vrf_id_set = 0;
4881
4882     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4883         if (unformat (i, "vrf %d", &vrf_id))
4884             vrf_id_set = 1;
4885         else if (unformat (i, "ipv6"))
4886             is_ipv6 = 1;
4887         else {
4888             clib_warning ("parse error '%U'", format_unformat_error, i);
4889             return -99;
4890         }
4891     }
4892
4893     if (vrf_id_set == 0) {
4894         errmsg ("missing vrf id\n");
4895         return -99;
4896     }
4897     
4898     M(RESET_FIB, reset_fib);
4899
4900     mp->vrf_id = ntohl(vrf_id);
4901     mp->is_ipv6 = is_ipv6;
4902
4903     S; W;
4904     /* NOTREACHED */
4905     return 0;
4906 }
4907
4908 static int api_dhcp_proxy_config (vat_main_t * vam)
4909 {
4910     unformat_input_t * i = vam->input;
4911     vl_api_dhcp_proxy_config_t *mp;
4912     f64 timeout;
4913     u32 vrf_id = 0;
4914     u8 is_add = 1;
4915     u8 insert_cid = 1;
4916     u8 v4_address_set = 0;
4917     u8 v6_address_set = 0;
4918     ip4_address_t v4address;
4919     ip6_address_t v6address;
4920     u8 v4_src_address_set = 0;
4921     u8 v6_src_address_set = 0;
4922     ip4_address_t v4srcaddress;
4923     ip6_address_t v6srcaddress;
4924     
4925     /* Parse args required to build the message */
4926     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4927         if (unformat (i, "del"))
4928             is_add = 0;
4929         else if (unformat (i, "vrf %d", &vrf_id))
4930             ;
4931         else if (unformat (i, "insert-cid %d", &insert_cid))
4932             ;
4933         else if (unformat (i, "svr %U", 
4934                            unformat_ip4_address, &v4address))
4935                 v4_address_set = 1;
4936         else if (unformat (i, "svr %U", 
4937                            unformat_ip6_address, &v6address))
4938                 v6_address_set = 1;
4939         else if (unformat (i, "src %U", 
4940                            unformat_ip4_address, &v4srcaddress))
4941                 v4_src_address_set = 1;
4942         else if (unformat (i, "src %U", 
4943                            unformat_ip6_address, &v6srcaddress))
4944                 v6_src_address_set = 1;
4945         else
4946             break;
4947     }
4948
4949     if (v4_address_set && v6_address_set) {
4950         errmsg ("both v4 and v6 server addresses set\n");
4951         return -99;
4952     }
4953     if (!v4_address_set && !v6_address_set) {
4954         errmsg ("no server addresses set\n");
4955         return -99;
4956     }
4957
4958     if (v4_src_address_set && v6_src_address_set) {
4959         errmsg ("both v4 and v6  src addresses set\n");
4960         return -99;
4961     }
4962     if (!v4_src_address_set && !v6_src_address_set) {
4963         errmsg ("no src addresses set\n");
4964         return -99;
4965     }
4966
4967     if (!(v4_src_address_set && v4_address_set) &&
4968         !(v6_src_address_set && v6_address_set)) {
4969         errmsg ("no matching server and src addresses set\n");
4970         return -99;
4971     }
4972
4973     /* Construct the API message */
4974     M(DHCP_PROXY_CONFIG, dhcp_proxy_config);
4975
4976     mp->insert_circuit_id = insert_cid;
4977     mp->is_add = is_add;
4978     mp->vrf_id = ntohl (vrf_id);
4979     if (v6_address_set) {
4980         mp->is_ipv6 = 1;
4981         clib_memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
4982         clib_memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
4983     } else {
4984         clib_memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
4985         clib_memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
4986     }
4987
4988     /* send it... */
4989     S;
4990
4991     /* Wait for a reply, return good/bad news  */
4992     W;
4993     /* NOTREACHED */
4994     return 0;
4995 }
4996
4997 static int api_dhcp_proxy_config_2 (vat_main_t * vam)
4998 {
4999     unformat_input_t * i = vam->input;
5000     vl_api_dhcp_proxy_config_2_t *mp;
5001     f64 timeout;
5002     u32 rx_vrf_id = 0;
5003     u32 server_vrf_id = 0;
5004     u8 is_add = 1;
5005     u8 insert_cid = 1;
5006     u8 v4_address_set = 0;
5007     u8 v6_address_set = 0;
5008     ip4_address_t v4address;
5009     ip6_address_t v6address;
5010     u8 v4_src_address_set = 0;
5011     u8 v6_src_address_set = 0;
5012     ip4_address_t v4srcaddress;
5013     ip6_address_t v6srcaddress;
5014     
5015     /* Parse args required to build the message */
5016     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5017         if (unformat (i, "del"))
5018             is_add = 0;
5019         else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
5020             ;
5021         else if (unformat (i, "server_vrf_id %d", &server_vrf_id))
5022             ;
5023         else if (unformat (i, "insert-cid %d", &insert_cid))
5024             ;
5025         else if (unformat (i, "svr %U", 
5026                            unformat_ip4_address, &v4address))
5027                 v4_address_set = 1;
5028         else if (unformat (i, "svr %U", 
5029                            unformat_ip6_address, &v6address))
5030                 v6_address_set = 1;
5031         else if (unformat (i, "src %U", 
5032                            unformat_ip4_address, &v4srcaddress))
5033                 v4_src_address_set = 1;
5034         else if (unformat (i, "src %U", 
5035                            unformat_ip6_address, &v6srcaddress))
5036                 v6_src_address_set = 1;
5037         else
5038             break;
5039     }
5040
5041     if (v4_address_set && v6_address_set) {
5042         errmsg ("both v4 and v6 server addresses set\n");
5043         return -99;
5044     }
5045     if (!v4_address_set && !v6_address_set) {
5046         errmsg ("no server addresses set\n");
5047         return -99;
5048     }
5049
5050     if (v4_src_address_set && v6_src_address_set) {
5051         errmsg ("both v4 and v6  src addresses set\n");
5052         return -99;
5053     }
5054     if (!v4_src_address_set && !v6_src_address_set) {
5055         errmsg ("no src addresses set\n");
5056         return -99;
5057     }
5058
5059     if (!(v4_src_address_set && v4_address_set) &&
5060         !(v6_src_address_set && v6_address_set)) {
5061         errmsg ("no matching server and src addresses set\n");
5062         return -99;
5063     }
5064
5065     /* Construct the API message */
5066     M(DHCP_PROXY_CONFIG_2, dhcp_proxy_config_2);
5067
5068     mp->insert_circuit_id = insert_cid;
5069     mp->is_add = is_add;
5070     mp->rx_vrf_id = ntohl (rx_vrf_id);
5071     mp->server_vrf_id = ntohl (server_vrf_id);
5072     if (v6_address_set) {
5073         mp->is_ipv6 = 1;
5074         clib_memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
5075         clib_memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
5076     } else {
5077         clib_memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
5078         clib_memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
5079     }
5080
5081     /* send it... */
5082     S;
5083
5084     /* Wait for a reply, return good/bad news  */
5085     W;
5086     /* NOTREACHED */
5087     return 0;
5088 }
5089
5090 static int api_dhcp_proxy_set_vss (vat_main_t * vam)
5091 {
5092     unformat_input_t * i = vam->input;
5093     vl_api_dhcp_proxy_set_vss_t *mp;
5094     f64 timeout;
5095     u8  is_ipv6 = 0;
5096     u8  is_add = 1;
5097     u32 tbl_id;
5098     u8  tbl_id_set = 0;
5099     u32 oui;
5100     u8  oui_set = 0;
5101     u32 fib_id;
5102     u8  fib_id_set = 0;
5103
5104     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5105         if (unformat (i, "tbl_id %d", &tbl_id))
5106             tbl_id_set = 1;
5107         if (unformat (i, "fib_id %d", &fib_id))
5108             fib_id_set = 1;
5109         if (unformat (i, "oui %d", &oui))
5110             oui_set = 1;
5111         else if (unformat (i, "ipv6"))
5112             is_ipv6 = 1;
5113         else if (unformat (i, "del"))
5114             is_add = 0;
5115         else {
5116             clib_warning ("parse error '%U'", format_unformat_error, i);
5117             return -99;
5118         }
5119     }
5120
5121     if (tbl_id_set == 0) {
5122         errmsg ("missing tbl id\n");
5123         return -99;
5124     }
5125
5126     if (fib_id_set == 0) {
5127         errmsg ("missing fib id\n");
5128         return -99;
5129     }
5130     if (oui_set == 0) {
5131         errmsg ("missing oui\n");
5132         return -99;
5133     }
5134     
5135     M(DHCP_PROXY_SET_VSS, dhcp_proxy_set_vss);
5136     mp->tbl_id = ntohl(tbl_id);
5137     mp->fib_id = ntohl(fib_id);
5138     mp->oui = ntohl(oui);
5139     mp->is_ipv6 = is_ipv6;
5140     mp->is_add = is_add;
5141
5142     S; W;
5143     /* NOTREACHED */
5144     return 0;
5145 }
5146
5147 static int api_dhcp_client_config (vat_main_t * vam)
5148 {
5149     unformat_input_t * i = vam->input;
5150     vl_api_dhcp_client_config_t *mp;
5151     f64 timeout;
5152     u32 sw_if_index;
5153     u8 sw_if_index_set = 0;
5154     u8 is_add = 1;
5155     u8 * hostname = 0;
5156     u8 disable_event = 0;
5157
5158     /* Parse args required to build the message */
5159     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5160         if (unformat (i, "del"))
5161             is_add = 0;
5162         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5163             sw_if_index_set = 1;
5164         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5165             sw_if_index_set = 1;
5166         else if (unformat (i, "hostname %s", &hostname))
5167             ;
5168         else if (unformat (i, "disable_event"))
5169             disable_event = 1;
5170         else
5171             break;
5172     }
5173
5174     if (sw_if_index_set == 0) {
5175         errmsg ("missing interface name or sw_if_index\n");
5176         return -99;
5177     }
5178
5179     if (vec_len (hostname) > 63) {
5180         errmsg ("hostname too long\n");
5181     }
5182     vec_add1 (hostname, 0);
5183
5184     /* Construct the API message */
5185     M(DHCP_CLIENT_CONFIG, dhcp_client_config);
5186
5187     mp->sw_if_index = ntohl (sw_if_index);
5188     clib_memcpy (mp->hostname, hostname, vec_len (hostname));
5189     vec_free (hostname);
5190     mp->is_add = is_add;
5191     mp->want_dhcp_event = disable_event ? 0 : 1;
5192     mp->pid = getpid();
5193    
5194     /* send it... */
5195     S;
5196
5197     /* Wait for a reply, return good/bad news  */
5198     W;
5199     /* NOTREACHED */
5200     return 0;
5201 }
5202
5203 static int api_set_ip_flow_hash (vat_main_t * vam)
5204 {
5205     unformat_input_t * i = vam->input;
5206     vl_api_set_ip_flow_hash_t *mp;
5207     f64 timeout;
5208     u32 vrf_id = 0;
5209     u8 is_ipv6 = 0;
5210     u8 vrf_id_set = 0;
5211     u8 src = 0;
5212     u8 dst = 0;
5213     u8 sport = 0;
5214     u8 dport = 0;
5215     u8 proto = 0;
5216     u8 reverse = 0;
5217
5218     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5219         if (unformat (i, "vrf %d", &vrf_id))
5220             vrf_id_set = 1;
5221         else if (unformat (i, "ipv6"))
5222             is_ipv6 = 1;
5223         else if (unformat (i, "src"))
5224             src = 1;
5225         else if (unformat (i, "dst"))
5226             dst = 1;
5227         else if (unformat (i, "sport"))
5228             sport = 1;
5229         else if (unformat (i, "dport"))
5230             dport = 1;
5231         else if (unformat (i, "proto"))
5232             proto = 1;
5233         else if (unformat (i, "reverse"))
5234             reverse = 1;
5235
5236         else {
5237             clib_warning ("parse error '%U'", format_unformat_error, i);
5238             return -99;
5239         }
5240     }
5241
5242     if (vrf_id_set == 0) {
5243         errmsg ("missing vrf id\n");
5244         return -99;
5245     }
5246     
5247     M(SET_IP_FLOW_HASH, set_ip_flow_hash);
5248     mp->src = src;
5249     mp->dst = dst;
5250     mp->sport = sport;
5251     mp->dport = dport;
5252     mp->proto = proto;
5253     mp->reverse = reverse;
5254     mp->vrf_id = ntohl(vrf_id);
5255     mp->is_ipv6 = is_ipv6;
5256
5257     S; W;
5258     /* NOTREACHED */
5259     return 0;
5260 }
5261
5262 static int api_sw_interface_ip6_enable_disable (vat_main_t * vam)
5263 {
5264     unformat_input_t * i = vam->input;
5265     vl_api_sw_interface_ip6_enable_disable_t *mp;
5266     f64 timeout;
5267     u32 sw_if_index;
5268     u8  sw_if_index_set = 0;
5269     u8  enable = 0;
5270
5271     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5272         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5273             sw_if_index_set = 1;
5274         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5275             sw_if_index_set = 1;
5276         else if (unformat (i, "enable"))
5277             enable = 1;
5278         else if (unformat (i, "disable"))
5279             enable = 0;
5280         else {
5281             clib_warning ("parse error '%U'", format_unformat_error, i);
5282             return -99;
5283         }
5284     }
5285
5286     if (sw_if_index_set == 0) {
5287         errmsg ("missing interface name or sw_if_index\n");
5288         return -99;
5289     }
5290     
5291     M(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable);
5292
5293     mp->sw_if_index = ntohl(sw_if_index);
5294     mp->enable = enable;
5295
5296     S; W;
5297     /* NOTREACHED */
5298     return 0;
5299 }
5300
5301 static int api_sw_interface_ip6_set_link_local_address (vat_main_t * vam)
5302 {
5303     unformat_input_t * i = vam->input;
5304     vl_api_sw_interface_ip6_set_link_local_address_t *mp;
5305     f64 timeout;
5306     u32 sw_if_index;
5307     u8 sw_if_index_set = 0;
5308     u32 address_length = 0;
5309     u8 v6_address_set = 0;
5310     ip6_address_t v6address;
5311     
5312     /* Parse args required to build the message */
5313     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5314         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5315             sw_if_index_set = 1;
5316         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5317             sw_if_index_set = 1;
5318         else if (unformat (i, "%U/%d", 
5319                            unformat_ip6_address, &v6address, 
5320                            &address_length))
5321             v6_address_set = 1;
5322         else
5323             break;
5324     }
5325
5326     if (sw_if_index_set == 0) {
5327         errmsg ("missing interface name or sw_if_index\n");
5328         return -99;
5329     }
5330     if (!v6_address_set) {
5331         errmsg ("no address set\n");
5332         return -99;
5333     }
5334
5335     /* Construct the API message */
5336     M(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
5337       sw_interface_ip6_set_link_local_address);
5338
5339     mp->sw_if_index = ntohl (sw_if_index);
5340     clib_memcpy (mp->address, &v6address, sizeof (v6address));
5341     mp->address_length = address_length;
5342
5343     /* send it... */
5344     S;
5345
5346     /* Wait for a reply, return good/bad news  */
5347     W;
5348
5349     /* NOTREACHED */
5350     return 0;
5351 }
5352
5353
5354 static int api_sw_interface_ip6nd_ra_prefix (vat_main_t * vam)
5355 {
5356     unformat_input_t * i = vam->input;
5357     vl_api_sw_interface_ip6nd_ra_prefix_t *mp;
5358     f64 timeout;
5359     u32 sw_if_index;
5360     u8 sw_if_index_set = 0;
5361     u32 address_length = 0;
5362     u8 v6_address_set = 0;
5363     ip6_address_t v6address;
5364     u8 use_default = 0;
5365     u8 no_advertise = 0;
5366     u8 off_link = 0;
5367     u8 no_autoconfig = 0;
5368     u8 no_onlink = 0;
5369     u8 is_no = 0;
5370     u32 val_lifetime = 0;
5371     u32 pref_lifetime = 0;
5372     
5373     /* Parse args required to build the message */
5374     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5375         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5376             sw_if_index_set = 1;
5377         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5378             sw_if_index_set = 1;
5379         else if (unformat (i, "%U/%d", 
5380                            unformat_ip6_address, &v6address, 
5381                            &address_length))
5382             v6_address_set = 1;
5383         else if (unformat (i, "val_life %d", &val_lifetime))
5384             ;
5385         else if (unformat (i, "pref_life %d", &pref_lifetime))
5386             ;
5387         else if (unformat (i, "def"))
5388             use_default = 1;
5389         else if (unformat (i, "noadv"))
5390             no_advertise = 1;
5391         else if (unformat (i, "offl"))
5392             off_link = 1;
5393         else if (unformat (i, "noauto"))
5394             no_autoconfig = 1;
5395         else if (unformat (i, "nolink"))
5396             no_onlink = 1;
5397         else if (unformat (i, "isno"))
5398             is_no = 1;
5399         else {
5400             clib_warning ("parse error '%U'", format_unformat_error, i);
5401             return -99;
5402         }        
5403     }
5404
5405     if (sw_if_index_set == 0) {
5406         errmsg ("missing interface name or sw_if_index\n");
5407         return -99;
5408     }
5409     if (!v6_address_set) {
5410         errmsg ("no address set\n");
5411         return -99;
5412     }
5413
5414     /* Construct the API message */
5415     M(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix);
5416
5417     mp->sw_if_index = ntohl (sw_if_index);
5418     clib_memcpy (mp->address, &v6address, sizeof (v6address));
5419     mp->address_length = address_length;
5420     mp->use_default = use_default;
5421     mp->no_advertise = no_advertise;
5422     mp->off_link = off_link;
5423     mp->no_autoconfig = no_autoconfig;
5424     mp->no_onlink = no_onlink;
5425     mp->is_no = is_no;
5426     mp->val_lifetime = ntohl(val_lifetime);
5427     mp->pref_lifetime = ntohl(pref_lifetime);
5428
5429     /* send it... */
5430     S;
5431
5432     /* Wait for a reply, return good/bad news  */
5433     W;
5434
5435     /* NOTREACHED */
5436     return 0;
5437 }
5438
5439 static int api_sw_interface_ip6nd_ra_config (vat_main_t * vam)
5440 {
5441     unformat_input_t * i = vam->input;
5442     vl_api_sw_interface_ip6nd_ra_config_t *mp;
5443     f64 timeout;
5444     u32 sw_if_index;
5445     u8 sw_if_index_set = 0;
5446     u8 surpress = 0;
5447     u8 managed = 0;
5448     u8 other = 0;
5449     u8 ll_option = 0;
5450     u8 send_unicast = 0;
5451     u8 cease = 0;
5452     u8 is_no = 0;
5453     u8 default_router = 0;
5454     u32 max_interval = 0;
5455     u32 min_interval = 0;
5456     u32 lifetime = 0;
5457     u32 initial_count = 0;
5458     u32 initial_interval = 0;
5459
5460     
5461     /* Parse args required to build the message */
5462     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5463         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
5464             sw_if_index_set = 1;
5465         else if (unformat (i, "sw_if_index %d", &sw_if_index))
5466             sw_if_index_set = 1;
5467         else if (unformat (i, "maxint %d", &max_interval))
5468             ;
5469         else if (unformat (i, "minint %d", &min_interval))
5470             ;
5471         else if (unformat (i, "life %d", &lifetime))
5472             ;
5473         else if (unformat (i, "count %d", &initial_count))
5474             ;
5475         else if (unformat (i, "interval %d", &initial_interval))
5476             ;
5477         else if (unformat (i, "surpress"))
5478             surpress = 1;
5479         else if (unformat (i, "managed"))
5480             managed = 1;
5481         else if (unformat (i, "other"))
5482             other = 1;
5483         else if (unformat (i, "ll"))
5484             ll_option = 1;
5485         else if (unformat (i, "send"))
5486             send_unicast = 1;
5487         else if (unformat (i, "cease"))
5488             cease = 1;
5489         else if (unformat (i, "isno"))
5490             is_no = 1;
5491         else if (unformat (i, "def"))
5492             default_router = 1;
5493         else {
5494             clib_warning ("parse error '%U'", format_unformat_error, i);
5495             return -99;
5496         }        
5497     }
5498
5499     if (sw_if_index_set == 0) {
5500         errmsg ("missing interface name or sw_if_index\n");
5501         return -99;
5502     }
5503
5504     /* Construct the API message */
5505     M(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config);
5506
5507     mp->sw_if_index = ntohl (sw_if_index);
5508     mp->max_interval = ntohl(max_interval);
5509     mp->min_interval = ntohl(min_interval);
5510     mp->lifetime = ntohl(lifetime);
5511     mp->initial_count = ntohl(initial_count);
5512     mp->initial_interval = ntohl(initial_interval);
5513     mp->surpress = surpress;
5514     mp->managed = managed;
5515     mp->other = other;
5516     mp->ll_option = ll_option;
5517     mp->send_unicast = send_unicast;
5518     mp->cease = cease;
5519     mp->is_no = is_no;
5520     mp->default_router = default_router;
5521
5522     /* send it... */
5523     S;
5524
5525     /* Wait for a reply, return good/bad news  */
5526     W;
5527
5528     /* NOTREACHED */
5529     return 0;
5530 }
5531
5532 static int api_set_arp_neighbor_limit (vat_main_t * vam)
5533 {
5534     unformat_input_t * i = vam->input;
5535     vl_api_set_arp_neighbor_limit_t *mp;
5536     f64 timeout;
5537     u32 arp_nbr_limit;
5538     u8 limit_set = 0;
5539     u8 is_ipv6 = 0;
5540
5541     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5542         if (unformat (i, "arp_nbr_limit %d", &arp_nbr_limit))
5543             limit_set = 1;
5544         else if (unformat (i, "ipv6"))
5545             is_ipv6 = 1;
5546         else {
5547             clib_warning ("parse error '%U'", format_unformat_error, i);
5548             return -99;
5549         }
5550     }
5551
5552     if (limit_set == 0) {
5553         errmsg ("missing limit value\n");
5554         return -99;
5555     }
5556     
5557     M(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit);
5558
5559     mp->arp_neighbor_limit = ntohl(arp_nbr_limit);
5560     mp->is_ipv6 = is_ipv6;
5561
5562     S; W;
5563     /* NOTREACHED */
5564     return 0;
5565 }
5566
5567 static int api_l2_patch_add_del (vat_main_t * vam)
5568 {
5569     unformat_input_t * i = vam->input;
5570     vl_api_l2_patch_add_del_t *mp;
5571     f64 timeout;
5572     u32 rx_sw_if_index;
5573     u8 rx_sw_if_index_set = 0;
5574     u32 tx_sw_if_index;
5575     u8 tx_sw_if_index_set = 0;
5576     u8 is_add = 1;
5577     
5578     /* Parse args required to build the message */
5579     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5580         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
5581             rx_sw_if_index_set = 1;     
5582         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
5583             tx_sw_if_index_set = 1;
5584         else if (unformat (i, "rx")) {
5585             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5586                 if (unformat (i, "%U", unformat_sw_if_index, vam,
5587                               &rx_sw_if_index))
5588                     rx_sw_if_index_set = 1;
5589             } else
5590                 break;
5591         } else if (unformat (i, "tx")) {
5592             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5593                 if (unformat (i, "%U", unformat_sw_if_index, vam,
5594                               &tx_sw_if_index))
5595                     tx_sw_if_index_set = 1;
5596             } else
5597                 break;
5598         } else if (unformat (i, "del"))
5599             is_add = 0;
5600         else
5601             break;
5602     }
5603
5604     if (rx_sw_if_index_set == 0) {
5605         errmsg ("missing rx interface name or rx_sw_if_index\n");
5606         return -99;
5607     }
5608
5609     if (tx_sw_if_index_set == 0) {
5610         errmsg ("missing tx interface name or tx_sw_if_index\n");
5611         return -99;
5612     }
5613     
5614     M(L2_PATCH_ADD_DEL, l2_patch_add_del);
5615
5616     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
5617     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
5618     mp->is_add = is_add;
5619
5620     S; W;
5621     /* NOTREACHED */
5622     return 0;
5623 }
5624 static int api_trace_profile_add (vat_main_t *vam)
5625 {
5626    unformat_input_t * input = vam->input;
5627    vl_api_trace_profile_add_t *mp;
5628    f64 timeout;
5629    u32 id = 0;
5630    u32 trace_option_elts = 0;
5631    u32 trace_type = 0, node_id = 0, app_data = 0, trace_tsp = 2;
5632    int has_pow_option = 0;
5633    int has_ppc_option = 0;
5634   
5635   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5636     {
5637       if (unformat (input, "id %d trace-type 0x%x trace-elts %d "
5638                            "trace-tsp %d node-id 0x%x app-data 0x%x", 
5639                     &id, &trace_type, &trace_option_elts, &trace_tsp,
5640                       &node_id, &app_data))
5641             ;
5642       else if (unformat (input, "pow"))
5643         has_pow_option = 1;
5644       else if (unformat (input, "ppc encap"))
5645         has_ppc_option = PPC_ENCAP;
5646       else if (unformat (input, "ppc decap"))
5647         has_ppc_option = PPC_DECAP;
5648       else if (unformat (input, "ppc none"))
5649         has_ppc_option = PPC_NONE;
5650       else
5651         break;
5652     }
5653   M(TRACE_PROFILE_ADD, trace_profile_add);
5654   mp->id = htons(id);
5655   mp->trace_type = trace_type;
5656   mp->trace_num_elt = trace_option_elts;
5657   mp->trace_ppc = has_ppc_option;
5658   mp->trace_app_data = htonl(app_data);
5659   mp->pow_enable = has_pow_option;
5660   mp->trace_tsp = trace_tsp;
5661   mp->node_id = htonl(node_id);
5662   
5663   S; W;
5664   
5665   return(0);
5666    
5667 }
5668 static int api_trace_profile_apply (vat_main_t *vam)
5669 {
5670   unformat_input_t * input = vam->input;
5671   vl_api_trace_profile_apply_t *mp;
5672   f64 timeout;
5673   ip6_address_t addr;
5674   u32 mask_width = ~0;
5675   int is_add = 0;
5676   int is_pop = 0;
5677   int is_none = 0;
5678   u32 vrf_id = 0;
5679   u32 id = 0;
5680   
5681   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5682     {
5683       if (unformat (input, "%U/%d",
5684                     unformat_ip6_address, &addr, &mask_width))
5685         ;
5686       else if (unformat (input, "id %d", &id))
5687         ;
5688       else if (unformat (input, "vrf-id %d", &vrf_id))
5689         ;
5690       else if (unformat (input, "add"))
5691         is_add = 1;
5692       else if (unformat (input, "pop"))
5693         is_pop = 1;
5694       else if (unformat (input, "none"))
5695         is_none = 1;
5696       else
5697         break;
5698     }
5699
5700   if ((is_add + is_pop + is_none) != 1) {
5701     errmsg("One of (add, pop, none) required");
5702     return -99;
5703   }
5704   if (mask_width == ~0) {
5705     errmsg("<address>/<mask-width> required");
5706     return -99;
5707   }
5708   M(TRACE_PROFILE_APPLY, trace_profile_apply);
5709   clib_memcpy(mp->dest_ipv6, &addr, sizeof(mp->dest_ipv6));
5710   mp->id = htons(id);
5711   mp->prefix_length = htonl(mask_width);
5712   mp->vrf_id = htonl(vrf_id);
5713   if (is_add)
5714     mp->trace_op = IOAM_HBYH_ADD;
5715   else if (is_pop)
5716     mp->trace_op = IOAM_HBYH_POP;
5717   else
5718     mp->trace_op = IOAM_HBYH_MOD;
5719
5720   if(is_none)
5721     mp->enable = 0;
5722   else
5723     mp->enable = 1;
5724   
5725   S; W;
5726
5727   return 0;
5728 }
5729
5730 static int api_trace_profile_del (vat_main_t *vam)
5731 {
5732    vl_api_trace_profile_del_t *mp;
5733    f64 timeout;
5734    
5735    M(TRACE_PROFILE_DEL, trace_profile_del);
5736    S; W;
5737    return 0;
5738 }
5739
5740 static int api_sr_tunnel_add_del (vat_main_t * vam)
5741 {
5742   unformat_input_t * i = vam->input;
5743   vl_api_sr_tunnel_add_del_t *mp;
5744   f64 timeout;
5745   int is_del = 0;
5746   int pl_index;
5747   ip6_address_t src_address;
5748   int src_address_set = 0;
5749   ip6_address_t dst_address;
5750   u32 dst_mask_width;
5751   int dst_address_set = 0;
5752   u16 flags = 0;
5753   u32 rx_table_id = 0;
5754   u32 tx_table_id = 0;
5755   ip6_address_t * segments = 0;
5756   ip6_address_t * this_seg;
5757   ip6_address_t * tags = 0;
5758   ip6_address_t * this_tag;
5759   ip6_address_t next_address, tag;
5760   u8 * name = 0;
5761   u8 * policy_name = 0;
5762
5763   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5764     {
5765       if (unformat (i, "del"))
5766         is_del = 1;
5767       else if (unformat (i, "name %s", &name))
5768             ;
5769       else if (unformat (i, "policy %s", &policy_name))
5770             ;
5771       else if (unformat (i, "rx_fib_id %d", &rx_table_id))
5772         ;
5773       else if (unformat (i, "tx_fib_id %d", &tx_table_id))
5774         ;
5775       else if (unformat (i, "src %U", unformat_ip6_address, &src_address))
5776         src_address_set = 1;
5777       else if (unformat (i, "dst %U/%d", 
5778                          unformat_ip6_address, &dst_address,
5779                          &dst_mask_width))
5780         dst_address_set = 1;
5781       else if (unformat (i, "next %U", unformat_ip6_address,
5782                          &next_address))
5783         {
5784           vec_add2 (segments, this_seg, 1);
5785           clib_memcpy (this_seg->as_u8, next_address.as_u8, sizeof (*this_seg));
5786         }
5787       else if (unformat (i, "tag %U", unformat_ip6_address,
5788                          &tag))
5789         {
5790           vec_add2 (tags, this_tag, 1);
5791           clib_memcpy (this_tag->as_u8, tag.as_u8, sizeof (*this_tag));
5792         }
5793       else if (unformat (i, "clean"))
5794         flags |= IP6_SR_HEADER_FLAG_CLEANUP;
5795       else if (unformat (i, "protected"))
5796         flags |= IP6_SR_HEADER_FLAG_PROTECTED;
5797       else if (unformat (i, "InPE %d", &pl_index))
5798         {
5799           if (pl_index <= 0 || pl_index > 4)
5800             {
5801             pl_index_range_error:
5802               errmsg ("pl index %d out of range\n", pl_index);
5803               return -99;
5804             }
5805           flags |= IP6_SR_HEADER_FLAG_PL_ELT_INGRESS_PE << (3*(pl_index - 1));
5806         }
5807       else if (unformat (i, "EgPE %d", &pl_index))
5808         {
5809           if (pl_index <= 0 || pl_index > 4)
5810             goto pl_index_range_error;
5811           flags |= IP6_SR_HEADER_FLAG_PL_ELT_EGRESS_PE << (3*(pl_index - 1));
5812         }
5813       else if (unformat (i, "OrgSrc %d", &pl_index))
5814         {
5815           if (pl_index <= 0 || pl_index > 4)
5816             goto pl_index_range_error;
5817           flags |= IP6_SR_HEADER_FLAG_PL_ELT_ORIG_SRC_ADDR << (3*(pl_index - 1));
5818         }
5819       else 
5820         break;
5821     }
5822
5823   if (!src_address_set)
5824     {
5825       errmsg ("src address required\n");
5826       return -99;
5827     }
5828
5829   if (!dst_address_set)
5830     {
5831       errmsg ("dst address required\n");
5832       return -99;
5833     }
5834
5835   if (!segments)
5836     {
5837       errmsg ("at least one sr segment required\n");
5838       return -99;
5839     }
5840
5841   M2(SR_TUNNEL_ADD_DEL, sr_tunnel_add_del, 
5842      vec_len(segments) * sizeof (ip6_address_t) 
5843      + vec_len(tags) * sizeof (ip6_address_t));
5844
5845   clib_memcpy (mp->src_address, &src_address, sizeof (mp->src_address));
5846   clib_memcpy (mp->dst_address, &dst_address, sizeof (mp->dst_address));
5847   mp->dst_mask_width = dst_mask_width;
5848   mp->flags_net_byte_order = clib_host_to_net_u16 (flags);
5849   mp->n_segments = vec_len (segments);
5850   mp->n_tags = vec_len (tags);
5851   mp->is_add = is_del == 0;
5852   clib_memcpy (mp->segs_and_tags, segments, 
5853           vec_len(segments)* sizeof (ip6_address_t));
5854   clib_memcpy (mp->segs_and_tags + vec_len(segments)*sizeof (ip6_address_t),
5855           tags, vec_len(tags)* sizeof (ip6_address_t));
5856
5857   mp->outer_vrf_id = ntohl (rx_table_id);
5858   mp->inner_vrf_id = ntohl (tx_table_id);
5859   memcpy (mp->name, name, vec_len(name));
5860   memcpy (mp->policy_name, policy_name, vec_len(policy_name));
5861
5862   vec_free (segments);
5863   vec_free (tags);
5864   
5865   S; W;
5866   /* NOTREACHED */
5867 }
5868
5869 static int api_sr_policy_add_del (vat_main_t * vam)
5870 {
5871   unformat_input_t * input = vam->input;
5872   vl_api_sr_policy_add_del_t *mp;
5873   f64 timeout;
5874   int is_del = 0;
5875   u8 * name = 0;
5876   u8 * tunnel_name = 0;
5877   u8 ** tunnel_names = 0;
5878   
5879   int name_set = 0 ;
5880   int tunnel_set = 0;
5881   int j = 0;
5882   int tunnel_names_length = 1; // Init to 1 to offset the #tunnel_names counter byte
5883   int tun_name_len = 0; // Different naming convention used as confusing these would be "bad" (TM)
5884
5885   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5886     {
5887       if (unformat (input, "del"))
5888         is_del = 1;
5889       else if (unformat (input, "name %s", &name))
5890         name_set = 1;
5891       else if (unformat (input, "tunnel %s", &tunnel_name))
5892         {
5893           if (tunnel_name)
5894             {
5895               vec_add1 (tunnel_names, tunnel_name);
5896               /* For serializer: 
5897                  - length = #bytes to store in serial vector
5898                  - +1 = byte to store that length
5899               */
5900               tunnel_names_length += (vec_len (tunnel_name) + 1); 
5901               tunnel_set = 1;
5902               tunnel_name = 0;
5903             }
5904         }
5905       else 
5906         break;
5907     }
5908
5909   if (!name_set)
5910     {
5911       errmsg ("policy name required\n");
5912       return -99;
5913     }
5914
5915   if ((!tunnel_set) && (!is_del))
5916     {
5917       errmsg ("tunnel name required\n");
5918       return -99;
5919     }
5920
5921   M2(SR_POLICY_ADD_DEL, sr_policy_add_del, tunnel_names_length);
5922
5923   
5924
5925   mp->is_add = !is_del;
5926
5927   memcpy (mp->name, name, vec_len(name));
5928   // Since mp->tunnel_names is of type u8[0] and not a u8 *, u8 ** needs to be serialized
5929   u8 * serial_orig = 0;
5930   vec_validate (serial_orig, tunnel_names_length);
5931   *serial_orig = vec_len(tunnel_names); // Store the number of tunnels as length in first byte of serialized vector
5932   serial_orig += 1; // Move along one byte to store the length of first tunnel_name
5933
5934   for (j=0; j < vec_len(tunnel_names); j++)
5935     {
5936       tun_name_len = vec_len (tunnel_names[j]);
5937       *serial_orig = tun_name_len; // Store length of tunnel name in first byte of Length/Value pair
5938       serial_orig += 1; // Move along one byte to store the actual tunnel name
5939       memcpy (serial_orig, tunnel_names[j], tun_name_len);
5940       serial_orig += tun_name_len; // Advance past the copy
5941     }
5942   memcpy (mp->tunnel_names, serial_orig - tunnel_names_length, tunnel_names_length); // Regress serial_orig to head then copy fwd
5943
5944   vec_free (tunnel_names);
5945   vec_free (tunnel_name);
5946   
5947   S; W;
5948   /* NOTREACHED */
5949 }
5950
5951 static int api_sr_multicast_map_add_del (vat_main_t * vam)
5952 {
5953   unformat_input_t * input = vam->input;
5954   vl_api_sr_multicast_map_add_del_t *mp;
5955   f64 timeout;
5956   int is_del = 0;
5957   ip6_address_t multicast_address;
5958   u8 * policy_name = 0;
5959   int multicast_address_set = 0;
5960
5961   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5962     {
5963       if (unformat (input, "del"))
5964         is_del = 1;
5965       else if (unformat (input, "address %U", unformat_ip6_address, &multicast_address))
5966         multicast_address_set = 1;
5967       else if (unformat (input, "sr-policy %s", &policy_name))
5968         ;
5969       else 
5970         break;
5971     }
5972
5973   if (!is_del && !policy_name)
5974     {
5975       errmsg ("sr-policy name required\n");
5976       return -99;
5977     }
5978
5979
5980   if (!multicast_address_set)
5981     {
5982       errmsg ("address required\n");
5983       return -99;
5984     }
5985
5986   M(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del);
5987
5988   mp->is_add = !is_del;
5989   memcpy (mp->policy_name, policy_name, vec_len(policy_name));
5990   clib_memcpy (mp->multicast_address, &multicast_address, sizeof (mp->multicast_address));
5991
5992
5993   vec_free (policy_name);
5994   
5995   S; W;
5996   /* NOTREACHED */
5997 }
5998
5999
6000 #define foreach_ip4_proto_field                 \
6001 _(src_address)                                  \
6002 _(dst_address)                                  \
6003 _(tos)                                          \
6004 _(length)                                       \
6005 _(fragment_id)                                  \
6006 _(ttl)                                          \
6007 _(protocol)                                     \
6008 _(checksum)
6009
6010 uword unformat_ip4_mask (unformat_input_t * input, va_list * args)
6011 {
6012   u8 ** maskp = va_arg (*args, u8 **);
6013   u8 * mask = 0;
6014   u8 found_something = 0;
6015   ip4_header_t * ip;
6016   
6017 #define _(a) u8 a=0;
6018   foreach_ip4_proto_field;
6019 #undef _
6020   u8 version = 0;
6021   u8 hdr_length = 0;
6022   
6023   
6024   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
6025     {
6026       if (unformat (input, "version")) 
6027         version = 1;
6028       else if (unformat (input, "hdr_length"))
6029         hdr_length = 1;
6030       else if (unformat (input, "src"))
6031         src_address = 1;
6032       else if (unformat (input, "dst"))
6033         dst_address = 1;
6034       else if (unformat (input, "proto"))
6035         protocol = 1;
6036       
6037 #define _(a) else if (unformat (input, #a)) a=1;
6038       foreach_ip4_proto_field
6039 #undef _
6040       else
6041         break;
6042     }
6043   
6044 #define _(a) found_something += a;
6045   foreach_ip4_proto_field;
6046 #undef _
6047   
6048   if (found_something == 0)
6049     return 0;
6050   
6051   vec_validate (mask, sizeof (*ip) - 1);
6052   
6053   ip = (ip4_header_t *) mask;
6054   
6055 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
6056   foreach_ip4_proto_field;
6057 #undef _
6058   
6059   ip->ip_version_and_header_length = 0;
6060   
6061   if (version)
6062     ip->ip_version_and_header_length |= 0xF0;
6063   
6064   if (hdr_length)
6065     ip->ip_version_and_header_length |= 0x0F;
6066   
6067   *maskp = mask;
6068   return 1;
6069 }
6070
6071 #define foreach_ip6_proto_field                 \
6072 _(src_address)                                  \
6073 _(dst_address)                                  \
6074 _(payload_length)                               \
6075 _(hop_limit)                                    \
6076 _(protocol)
6077
6078 uword unformat_ip6_mask (unformat_input_t * input, va_list * args)
6079 {
6080   u8 ** maskp = va_arg (*args, u8 **);
6081   u8 * mask = 0;
6082   u8 found_something = 0;
6083   ip6_header_t * ip;
6084   u32 ip_version_traffic_class_and_flow_label;
6085   
6086 #define _(a) u8 a=0;
6087   foreach_ip6_proto_field;
6088 #undef _
6089   u8 version = 0;
6090   u8 traffic_class = 0;
6091   u8 flow_label = 0;
6092   
6093   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
6094     {
6095       if (unformat (input, "version")) 
6096         version = 1;
6097       else if (unformat (input, "traffic-class"))
6098         traffic_class = 1;
6099       else if (unformat (input, "flow-label"))
6100         flow_label = 1;
6101       else if (unformat (input, "src"))
6102         src_address = 1;
6103       else if (unformat (input, "dst"))
6104         dst_address = 1;
6105       else if (unformat (input, "proto"))
6106         protocol = 1;
6107       
6108 #define _(a) else if (unformat (input, #a)) a=1;
6109       foreach_ip6_proto_field
6110 #undef _
6111       else
6112         break;
6113     }
6114   
6115 #define _(a) found_something += a;
6116   foreach_ip6_proto_field;
6117 #undef _
6118   
6119   if (found_something == 0)
6120     return 0;
6121   
6122   vec_validate (mask, sizeof (*ip) - 1);
6123   
6124   ip = (ip6_header_t *) mask;
6125   
6126 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
6127   foreach_ip6_proto_field;
6128 #undef _
6129   
6130   ip_version_traffic_class_and_flow_label = 0;
6131   
6132   if (version)
6133     ip_version_traffic_class_and_flow_label |= 0xF0000000;
6134
6135   if (traffic_class)
6136     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
6137
6138   if (flow_label)
6139     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
6140
6141   ip->ip_version_traffic_class_and_flow_label = 
6142     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
6143   
6144   *maskp = mask;
6145   return 1;
6146 }
6147
6148 uword unformat_l3_mask (unformat_input_t * input, va_list * args)
6149 {
6150   u8 ** maskp = va_arg (*args, u8 **);
6151
6152   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6153     if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
6154       return 1;
6155     else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
6156       return 1;
6157     else
6158       break;
6159   }
6160   return 0;
6161 }
6162
6163 uword unformat_l2_mask (unformat_input_t * input, va_list * args)
6164 {
6165   u8 ** maskp = va_arg (*args, u8 **);
6166   u8 * mask = 0;
6167   u8 src = 0;
6168   u8 dst = 0;
6169   u8 proto = 0;
6170   u8 tag1 = 0;
6171   u8 tag2 = 0;
6172   u8 ignore_tag1 = 0;
6173   u8 ignore_tag2 = 0;
6174   u8 cos1 = 0;
6175   u8 cos2 = 0;
6176   u8 dot1q = 0;
6177   u8 dot1ad = 0;
6178   int len = 14;
6179
6180   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6181     if (unformat (input, "src"))
6182       src = 1;
6183     else if (unformat (input, "dst"))
6184       dst = 1;
6185     else if (unformat (input, "proto"))
6186       proto = 1;
6187     else if (unformat (input, "tag1"))
6188       tag1 = 1;
6189     else if (unformat (input, "tag2"))
6190       tag2 = 1;
6191     else if (unformat (input, "ignore-tag1"))
6192       ignore_tag1 = 1;
6193     else if (unformat (input, "ignore-tag2"))
6194       ignore_tag2 = 1;
6195     else if (unformat (input, "cos1"))
6196       cos1 = 1;
6197     else if (unformat (input, "cos2"))
6198       cos2 = 1;
6199     else if (unformat (input, "dot1q"))
6200       dot1q = 1;
6201     else if (unformat (input, "dot1ad"))
6202       dot1ad = 1;
6203     else
6204       break;
6205   }
6206   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
6207       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
6208     return 0;
6209
6210   if (tag1 || ignore_tag1 || cos1 || dot1q)
6211     len = 18;
6212   if (tag2 || ignore_tag2 || cos2 || dot1ad)
6213     len = 22;
6214
6215   vec_validate (mask, len-1);
6216
6217   if (dst)
6218     memset (mask, 0xff, 6);
6219
6220   if (src)
6221     memset (mask + 6, 0xff, 6);
6222   
6223   if (tag2 || dot1ad)
6224     {
6225       /* inner vlan tag */
6226       if (tag2)
6227         {
6228           mask[19] = 0xff;
6229           mask[18] = 0x0f;
6230         }
6231       if (cos2)
6232         mask[18] |= 0xe0;
6233       if (proto)
6234           mask[21] = mask [20] = 0xff;
6235       if (tag1)
6236         {
6237           mask [15] = 0xff;
6238           mask [14] = 0x0f;
6239         }
6240       if (cos1)
6241         mask[14] |= 0xe0;
6242       *maskp = mask;
6243       return 1;
6244     }
6245   if (tag1 | dot1q)
6246     {
6247       if (tag1)
6248         {
6249           mask [15] = 0xff;
6250           mask [14] = 0x0f;
6251         }
6252       if (cos1)
6253         mask[14] |= 0xe0;
6254       if (proto)
6255           mask[16] = mask [17] = 0xff;
6256
6257       *maskp = mask;
6258       return 1;
6259     }
6260   if (cos2)
6261     mask[18] |= 0xe0;
6262   if (cos1)
6263     mask[14] |= 0xe0;
6264   if (proto)
6265     mask[12] = mask [13] = 0xff;
6266     
6267   *maskp = mask;
6268   return 1;
6269 }
6270
6271 uword unformat_classify_mask (unformat_input_t * input, va_list * args)
6272 {
6273   u8 ** maskp = va_arg (*args, u8 **);
6274   u32 * skipp = va_arg (*args, u32 *);
6275   u32 * matchp = va_arg (*args, u32 *);
6276   u32 match;
6277   u8 * mask = 0;
6278   u8 * l2 = 0;
6279   u8 * l3 = 0;
6280   int i;
6281   
6282   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6283     if (unformat (input, "hex %U", unformat_hex_string, &mask))
6284       ;
6285     else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
6286       ;
6287     else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
6288       ;
6289     else
6290       break;
6291   }
6292
6293   if (mask || l2 || l3)
6294     {
6295       if (l2 || l3)
6296         {
6297           /* "With a free Ethernet header in every package" */
6298           if (l2 == 0)
6299             vec_validate (l2, 13);
6300           mask = l2;
6301           vec_append (mask, l3);
6302           vec_free (l3);
6303         }
6304
6305       /* Scan forward looking for the first significant mask octet */
6306       for (i = 0; i < vec_len (mask); i++)
6307         if (mask[i])
6308           break;
6309
6310       /* compute (skip, match) params */
6311       *skipp = i / sizeof(u32x4);
6312       vec_delete (mask, *skipp * sizeof(u32x4), 0);
6313
6314       /* Pad mask to an even multiple of the vector size */
6315       while (vec_len (mask) % sizeof (u32x4))
6316         vec_add1 (mask, 0);
6317
6318       match = vec_len (mask) / sizeof (u32x4);
6319
6320       for (i = match*sizeof(u32x4); i > 0; i-= sizeof(u32x4))
6321         {
6322           u64 *tmp = (u64 *)(mask + (i-sizeof(u32x4)));
6323           if (*tmp || *(tmp+1))
6324             break;
6325           match--;
6326         }
6327       if (match == 0)
6328         clib_warning ("BUG: match 0");
6329
6330       _vec_len (mask) = match * sizeof(u32x4);
6331
6332       *matchp = match;
6333       *maskp = mask;
6334
6335       return 1;
6336     }
6337
6338   return 0;
6339 }
6340
6341 #define foreach_l2_next                         \
6342 _(drop, DROP)                                   \
6343 _(ethernet, ETHERNET_INPUT)                     \
6344 _(ip4, IP4_INPUT)                               \
6345 _(ip6, IP6_INPUT)
6346
6347 uword unformat_l2_next_index (unformat_input_t * input, va_list * args)
6348 {
6349   u32 * miss_next_indexp = va_arg (*args, u32 *);
6350   u32 next_index = 0;
6351   u32 tmp;
6352   
6353 #define _(n,N) \
6354   if (unformat (input, #n)) { next_index = L2_CLASSIFY_NEXT_##N; goto out;}
6355   foreach_l2_next;
6356 #undef _
6357   
6358   if (unformat (input, "%d", &tmp))
6359     { 
6360       next_index = tmp; 
6361       goto out; 
6362     }
6363   
6364   return 0;
6365
6366  out:
6367   *miss_next_indexp = next_index;
6368   return 1;
6369 }
6370
6371 #define foreach_ip_next                         \
6372 _(miss, MISS)                                   \
6373 _(drop, DROP)                                   \
6374 _(local, LOCAL)                                 \
6375 _(rewrite, REWRITE)
6376
6377 uword unformat_ip_next_index (unformat_input_t * input, va_list * args)
6378 {
6379   u32 * miss_next_indexp = va_arg (*args, u32 *);
6380   u32 next_index = 0;
6381   u32 tmp;
6382   
6383 #define _(n,N) \
6384   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
6385   foreach_ip_next;
6386 #undef _
6387   
6388   if (unformat (input, "%d", &tmp))
6389     { 
6390       next_index = tmp; 
6391       goto out; 
6392     }
6393   
6394   return 0;
6395
6396  out:
6397   *miss_next_indexp = next_index;
6398   return 1;
6399 }
6400
6401 #define foreach_acl_next                        \
6402 _(deny, DENY)
6403
6404 uword unformat_acl_next_index (unformat_input_t * input, va_list * args)
6405 {
6406   u32 * miss_next_indexp = va_arg (*args, u32 *);
6407   u32 next_index = 0;
6408   u32 tmp;
6409
6410 #define _(n,N) \
6411   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
6412   foreach_acl_next;
6413 #undef _
6414
6415   if (unformat (input, "permit"))
6416     {
6417       next_index = ~0;
6418       goto out;
6419     }
6420   else if (unformat (input, "%d", &tmp))
6421     {
6422       next_index = tmp;
6423       goto out;
6424     }
6425
6426   return 0;
6427
6428  out:
6429   *miss_next_indexp = next_index;
6430   return 1;
6431 }
6432
6433 static int api_classify_add_del_table (vat_main_t * vam)
6434 {
6435   unformat_input_t * i = vam->input;
6436   vl_api_classify_add_del_table_t *mp;
6437
6438   u32 nbuckets = 2;
6439   u32 skip = ~0;
6440   u32 match = ~0;
6441   int is_add = 1;
6442   u32 table_index = ~0;
6443   u32 next_table_index = ~0;
6444   u32 miss_next_index = ~0;
6445   u32 memory_size = 32<<20;
6446   u8 * mask = 0;
6447   f64 timeout;
6448
6449   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6450     if (unformat (i, "del"))
6451       is_add = 0;
6452     else if (unformat (i, "buckets %d", &nbuckets))
6453       ;
6454     else if (unformat (i, "memory_size %d", &memory_size))
6455       ;
6456     else if (unformat (i, "skip %d", &skip))
6457       ;
6458     else if (unformat (i, "match %d", &match))
6459       ;
6460     else if (unformat (i, "table %d", &table_index))
6461       ;
6462     else if (unformat (i, "mask %U", unformat_classify_mask, 
6463                        &mask, &skip, &match))
6464       ;
6465     else if (unformat (i, "next-table %d", &next_table_index))
6466       ;
6467     else if (unformat (i, "miss-next %U", unformat_ip_next_index,
6468                        &miss_next_index))
6469       ;
6470     else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
6471                        &miss_next_index))
6472       ;
6473     else if (unformat (i, "acl-miss-next %U", unformat_acl_next_index,
6474                        &miss_next_index))
6475       ;
6476     else
6477       break;
6478   }
6479   
6480   if (is_add && mask == 0) {
6481       errmsg ("Mask required\n");
6482       return -99;
6483   }
6484
6485   if (is_add && skip == ~0) {
6486       errmsg ("skip count required\n");
6487       return -99;
6488   }
6489
6490   if (is_add && match == ~0) {
6491       errmsg ("match count required\n");
6492       return -99;
6493   }
6494       
6495   if (!is_add && table_index == ~0) {
6496       errmsg ("table index required for delete\n");
6497       return -99;
6498   }
6499
6500   M2 (CLASSIFY_ADD_DEL_TABLE, classify_add_del_table,
6501       vec_len(mask));
6502
6503   mp->is_add = is_add;
6504   mp->table_index = ntohl(table_index);
6505   mp->nbuckets = ntohl(nbuckets);
6506   mp->memory_size = ntohl(memory_size);
6507   mp->skip_n_vectors = ntohl(skip);
6508   mp->match_n_vectors = ntohl(match);
6509   mp->next_table_index = ntohl(next_table_index);
6510   mp->miss_next_index = ntohl(miss_next_index);
6511   clib_memcpy (mp->mask, mask, vec_len(mask));
6512
6513   vec_free(mask);
6514
6515   S; W;
6516   /* NOTREACHED */
6517 }
6518
6519 uword unformat_ip4_match (unformat_input_t * input, va_list * args)
6520 {
6521   u8 ** matchp = va_arg (*args, u8 **);
6522   u8 * match = 0;
6523   ip4_header_t * ip;
6524   int version = 0;
6525   u32 version_val;
6526   int hdr_length = 0;
6527   u32 hdr_length_val;
6528   int src = 0, dst = 0;
6529   ip4_address_t src_val, dst_val;
6530   int proto = 0;
6531   u32 proto_val;
6532   int tos = 0;
6533   u32 tos_val;
6534   int length = 0;
6535   u32 length_val;
6536   int fragment_id = 0;
6537   u32 fragment_id_val;
6538   int ttl = 0;
6539   int ttl_val;
6540   int checksum = 0;
6541   u32 checksum_val;
6542
6543   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
6544     {
6545       if (unformat (input, "version %d", &version_val)) 
6546         version = 1;
6547       else if (unformat (input, "hdr_length %d", &hdr_length_val))
6548         hdr_length = 1;
6549       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
6550         src = 1;
6551       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
6552         dst = 1;
6553       else if (unformat (input, "proto %d", &proto_val))
6554         proto = 1;
6555       else if (unformat (input, "tos %d", &tos_val))
6556         tos = 1;
6557       else if (unformat (input, "length %d", &length_val))
6558         length = 1;
6559       else if (unformat (input, "fragment_id %d", &fragment_id_val))
6560         fragment_id = 1;
6561       else if (unformat (input, "ttl %d", &ttl_val))
6562         ttl = 1;
6563       else if (unformat (input, "checksum %d", &checksum_val))
6564         checksum = 1;
6565       else
6566         break;
6567     }
6568   
6569   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
6570       + ttl + checksum == 0)
6571     return 0;
6572
6573   /* 
6574    * Aligned because we use the real comparison functions
6575    */
6576   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
6577   
6578   ip = (ip4_header_t *) match;
6579   
6580   /* These are realistically matched in practice */
6581   if (src)
6582     ip->src_address.as_u32 = src_val.as_u32;
6583
6584   if (dst)
6585     ip->dst_address.as_u32 = dst_val.as_u32;
6586   
6587   if (proto)
6588     ip->protocol = proto_val;
6589     
6590
6591   /* These are not, but they're included for completeness */
6592   if (version)
6593     ip->ip_version_and_header_length |= (version_val & 0xF)<<4;
6594
6595   if (hdr_length)
6596     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
6597     
6598   if (tos)
6599     ip->tos = tos_val;
6600   
6601   if (length)
6602     ip->length = length_val;
6603   
6604   if (ttl)
6605     ip->ttl = ttl_val;
6606
6607   if (checksum)
6608     ip->checksum = checksum_val;
6609
6610   *matchp = match;
6611   return 1;
6612 }
6613
6614 uword unformat_ip6_match (unformat_input_t * input, va_list * args)
6615 {
6616   u8 ** matchp = va_arg (*args, u8 **);
6617   u8 * match = 0;
6618   ip6_header_t * ip;
6619   int version = 0;
6620   u32 version_val;
6621   u8  traffic_class;
6622   u32 traffic_class_val;
6623   u8  flow_label;
6624   u8  flow_label_val;
6625   int src = 0, dst = 0;
6626   ip6_address_t src_val, dst_val;
6627   int proto = 0;
6628   u32 proto_val;
6629   int payload_length = 0;
6630   u32 payload_length_val;
6631   int hop_limit = 0;
6632   int hop_limit_val;
6633   u32 ip_version_traffic_class_and_flow_label;
6634
6635   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
6636     {
6637       if (unformat (input, "version %d", &version_val)) 
6638         version = 1;
6639       else if (unformat (input, "traffic_class %d", &traffic_class_val))
6640         traffic_class = 1;
6641       else if (unformat (input, "flow_label %d", &flow_label_val))
6642         flow_label = 1;
6643       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
6644         src = 1;
6645       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
6646         dst = 1;
6647       else if (unformat (input, "proto %d", &proto_val))
6648         proto = 1;
6649       else if (unformat (input, "payload_length %d", &payload_length_val))
6650         payload_length = 1;
6651       else if (unformat (input, "hop_limit %d", &hop_limit_val))
6652         hop_limit = 1;
6653       else
6654         break;
6655     }
6656   
6657   if (version + traffic_class + flow_label + src + dst + proto +
6658       payload_length + hop_limit == 0)
6659     return 0;
6660
6661   /* 
6662    * Aligned because we use the real comparison functions
6663    */
6664   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
6665   
6666   ip = (ip6_header_t *) match;
6667   
6668   if (src)
6669     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
6670
6671   if (dst)
6672     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
6673   
6674   if (proto)
6675     ip->protocol = proto_val;
6676     
6677   ip_version_traffic_class_and_flow_label = 0;
6678
6679   if (version)
6680     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
6681
6682   if (traffic_class)
6683     ip_version_traffic_class_and_flow_label |= (traffic_class_val & 0xFF) << 20;
6684
6685   if (flow_label)
6686     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
6687     
6688   ip->ip_version_traffic_class_and_flow_label = 
6689     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
6690
6691   if (payload_length)
6692     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
6693   
6694   if (hop_limit)
6695     ip->hop_limit = hop_limit_val;
6696
6697   *matchp = match;
6698   return 1;
6699 }
6700
6701 uword unformat_l3_match (unformat_input_t * input, va_list * args)
6702 {
6703   u8 ** matchp = va_arg (*args, u8 **);
6704
6705   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6706     if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
6707       return 1;
6708     else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
6709       return 1;
6710     else
6711       break;
6712   }
6713   return 0;
6714 }
6715
6716 uword unformat_vlan_tag (unformat_input_t * input, va_list * args)
6717 {
6718   u8 * tagp = va_arg (*args, u8 *);
6719   u32 tag;
6720
6721   if (unformat(input, "%d", &tag))
6722     {
6723       tagp[0] = (tag>>8) & 0x0F;
6724       tagp[1] = tag & 0xFF;
6725       return 1;
6726     }
6727
6728   return 0;
6729 }
6730
6731 uword unformat_l2_match (unformat_input_t * input, va_list * args)
6732 {
6733   u8 ** matchp = va_arg (*args, u8 **);
6734   u8 * match = 0;
6735   u8 src = 0;
6736   u8 src_val[6];
6737   u8 dst = 0;
6738   u8 dst_val[6];
6739   u8 proto = 0;
6740   u16 proto_val;
6741   u8 tag1 = 0;
6742   u8 tag1_val [2];
6743   u8 tag2 = 0;
6744   u8 tag2_val [2];
6745   int len = 14;
6746   u8 ignore_tag1 = 0;
6747   u8 ignore_tag2 = 0;
6748   u8 cos1 = 0;
6749   u8 cos2 = 0;
6750   u32 cos1_val = 0;
6751   u32 cos2_val = 0;
6752
6753   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6754     if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
6755       src = 1;
6756     else if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
6757       dst = 1;
6758     else if (unformat (input, "proto %U", 
6759                        unformat_ethernet_type_host_byte_order, &proto_val))
6760       proto = 1;
6761     else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
6762       tag1 = 1;
6763     else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
6764       tag2 = 1;
6765     else if (unformat (input, "ignore-tag1"))
6766       ignore_tag1 = 1;
6767     else if (unformat (input, "ignore-tag2"))
6768       ignore_tag2 = 1;
6769     else if (unformat (input, "cos1 %d", &cos1_val))
6770       cos1 = 1;
6771     else if (unformat (input, "cos2 %d", &cos2_val))
6772       cos2 = 1;
6773     else
6774       break;
6775   }
6776   if ((src + dst + proto + tag1 + tag2 +
6777       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
6778     return 0;
6779
6780   if (tag1 || ignore_tag1 || cos1)
6781     len = 18;
6782   if (tag2 || ignore_tag2 || cos2)
6783     len = 22;
6784
6785   vec_validate_aligned (match, len-1, sizeof(u32x4));
6786
6787   if (dst)
6788     clib_memcpy (match, dst_val, 6);
6789
6790   if (src)
6791     clib_memcpy (match + 6, src_val, 6);
6792   
6793   if (tag2)
6794     {
6795       /* inner vlan tag */
6796       match[19] = tag2_val[1];
6797       match[18] = tag2_val[0];
6798       if (cos2)
6799         match [18] |= (cos2_val & 0x7) << 5;
6800       if (proto)
6801         {
6802           match[21] = proto_val & 0xff;
6803           match[20] = proto_val >> 8;
6804         }
6805       if (tag1)
6806         {
6807           match [15] = tag1_val[1];
6808           match [14] = tag1_val[0];
6809         }
6810       if (cos1)
6811         match [14] |= (cos1_val & 0x7) << 5;
6812       *matchp = match;
6813       return 1;
6814     }
6815   if (tag1)
6816     {
6817       match [15] = tag1_val[1];
6818       match [14] = tag1_val[0];
6819       if (proto)
6820         {
6821           match[17] = proto_val & 0xff;
6822           match[16] = proto_val >> 8;
6823         }
6824       if (cos1)
6825         match [14] |= (cos1_val & 0x7) << 5;
6826
6827       *matchp = match;
6828       return 1;
6829     }
6830   if (cos2)
6831     match [18] |= (cos2_val & 0x7) << 5;
6832   if (cos1)
6833     match [14] |= (cos1_val & 0x7) << 5;
6834   if (proto)
6835     {
6836       match[13] = proto_val & 0xff;
6837       match[12] = proto_val >> 8;
6838     }
6839   
6840   *matchp = match;
6841   return 1;
6842 }
6843
6844
6845 uword unformat_classify_match (unformat_input_t * input, va_list * args)
6846 {
6847   u8 ** matchp = va_arg (*args, u8 **);
6848   u32 skip_n_vectors = va_arg (*args, u32);
6849   u32 match_n_vectors = va_arg (*args, u32);
6850   
6851   u8 * match = 0;
6852   u8 * l2 = 0;
6853   u8 * l3 = 0;
6854
6855   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6856     if (unformat (input, "hex %U", unformat_hex_string, &match))
6857       ;
6858     else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
6859       ;
6860     else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
6861       ;
6862     else
6863       break;
6864   }
6865
6866   if (match || l2 || l3)
6867     {
6868       if (l2 || l3)
6869         {
6870           /* "Win a free Ethernet header in every packet" */
6871           if (l2 == 0)
6872             vec_validate_aligned (l2, 13, sizeof(u32x4));
6873           match = l2;
6874           vec_append_aligned (match, l3, sizeof(u32x4));
6875           vec_free (l3);
6876         }
6877
6878       /* Make sure the vector is big enough even if key is all 0's */
6879       vec_validate_aligned 
6880           (match, ((match_n_vectors + skip_n_vectors) * sizeof(u32x4)) - 1,
6881            sizeof(u32x4));
6882       
6883       /* Set size, include skipped vectors*/
6884       _vec_len (match) = (match_n_vectors+skip_n_vectors) * sizeof(u32x4);
6885
6886       *matchp = match;
6887
6888       return 1;
6889     }
6890
6891   return 0;
6892 }
6893
6894 static int api_classify_add_del_session (vat_main_t * vam)
6895 {
6896     unformat_input_t * i = vam->input;
6897     vl_api_classify_add_del_session_t *mp;
6898     int is_add = 1;
6899     u32 table_index = ~0;
6900     u32 hit_next_index = ~0;
6901     u32 opaque_index = ~0;
6902     u8 * match = 0;
6903     i32 advance = 0;
6904     f64 timeout;
6905     u32 skip_n_vectors = 0;
6906     u32 match_n_vectors = 0;
6907
6908     /* 
6909      * Warning: you have to supply skip_n and match_n
6910      * because the API client cant simply look at the classify
6911      * table object.
6912      */
6913
6914     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6915         if (unformat (i, "del"))
6916             is_add = 0;
6917         else if (unformat (i, "hit-next %U", unformat_ip_next_index,
6918                            &hit_next_index))
6919             ;
6920         else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
6921                            &hit_next_index))
6922             ;
6923         else if (unformat (i, "acl-hit-next %U", unformat_acl_next_index,
6924                            &hit_next_index))
6925             ;
6926         else if (unformat (i, "opaque-index %d", &opaque_index))
6927             ;
6928         else if (unformat (i, "skip_n %d", &skip_n_vectors))
6929             ;
6930         else if (unformat (i, "match_n %d", &match_n_vectors))
6931             ;
6932         else if (unformat (i, "match %U", unformat_classify_match,
6933                            &match, skip_n_vectors, match_n_vectors))
6934             ;
6935         else if (unformat (i, "advance %d", &advance))
6936             ;
6937         else if (unformat (i, "table-index %d", &table_index))
6938             ;
6939         else
6940             break;
6941     }
6942
6943     if (table_index == ~0) {
6944         errmsg ("Table index required\n");
6945         return -99;
6946     }
6947
6948     if (is_add && match == 0) {
6949         errmsg ("Match value required\n");
6950         return -99;
6951     }
6952
6953     M2 (CLASSIFY_ADD_DEL_SESSION, classify_add_del_session,
6954         vec_len(match));
6955
6956     mp->is_add = is_add;
6957     mp->table_index = ntohl(table_index);
6958     mp->hit_next_index = ntohl(hit_next_index);
6959     mp->opaque_index = ntohl(opaque_index);
6960     mp->advance = ntohl(advance);
6961     clib_memcpy (mp->match, match, vec_len(match));
6962     vec_free(match);
6963
6964     S; W;
6965     /* NOTREACHED */
6966 }
6967
6968 static int api_classify_set_interface_ip_table (vat_main_t * vam)
6969 {
6970     unformat_input_t * i = vam->input;
6971     vl_api_classify_set_interface_ip_table_t *mp;
6972     f64 timeout;
6973     u32 sw_if_index;
6974     int sw_if_index_set;
6975     u32 table_index = ~0;
6976     u8  is_ipv6 = 0;
6977
6978     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6979         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6980             sw_if_index_set = 1;
6981         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6982             sw_if_index_set = 1;
6983         else if (unformat (i, "table %d", &table_index))
6984             ;
6985         else {
6986             clib_warning ("parse error '%U'", format_unformat_error, i);
6987             return -99;
6988         }
6989     }
6990     
6991     if (sw_if_index_set == 0) {
6992         errmsg ("missing interface name or sw_if_index\n");
6993         return -99;
6994     }
6995
6996
6997     M(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table);
6998
6999     mp->sw_if_index = ntohl(sw_if_index);
7000     mp->table_index = ntohl(table_index);
7001     mp->is_ipv6 = is_ipv6;
7002
7003     S; W;
7004     /* NOTREACHED */
7005     return 0;
7006 }
7007
7008 static int api_classify_set_interface_l2_tables (vat_main_t * vam)
7009 {
7010     unformat_input_t * i = vam->input;
7011     vl_api_classify_set_interface_l2_tables_t *mp;
7012     f64 timeout;
7013     u32 sw_if_index;
7014     int sw_if_index_set;
7015     u32 ip4_table_index = ~0;
7016     u32 ip6_table_index = ~0;
7017     u32 other_table_index = ~0;
7018
7019     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7020         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7021             sw_if_index_set = 1;
7022         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7023             sw_if_index_set = 1;
7024         else if (unformat (i, "ip4-table %d", &ip4_table_index))
7025             ;
7026         else if (unformat (i, "ip6-table %d", &ip6_table_index))
7027             ;
7028         else if (unformat (i, "other-table %d", &other_table_index))
7029             ;
7030         else {
7031             clib_warning ("parse error '%U'", format_unformat_error, i);
7032             return -99;
7033         }
7034     }
7035     
7036     if (sw_if_index_set == 0) {
7037         errmsg ("missing interface name or sw_if_index\n");
7038         return -99;
7039     }
7040
7041
7042     M(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables);
7043
7044     mp->sw_if_index = ntohl(sw_if_index);
7045     mp->ip4_table_index = ntohl(ip4_table_index);
7046     mp->ip6_table_index = ntohl(ip6_table_index);
7047     mp->other_table_index = ntohl(other_table_index);
7048
7049
7050     S; W;
7051     /* NOTREACHED */
7052     return 0;
7053 }
7054
7055 static int api_get_node_index (vat_main_t * vam)
7056 {
7057     unformat_input_t * i = vam->input;
7058     vl_api_get_node_index_t * mp;
7059     f64 timeout;
7060     u8 * name = 0;
7061     
7062     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7063         if (unformat (i, "node %s", &name))
7064             ;
7065         else
7066             break;
7067     }
7068     if (name == 0) {
7069         errmsg ("node name required\n");
7070         return -99;
7071     }
7072     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
7073         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
7074         return -99;
7075     }
7076
7077     M(GET_NODE_INDEX, get_node_index);
7078     clib_memcpy (mp->node_name, name, vec_len(name));
7079     vec_free(name);
7080     
7081     S; W;
7082     /* NOTREACHED */
7083     return 0;
7084 }
7085
7086 static int api_add_node_next (vat_main_t * vam)
7087 {
7088     unformat_input_t * i = vam->input;
7089     vl_api_add_node_next_t * mp;
7090     f64 timeout;
7091     u8 * name = 0;
7092     u8 * next = 0;
7093
7094     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7095         if (unformat (i, "node %s", &name))
7096             ;
7097         else if (unformat (i, "next %s", &next))
7098             ;
7099         else
7100             break;
7101     }
7102     if (name == 0) {
7103         errmsg ("node name required\n");
7104         return -99;
7105     }
7106     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
7107         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
7108         return -99;
7109     }
7110     if (next == 0) {
7111         errmsg ("next node required\n");
7112         return -99;
7113     }
7114     if (vec_len (next) >= ARRAY_LEN(mp->next_name)) {
7115         errmsg ("next name too long, max %d\n", ARRAY_LEN(mp->next_name));
7116         return -99;
7117     }
7118     
7119     M(ADD_NODE_NEXT, add_node_next);
7120     clib_memcpy (mp->node_name, name, vec_len(name));
7121     clib_memcpy (mp->next_name, next, vec_len(next));
7122     vec_free(name);
7123     vec_free(next);
7124     
7125     S; W;
7126     /* NOTREACHED */
7127     return 0;
7128 }
7129
7130 static int api_l2tpv3_create_tunnel (vat_main_t * vam)
7131 {
7132     unformat_input_t * i = vam->input;
7133     ip6_address_t client_address, our_address;
7134     int client_address_set = 0;
7135     int our_address_set = 0;
7136     u32 local_session_id = 0;
7137     u32 remote_session_id = 0;
7138     u64 local_cookie = 0;
7139     u64 remote_cookie = 0;
7140     u8 l2_sublayer_present = 0;
7141     vl_api_l2tpv3_create_tunnel_t * mp;
7142     f64 timeout;
7143
7144     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7145         if (unformat (i, "client_address %U", unformat_ip6_address, 
7146                       &client_address))
7147             client_address_set = 1;
7148         else if (unformat (i, "our_address %U", unformat_ip6_address, 
7149                            &our_address))
7150             our_address_set = 1;
7151         else if (unformat (i, "local_session_id %d", &local_session_id))
7152             ;
7153         else if (unformat (i, "remote_session_id %d", &remote_session_id))
7154             ;
7155         else if (unformat (i, "local_cookie %lld", &local_cookie))
7156             ;
7157         else if (unformat (i, "remote_cookie %lld", &remote_cookie))
7158             ;
7159         else if (unformat (i, "l2-sublayer-present"))
7160             l2_sublayer_present = 1;
7161         else
7162             break;
7163     }
7164
7165     if (client_address_set == 0) {
7166         errmsg ("client_address required\n");
7167         return -99;
7168     }
7169
7170     if (our_address_set == 0) {
7171         errmsg ("our_address required\n");
7172         return -99;
7173     }
7174
7175     M(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel);
7176
7177     clib_memcpy (mp->client_address, client_address.as_u8, 
7178             sizeof (mp->client_address));
7179
7180     clib_memcpy (mp->our_address, our_address.as_u8, 
7181             sizeof (mp->our_address));
7182     
7183     mp->local_session_id = ntohl (local_session_id);
7184     mp->remote_session_id = ntohl (remote_session_id);
7185     mp->local_cookie = clib_host_to_net_u64 (local_cookie);
7186     mp->remote_cookie = clib_host_to_net_u64 (remote_cookie);
7187     mp->l2_sublayer_present = l2_sublayer_present;
7188     mp->is_ipv6 = 1;
7189
7190     S; W;
7191     /* NOTREACHED */
7192     return 0;
7193 }
7194
7195 static int api_l2tpv3_set_tunnel_cookies (vat_main_t * vam)
7196 {
7197     unformat_input_t * i = vam->input;
7198     u32 sw_if_index;
7199     u8  sw_if_index_set = 0;
7200     u64 new_local_cookie = 0;
7201     u64 new_remote_cookie = 0;
7202     vl_api_l2tpv3_set_tunnel_cookies_t *mp;
7203     f64 timeout;
7204
7205     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7206         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7207             sw_if_index_set = 1;
7208         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7209             sw_if_index_set = 1;
7210         else if (unformat (i, "new_local_cookie %lld", &new_local_cookie))
7211             ;
7212         else if (unformat (i, "new_remote_cookie %lld", &new_remote_cookie))
7213             ;
7214         else
7215             break;
7216     }
7217
7218     if (sw_if_index_set == 0) {
7219         errmsg ("missing interface name or sw_if_index\n");
7220         return -99;
7221     }
7222
7223     M(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies);
7224
7225     mp->sw_if_index = ntohl(sw_if_index);
7226     mp->new_local_cookie = clib_host_to_net_u64 (new_local_cookie);
7227     mp->new_remote_cookie = clib_host_to_net_u64 (new_remote_cookie);
7228
7229     S; W;
7230     /* NOTREACHED */
7231     return 0;
7232 }
7233
7234 static int api_l2tpv3_interface_enable_disable (vat_main_t * vam)
7235 {
7236     unformat_input_t * i = vam->input;
7237     vl_api_l2tpv3_interface_enable_disable_t *mp;
7238     f64 timeout;
7239     u32 sw_if_index;
7240     u8  sw_if_index_set = 0;
7241     u8  enable_disable = 1;
7242
7243     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7244         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7245             sw_if_index_set = 1;
7246         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7247             sw_if_index_set = 1;
7248         else if (unformat (i, "enable"))
7249             enable_disable = 1;
7250         else if (unformat (i, "disable"))
7251             enable_disable = 0;
7252         else
7253             break;
7254     }
7255
7256     if (sw_if_index_set == 0) {
7257         errmsg ("missing interface name or sw_if_index\n");
7258         return -99;
7259     }
7260     
7261     M(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable);
7262
7263     mp->sw_if_index = ntohl(sw_if_index);
7264     mp->enable_disable = enable_disable;
7265
7266     S; W;
7267     /* NOTREACHED */
7268     return 0;
7269 }
7270
7271 static int api_l2tpv3_set_lookup_key (vat_main_t * vam)
7272 {
7273     unformat_input_t * i = vam->input;
7274     vl_api_l2tpv3_set_lookup_key_t * mp;
7275     f64 timeout;
7276     u8 key = ~0;
7277
7278     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7279         if (unformat (i, "lookup_v6_src"))
7280             key = L2T_LOOKUP_SRC_ADDRESS;
7281         else if (unformat (i, "lookup_v6_dst"))
7282             key = L2T_LOOKUP_DST_ADDRESS;
7283         else if (unformat (i, "lookup_session_id"))
7284             key = L2T_LOOKUP_SESSION_ID;
7285         else
7286             break;
7287     }
7288
7289     if (key == (u8) ~0) {
7290         errmsg ("l2tp session lookup key unset\n");
7291         return -99;
7292     }
7293     
7294     M(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key);
7295
7296     mp->key = key;
7297
7298     S; W;
7299     /* NOTREACHED */
7300     return 0;
7301 }
7302
7303 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler
7304 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
7305 {
7306     vat_main_t * vam = &vat_main;
7307
7308     fformat(vam->ofp,  "* %U (our) %U (client) (sw_if_index %d)\n",
7309               format_ip6_address, mp->our_address,
7310               format_ip6_address, mp->client_address,
7311               clib_net_to_host_u32(mp->sw_if_index));
7312
7313     fformat (vam->ofp, "   local cookies %016llx %016llx remote cookie %016llx\n",
7314               clib_net_to_host_u64 (mp->local_cookie[0]),
7315               clib_net_to_host_u64 (mp->local_cookie[1]),
7316               clib_net_to_host_u64 (mp->remote_cookie));
7317
7318     fformat (vam->ofp, "   local session-id %d remote session-id %d\n",
7319               clib_net_to_host_u32 (mp->local_session_id),
7320               clib_net_to_host_u32 (mp->remote_session_id));
7321
7322     fformat (vam->ofp, "   l2 specific sublayer %s\n\n",
7323               mp->l2_sublayer_present ? "preset" : "absent");
7324
7325 }
7326
7327 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler_json
7328 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
7329 {
7330     vat_main_t * vam = &vat_main;
7331     vat_json_node_t *node = NULL;
7332     struct in6_addr addr;
7333
7334     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7335         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7336         vat_json_init_array(&vam->json_tree);
7337     }
7338     node = vat_json_array_add(&vam->json_tree);
7339
7340     vat_json_init_object(node);
7341
7342     clib_memcpy(&addr, mp->our_address, sizeof(addr));
7343     vat_json_object_add_ip6(node, "our_address", addr);
7344     clib_memcpy(&addr, mp->client_address, sizeof(addr));
7345     vat_json_object_add_ip6(node, "client_address", addr);
7346
7347     vat_json_node_t * lc = vat_json_object_add(node, "local_cookie");
7348     vat_json_init_array(lc);
7349     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[0]));
7350     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[1]));
7351     vat_json_object_add_uint(node, "remote_cookie", clib_net_to_host_u64(mp->remote_cookie));
7352
7353     printf("local id: %u", clib_net_to_host_u32(mp->local_session_id));
7354     vat_json_object_add_uint(node, "local_session_id", clib_net_to_host_u32(mp->local_session_id));
7355     vat_json_object_add_uint(node, "remote_session_id", clib_net_to_host_u32(mp->remote_session_id));
7356     vat_json_object_add_string_copy(node, "l2_sublayer", mp->l2_sublayer_present ?
7357             (u8*)"present" : (u8*)"absent");
7358 }
7359
7360 static int api_sw_if_l2tpv3_tunnel_dump (vat_main_t * vam)
7361 {
7362     vl_api_sw_if_l2tpv3_tunnel_dump_t *mp;
7363     f64 timeout;
7364
7365     /* Get list of l2tpv3-tunnel interfaces */
7366     M(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump);
7367     S;
7368
7369     /* Use a control ping for synchronization */
7370     {
7371         vl_api_control_ping_t * mp;
7372         M(CONTROL_PING, control_ping);
7373         S;
7374     }
7375     W;
7376 }
7377
7378
7379 static void vl_api_sw_interface_tap_details_t_handler
7380 (vl_api_sw_interface_tap_details_t * mp)
7381 {
7382     vat_main_t * vam = &vat_main;
7383
7384     fformat(vam->ofp,  "%-16s %d\n",
7385               mp->dev_name,
7386               clib_net_to_host_u32(mp->sw_if_index));
7387 }
7388
7389 static void vl_api_sw_interface_tap_details_t_handler_json
7390 (vl_api_sw_interface_tap_details_t * mp)
7391 {
7392     vat_main_t * vam = &vat_main;
7393     vat_json_node_t *node = NULL;
7394
7395     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7396         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7397         vat_json_init_array(&vam->json_tree);
7398     }
7399     node = vat_json_array_add(&vam->json_tree);
7400
7401     vat_json_init_object(node);
7402     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7403     vat_json_object_add_string_copy(node, "dev_name", mp->dev_name);
7404 }
7405
7406 static int api_sw_interface_tap_dump (vat_main_t * vam)
7407 {
7408     vl_api_sw_interface_tap_dump_t *mp;
7409     f64 timeout;
7410
7411     fformat(vam->ofp,  "\n%-16s %s\n", "dev_name", "sw_if_index");
7412     /* Get list of tap interfaces */
7413     M(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump);
7414     S;
7415
7416     /* Use a control ping for synchronization */
7417     {
7418         vl_api_control_ping_t * mp;
7419         M(CONTROL_PING, control_ping);
7420         S;
7421     }
7422     W;
7423 }
7424
7425 static uword unformat_vxlan_decap_next 
7426 (unformat_input_t * input, va_list * args)
7427 {
7428   u32 * result = va_arg (*args, u32 *);
7429   u32 tmp;
7430   
7431   if (unformat (input, "drop"))
7432     *result = VXLAN_INPUT_NEXT_DROP;
7433   else if (unformat (input, "ip4"))
7434     *result = VXLAN_INPUT_NEXT_IP4_INPUT;
7435   else if (unformat (input, "ip6"))
7436     *result = VXLAN_INPUT_NEXT_IP6_INPUT;
7437   else if (unformat (input, "l2"))
7438     *result = VXLAN_INPUT_NEXT_L2_INPUT;
7439   else if (unformat (input, "%d", &tmp))
7440     *result = tmp;
7441   else
7442     return 0;
7443   return 1;
7444 }
7445
7446 static int api_vxlan_add_del_tunnel (vat_main_t * vam)
7447 {
7448     unformat_input_t * line_input = vam->input;
7449     vl_api_vxlan_add_del_tunnel_t *mp;
7450     f64 timeout;
7451     ip4_address_t src4, dst4;
7452     ip6_address_t src6, dst6;
7453     u8 is_add = 1;
7454     u8 ipv4_set = 0, ipv6_set = 0;
7455     u8 src_set = 0;
7456     u8 dst_set = 0;
7457     u32 encap_vrf_id = 0;
7458     u32 decap_next_index = ~0;
7459     u32 vni = 0;
7460
7461     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7462         if (unformat (line_input, "del"))
7463             is_add = 0;
7464         else if (unformat (line_input, "src %U", 
7465                            unformat_ip4_address, &src4))
7466           {
7467             ipv4_set = 1;
7468             src_set = 1;
7469           }
7470         else if (unformat (line_input, "dst %U",
7471                            unformat_ip4_address, &dst4))
7472           {
7473             ipv4_set = 1;
7474             dst_set = 1;
7475           }
7476         else if (unformat (line_input, "src %U", 
7477                            unformat_ip6_address, &src6))
7478           {
7479             ipv6_set = 1;
7480             src_set = 1;
7481           }
7482         else if (unformat (line_input, "dst %U",
7483                            unformat_ip6_address, &dst6))
7484           {
7485             ipv6_set = 1;
7486             dst_set = 1;
7487           }
7488         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7489             ;
7490         else if (unformat (line_input, "decap-next %U", 
7491                            unformat_vxlan_decap_next, &decap_next_index))
7492             ;
7493         else if (unformat (line_input, "vni %d", &vni))
7494             ;
7495         else {
7496             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7497             return -99;
7498         }
7499     }
7500
7501     if (src_set == 0) {
7502         errmsg ("tunnel src address not specified\n");
7503         return -99;
7504     }
7505     if (dst_set == 0) {
7506         errmsg ("tunnel dst address not specified\n");
7507         return -99;
7508     }
7509
7510     if (ipv4_set && ipv6_set) {
7511         errmsg ("both IPv4 and IPv6 addresses specified");
7512         return -99;
7513     }
7514
7515     if ((vni == 0) || (vni>>24)) {
7516         errmsg ("vni not specified or out of range\n");
7517         return -99;
7518     }
7519
7520     M (VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel);
7521
7522     if (ipv6_set) {
7523         clib_memcpy(&mp->src_address, &src6, sizeof(src6));
7524         clib_memcpy(&mp->dst_address, &dst6, sizeof(dst6));
7525     } else { 
7526         clib_memcpy(&mp->src_address, &src4, sizeof(src4));
7527         clib_memcpy(&mp->dst_address, &dst4, sizeof(dst4));
7528     }
7529     mp->encap_vrf_id = ntohl(encap_vrf_id);
7530     mp->decap_next_index = ntohl(decap_next_index);
7531     mp->vni = ntohl(vni);
7532     mp->is_add = is_add;
7533     mp->is_ipv6 = ipv6_set;
7534
7535     S; W;
7536     /* NOTREACHED */
7537     return 0;
7538 }
7539
7540 static void vl_api_vxlan_tunnel_details_t_handler
7541 (vl_api_vxlan_tunnel_details_t * mp)
7542 {
7543     vat_main_t * vam = &vat_main;
7544
7545     fformat(vam->ofp, "%11d%24U%24U%14d%18d%13d\n",
7546             ntohl(mp->sw_if_index),
7547             format_ip46_address, &(mp->src_address[0]),
7548             IP46_TYPE_ANY,
7549             format_ip46_address, &(mp->dst_address[0]),
7550             IP46_TYPE_ANY,
7551             ntohl(mp->encap_vrf_id),
7552             ntohl(mp->decap_next_index),
7553             ntohl(mp->vni));
7554 }
7555
7556 static void vl_api_vxlan_tunnel_details_t_handler_json
7557 (vl_api_vxlan_tunnel_details_t * mp)
7558 {
7559     vat_main_t * vam = &vat_main;
7560     vat_json_node_t *node = NULL;
7561     struct in_addr ip4;
7562     struct in6_addr ip6;
7563
7564     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7565         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7566         vat_json_init_array(&vam->json_tree);
7567     }
7568     node = vat_json_array_add(&vam->json_tree);
7569
7570     vat_json_init_object(node);
7571     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7572     if (mp->is_ipv6) {
7573         clib_memcpy(&ip6, &(mp->src_address[0]), sizeof(ip6));
7574         vat_json_object_add_ip6(node, "src_address", ip6);
7575         clib_memcpy(&ip6, &(mp->dst_address[0]), sizeof(ip6));
7576         vat_json_object_add_ip6(node, "dst_address", ip6);
7577     } else {
7578         clib_memcpy(&ip4, &(mp->src_address[0]), sizeof(ip4));
7579         vat_json_object_add_ip4(node, "src_address", ip4);
7580         clib_memcpy(&ip4, &(mp->dst_address[0]), sizeof(ip4));
7581         vat_json_object_add_ip4(node, "dst_address", ip4);
7582     }
7583     vat_json_object_add_uint(node, "encap_vrf_id", ntohl(mp->encap_vrf_id));
7584     vat_json_object_add_uint(node, "decap_next_index", ntohl(mp->decap_next_index));
7585     vat_json_object_add_uint(node, "vni", ntohl(mp->vni));
7586     vat_json_object_add_uint(node, "is_ipv6", mp->is_ipv6 ? 1 : 0);
7587 }
7588
7589 static int api_vxlan_tunnel_dump (vat_main_t * vam)
7590 {
7591     unformat_input_t * i = vam->input;
7592     vl_api_vxlan_tunnel_dump_t *mp;
7593     f64 timeout;
7594     u32 sw_if_index;
7595     u8 sw_if_index_set = 0;
7596
7597     /* Parse args required to build the message */
7598     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7599         if (unformat (i, "sw_if_index %d", &sw_if_index))
7600             sw_if_index_set = 1;
7601         else
7602             break;
7603     }
7604
7605     if (sw_if_index_set == 0) {
7606         sw_if_index = ~0;
7607     }
7608
7609     if (!vam->json_output) {
7610         fformat(vam->ofp, "%11s%24s%24s%14s%18s%13s\n",
7611                 "sw_if_index", "src_address", "dst_address",
7612                 "encap_vrf_id", "decap_next_index", "vni");
7613     }
7614
7615     /* Get list of vxlan-tunnel interfaces */
7616     M(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump);
7617
7618     mp->sw_if_index = htonl(sw_if_index);
7619
7620     S;
7621
7622     /* Use a control ping for synchronization */
7623     {
7624         vl_api_control_ping_t * mp;
7625         M(CONTROL_PING, control_ping);
7626         S;
7627     }
7628     W;
7629 }
7630
7631 static int api_gre_add_del_tunnel (vat_main_t * vam)
7632 {
7633     unformat_input_t * line_input = vam->input;
7634     vl_api_gre_add_del_tunnel_t *mp;
7635     f64 timeout;
7636     ip4_address_t src4, dst4;
7637     u8 is_add = 1;
7638     u8 src_set = 0;
7639     u8 dst_set = 0;
7640     u32 outer_fib_id = 0;
7641
7642     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7643         if (unformat (line_input, "del"))
7644             is_add = 0;
7645         else if (unformat (line_input, "src %U",
7646                            unformat_ip4_address, &src4))
7647             src_set = 1;
7648         else if (unformat (line_input, "dst %U",
7649                            unformat_ip4_address, &dst4))
7650             dst_set = 1;
7651         else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id))
7652             ;
7653         else {
7654             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7655             return -99;
7656         }
7657     }
7658
7659     if (src_set == 0) {
7660         errmsg ("tunnel src address not specified\n");
7661         return -99;
7662     }
7663     if (dst_set == 0) {
7664         errmsg ("tunnel dst address not specified\n");
7665         return -99;
7666     }
7667
7668
7669     M (GRE_ADD_DEL_TUNNEL, gre_add_del_tunnel);
7670
7671     clib_memcpy(&mp->src_address, &src4, sizeof(src4));
7672     clib_memcpy(&mp->dst_address, &dst4, sizeof(dst4));
7673     mp->outer_table_id = ntohl(outer_fib_id);
7674     mp->is_add = is_add;
7675
7676     S; W;
7677     /* NOTREACHED */
7678     return 0;
7679 }
7680
7681 static void vl_api_gre_tunnel_details_t_handler
7682 (vl_api_gre_tunnel_details_t * mp)
7683 {
7684     vat_main_t * vam = &vat_main;
7685
7686     fformat(vam->ofp, "%11d%15U%15U%14d\n",
7687             ntohl(mp->sw_if_index),
7688             format_ip4_address, &mp->src_address,
7689             format_ip4_address, &mp->dst_address,
7690             ntohl(mp->outer_table_id));
7691 }
7692
7693 static void vl_api_gre_tunnel_details_t_handler_json
7694 (vl_api_gre_tunnel_details_t * mp)
7695 {
7696     vat_main_t * vam = &vat_main;
7697     vat_json_node_t *node = NULL;
7698     struct in_addr ip4;
7699
7700     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7701         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7702         vat_json_init_array(&vam->json_tree);
7703     }
7704     node = vat_json_array_add(&vam->json_tree);
7705
7706     vat_json_init_object(node);
7707     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7708     clib_memcpy(&ip4, &mp->src_address, sizeof(ip4));
7709     vat_json_object_add_ip4(node, "src_address", ip4);
7710     clib_memcpy(&ip4, &mp->dst_address, sizeof(ip4));
7711     vat_json_object_add_ip4(node, "dst_address", ip4);
7712     vat_json_object_add_uint(node, "outer_fib_id", ntohl(mp->outer_table_id));
7713 }
7714
7715 static int api_gre_tunnel_dump (vat_main_t * vam)
7716 {
7717     unformat_input_t * i = vam->input;
7718     vl_api_gre_tunnel_dump_t *mp;
7719     f64 timeout;
7720     u32 sw_if_index;
7721     u8 sw_if_index_set = 0;
7722
7723     /* Parse args required to build the message */
7724     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7725         if (unformat (i, "sw_if_index %d", &sw_if_index))
7726             sw_if_index_set = 1;
7727         else
7728             break;
7729     }
7730
7731     if (sw_if_index_set == 0) {
7732         sw_if_index = ~0;
7733     }
7734
7735     if (!vam->json_output) {
7736         fformat(vam->ofp, "%11s%15s%15s%14s\n",
7737                 "sw_if_index", "src_address", "dst_address",
7738                 "outer_fib_id");
7739     }
7740
7741     /* Get list of gre-tunnel interfaces */
7742     M(GRE_TUNNEL_DUMP, gre_tunnel_dump);
7743
7744     mp->sw_if_index = htonl(sw_if_index);
7745
7746     S;
7747
7748     /* Use a control ping for synchronization */
7749     {
7750         vl_api_control_ping_t * mp;
7751         M(CONTROL_PING, control_ping);
7752         S;
7753     }
7754     W;
7755 }
7756
7757 static int api_l2_fib_clear_table (vat_main_t * vam)
7758 {
7759 //  unformat_input_t * i = vam->input;
7760     vl_api_l2_fib_clear_table_t *mp;
7761     f64 timeout;
7762
7763     M(L2_FIB_CLEAR_TABLE, l2_fib_clear_table);
7764
7765     S; W;
7766     /* NOTREACHED */
7767     return 0;
7768 }
7769
7770 static int api_l2_interface_efp_filter (vat_main_t * vam)
7771 {
7772     unformat_input_t * i = vam->input;
7773     vl_api_l2_interface_efp_filter_t *mp;
7774     f64 timeout;
7775     u32 sw_if_index;
7776     u8 enable = 1;
7777     u8 sw_if_index_set = 0;
7778
7779     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7780         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7781             sw_if_index_set = 1;
7782         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7783             sw_if_index_set = 1;
7784         else if (unformat (i, "enable"))
7785             enable = 1;
7786         else if (unformat (i, "disable"))
7787             enable = 0;
7788         else {
7789             clib_warning ("parse error '%U'", format_unformat_error, i);
7790             return -99;
7791         }
7792     }
7793     
7794     if (sw_if_index_set == 0) {
7795         errmsg ("missing sw_if_index\n");
7796         return -99;
7797     }
7798
7799     M(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter);
7800
7801     mp->sw_if_index = ntohl(sw_if_index);
7802     mp->enable_disable = enable;
7803
7804     S; W;
7805     /* NOTREACHED */
7806     return 0;
7807 }
7808
7809 #define foreach_vtr_op                          \
7810 _("disable",  L2_VTR_DISABLED)                  \
7811 _("push-1",  L2_VTR_PUSH_1)                     \
7812 _("push-2",  L2_VTR_PUSH_2)                     \
7813 _("pop-1",  L2_VTR_POP_1)                       \
7814 _("pop-2",  L2_VTR_POP_2)                       \
7815 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
7816 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
7817 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
7818 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
7819
7820 static int api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
7821 {
7822     unformat_input_t * i = vam->input;
7823     vl_api_l2_interface_vlan_tag_rewrite_t *mp;
7824     f64 timeout;
7825     u32 sw_if_index;
7826     u8 sw_if_index_set = 0;
7827     u8 vtr_op_set = 0;
7828     u32 vtr_op = 0;
7829     u32 push_dot1q = 1;
7830     u32 tag1 = ~0;
7831     u32 tag2 = ~0;
7832
7833     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7834         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7835             sw_if_index_set = 1;
7836         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7837             sw_if_index_set = 1;
7838         else if (unformat (i, "vtr_op %d", &vtr_op))
7839             vtr_op_set = 1;
7840 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
7841         foreach_vtr_op
7842 #undef _
7843         
7844         else if (unformat (i, "push_dot1q %d", &push_dot1q))
7845             ;
7846         else if (unformat (i, "tag1 %d", &tag1))
7847             ;
7848         else if (unformat (i, "tag2 %d", &tag2))
7849             ;
7850         else {
7851             clib_warning ("parse error '%U'", format_unformat_error, i);
7852             return -99;
7853         }
7854     }
7855     
7856     if ((sw_if_index_set == 0)||(vtr_op_set == 0)) {
7857         errmsg ("missing vtr operation or sw_if_index\n");
7858         return -99;
7859     }
7860
7861     M(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)
7862
7863     mp->sw_if_index = ntohl(sw_if_index);
7864     mp->vtr_op = ntohl(vtr_op);
7865     mp->push_dot1q = ntohl(push_dot1q);
7866     mp->tag1 = ntohl(tag1);
7867     mp->tag2 = ntohl(tag2);
7868
7869     S; W;
7870     /* NOTREACHED */
7871     return 0;
7872 }
7873
7874 static int api_create_vhost_user_if (vat_main_t * vam)
7875 {
7876     unformat_input_t * i = vam->input;
7877     vl_api_create_vhost_user_if_t *mp;
7878     f64 timeout;
7879     u8 * file_name;
7880     u8 is_server = 0;
7881     u8 file_name_set = 0;
7882     u32 custom_dev_instance = ~0;
7883     u8 hwaddr[6];
7884     u8 use_custom_mac = 0;
7885
7886     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7887       if (unformat (i, "socket %s", &file_name)) {
7888         file_name_set = 1;
7889       }
7890       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
7891         ;
7892       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
7893         use_custom_mac = 1;
7894       else if (unformat (i, "server"))
7895         is_server = 1;
7896       else
7897         break;
7898     }
7899
7900     if (file_name_set == 0) {
7901       errmsg ("missing socket file name\n");
7902       return -99;
7903     }
7904
7905     if (vec_len (file_name) > 255) {
7906       errmsg ("socket file name too long\n");
7907       return -99;
7908     }
7909     vec_add1 (file_name, 0);
7910
7911     M(CREATE_VHOST_USER_IF, create_vhost_user_if);
7912
7913     mp->is_server = is_server;
7914     clib_memcpy(mp->sock_filename, file_name, vec_len(file_name));
7915     vec_free(file_name);
7916     if (custom_dev_instance != ~0) {
7917         mp->renumber = 1;
7918         mp->custom_dev_instance = ntohl(custom_dev_instance);
7919     }
7920     mp->use_custom_mac = use_custom_mac;
7921     clib_memcpy(mp->mac_address, hwaddr, 6);
7922
7923     S; W;
7924     /* NOTREACHED */
7925     return 0;
7926 }
7927
7928 static int api_modify_vhost_user_if (vat_main_t * vam)
7929 {
7930     unformat_input_t * i = vam->input;
7931     vl_api_modify_vhost_user_if_t *mp;
7932     f64 timeout;
7933     u8 * file_name;
7934     u8 is_server = 0;
7935     u8 file_name_set = 0;
7936     u32 custom_dev_instance = ~0;
7937     u8 sw_if_index_set = 0;
7938     u32 sw_if_index = (u32)~0;
7939
7940     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7941       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7942           sw_if_index_set = 1;
7943       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7944           sw_if_index_set = 1;
7945       else if (unformat (i, "socket %s", &file_name)) {
7946         file_name_set = 1;
7947       }
7948       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
7949         ;
7950       else if (unformat (i, "server"))
7951         is_server = 1;
7952       else
7953         break;
7954     }
7955
7956     if (sw_if_index_set == 0) {
7957        errmsg ("missing sw_if_index or interface name\n");
7958        return -99;
7959     }
7960
7961     if (file_name_set == 0) {
7962       errmsg ("missing socket file name\n");
7963       return -99;
7964     }
7965
7966     if (vec_len (file_name) > 255) {
7967       errmsg ("socket file name too long\n");
7968       return -99;
7969     }
7970     vec_add1 (file_name, 0);
7971
7972     M(MODIFY_VHOST_USER_IF, modify_vhost_user_if);
7973
7974     mp->sw_if_index = ntohl(sw_if_index);
7975     mp->is_server = is_server;
7976     clib_memcpy(mp->sock_filename, file_name, vec_len(file_name));
7977     vec_free(file_name);
7978     if (custom_dev_instance != ~0) {
7979         mp->renumber = 1;
7980         mp->custom_dev_instance = ntohl(custom_dev_instance);
7981     }
7982
7983     S; W;
7984     /* NOTREACHED */
7985     return 0;
7986 }
7987
7988 static int api_delete_vhost_user_if (vat_main_t * vam)
7989 {
7990     unformat_input_t * i = vam->input;
7991     vl_api_delete_vhost_user_if_t *mp;
7992     f64 timeout;
7993     u32 sw_if_index = ~0;
7994     u8 sw_if_index_set = 0;
7995
7996     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7997       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7998           sw_if_index_set = 1;
7999       else if (unformat (i, "sw_if_index %d", &sw_if_index))
8000           sw_if_index_set = 1;
8001       else
8002         break;
8003     }
8004
8005     if (sw_if_index_set == 0) {
8006        errmsg ("missing sw_if_index or interface name\n");
8007        return -99;
8008     }
8009
8010
8011     M(DELETE_VHOST_USER_IF, delete_vhost_user_if);
8012
8013     mp->sw_if_index = ntohl(sw_if_index);
8014
8015     S; W;
8016     /* NOTREACHED */
8017     return 0;
8018 }
8019
8020 static void vl_api_sw_interface_vhost_user_details_t_handler
8021 (vl_api_sw_interface_vhost_user_details_t * mp)
8022 {
8023     vat_main_t * vam = &vat_main;
8024
8025     fformat(vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s\n",
8026             (char *)mp->interface_name,
8027             ntohl(mp->sw_if_index), ntohl(mp->virtio_net_hdr_sz),
8028             clib_net_to_host_u64(mp->features), mp->is_server,
8029             ntohl(mp->num_regions), (char *)mp->sock_filename);
8030     fformat(vam->ofp, "    Status: '%s'\n", strerror(ntohl(mp->sock_errno)));
8031 }
8032
8033 static void vl_api_sw_interface_vhost_user_details_t_handler_json
8034 (vl_api_sw_interface_vhost_user_details_t * mp)
8035 {
8036     vat_main_t * vam = &vat_main;
8037     vat_json_node_t *node = NULL;
8038
8039     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8040         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8041         vat_json_init_array(&vam->json_tree);
8042     }
8043     node = vat_json_array_add(&vam->json_tree);
8044
8045     vat_json_init_object(node);
8046     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
8047     vat_json_object_add_string_copy(node, "interface_name", mp->interface_name);
8048     vat_json_object_add_uint(node, "virtio_net_hdr_sz", ntohl(mp->virtio_net_hdr_sz));
8049     vat_json_object_add_uint(node, "features", clib_net_to_host_u64(mp->features));
8050     vat_json_object_add_uint(node, "is_server", mp->is_server);
8051     vat_json_object_add_string_copy(node, "sock_filename", mp->sock_filename);
8052     vat_json_object_add_uint(node, "num_regions", ntohl(mp->num_regions));
8053     vat_json_object_add_uint(node, "sock_errno", ntohl(mp->sock_errno));
8054 }
8055
8056 static int api_sw_interface_vhost_user_dump (vat_main_t * vam)
8057 {
8058     vl_api_sw_interface_vhost_user_dump_t *mp;
8059     f64 timeout;
8060     fformat(vam->ofp, "Interface name           idx hdr_sz features server regions filename\n");
8061
8062     /* Get list of vhost-user interfaces */
8063     M(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump);
8064     S;
8065
8066     /* Use a control ping for synchronization */
8067     {
8068         vl_api_control_ping_t * mp;
8069         M(CONTROL_PING, control_ping);
8070         S;
8071     }
8072     W;
8073 }
8074
8075 static int api_show_version (vat_main_t * vam)
8076 {
8077     vl_api_show_version_t *mp;
8078     f64 timeout;
8079
8080     M(SHOW_VERSION, show_version);
8081
8082     S; W;
8083     /* NOTREACHED */
8084     return 0;
8085 }
8086
8087
8088 static int api_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
8089 {
8090     unformat_input_t * line_input = vam->input;
8091     vl_api_vxlan_gpe_add_del_tunnel_t *mp;
8092     f64 timeout;
8093     ip4_address_t local4, remote4;
8094     ip6_address_t local6, remote6;
8095     u8 is_add = 1;
8096     u8 ipv4_set = 0, ipv6_set = 0;
8097     u8 local_set = 0;
8098     u8 remote_set = 0;
8099     u32 encap_vrf_id = 0;
8100     u32 decap_vrf_id = 0;
8101     u8 protocol = ~0;
8102     u32 vni;
8103     u8 vni_set = 0;
8104
8105     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8106         if (unformat (line_input, "del"))
8107             is_add = 0;
8108         else if (unformat (line_input, "local %U", 
8109                            unformat_ip4_address, &local4))
8110         {
8111             local_set = 1;
8112             ipv4_set = 1;
8113         }
8114         else if (unformat (line_input, "remote %U",
8115                            unformat_ip4_address, &remote4))
8116         {
8117             remote_set = 1;
8118             ipv4_set = 1;
8119         }
8120         else if (unformat (line_input, "local %U",
8121                            unformat_ip6_address, &local6))
8122         {
8123             local_set = 1;
8124             ipv6_set = 1;
8125         }
8126         else if (unformat (line_input, "remote %U",
8127                            unformat_ip6_address, &remote6))
8128         {
8129             remote_set = 1;
8130             ipv6_set = 1;
8131         }
8132         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
8133             ;
8134         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
8135             ;
8136         else if (unformat (line_input, "vni %d", &vni))
8137             vni_set = 1;
8138         else if (unformat(line_input, "next-ip4"))
8139             protocol = 1;
8140         else if (unformat(line_input, "next-ip6"))
8141             protocol = 2;
8142         else if (unformat(line_input, "next-ethernet"))
8143             protocol = 3;
8144         else if (unformat(line_input, "next-nsh"))
8145             protocol = 4;
8146         else {
8147             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
8148             return -99;
8149         }
8150     }
8151
8152     if (local_set == 0) {
8153         errmsg ("tunnel local address not specified\n");
8154         return -99;
8155     }
8156     if (remote_set == 0) {
8157         errmsg ("tunnel remote address not specified\n");
8158         return -99;
8159     }
8160     if (ipv4_set && ipv6_set) {
8161         errmsg ("both IPv4 and IPv6 addresses specified");
8162         return -99;
8163     }
8164
8165     if (vni_set == 0) {
8166         errmsg ("vni not specified\n");
8167         return -99;
8168     }
8169
8170     M(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel);
8171     
8172
8173     if (ipv6_set) {
8174         clib_memcpy(&mp->local, &local6, sizeof(local6));
8175         clib_memcpy(&mp->remote, &remote6, sizeof(remote6));
8176     } else {
8177         clib_memcpy(&mp->local, &local4, sizeof(local4));
8178         clib_memcpy(&mp->remote, &remote4, sizeof(remote4));
8179     }
8180
8181     mp->encap_vrf_id = ntohl(encap_vrf_id);
8182     mp->decap_vrf_id = ntohl(decap_vrf_id);
8183     mp->protocol = ntohl(protocol);
8184     mp->vni = ntohl(vni);
8185     mp->is_add = is_add;
8186     mp->is_ipv6 = ipv6_set;
8187
8188     S; W;
8189     /* NOTREACHED */
8190     return 0;
8191 }
8192
8193 static void vl_api_vxlan_gpe_tunnel_details_t_handler
8194 (vl_api_vxlan_gpe_tunnel_details_t * mp)
8195 {
8196     vat_main_t * vam = &vat_main;
8197
8198     fformat(vam->ofp, "%11d%24U%24U%13d%12d%14d%14d\n",
8199             ntohl(mp->sw_if_index),
8200             format_ip46_address, &(mp->local[0]),
8201             format_ip46_address, &(mp->remote[0]),
8202                         ntohl(mp->vni),
8203             ntohl(mp->protocol),
8204             ntohl(mp->encap_vrf_id),
8205             ntohl(mp->decap_vrf_id));
8206 }
8207
8208 static void vl_api_vxlan_gpe_tunnel_details_t_handler_json
8209 (vl_api_vxlan_gpe_tunnel_details_t * mp)
8210 {
8211     vat_main_t * vam = &vat_main;
8212     vat_json_node_t *node = NULL;
8213     struct in_addr ip4;
8214     struct in6_addr ip6;
8215
8216     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8217         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8218         vat_json_init_array(&vam->json_tree);
8219     }
8220     node = vat_json_array_add(&vam->json_tree);
8221
8222     vat_json_init_object(node);
8223     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
8224     if (mp->is_ipv6) {
8225         clib_memcpy(&ip6, &(mp->local[0]), sizeof(ip6));
8226         vat_json_object_add_ip6(node, "local", ip6);
8227         clib_memcpy(&ip6, &(mp->remote[0]), sizeof(ip6));
8228         vat_json_object_add_ip6(node, "remote", ip6);
8229     } else {
8230         clib_memcpy(&ip4, &(mp->local[0]), sizeof(ip4));
8231         vat_json_object_add_ip4(node, "local", ip4);
8232         clib_memcpy(&ip4, &(mp->remote[0]), sizeof(ip4));
8233         vat_json_object_add_ip4(node, "remote", ip4);
8234     }
8235     vat_json_object_add_uint(node, "vni", ntohl(mp->vni));
8236     vat_json_object_add_uint(node, "protocol", ntohl(mp->protocol));
8237     vat_json_object_add_uint(node, "encap_vrf_id", ntohl(mp->encap_vrf_id));
8238     vat_json_object_add_uint(node, "decap_vrf_id", ntohl(mp->decap_vrf_id));
8239     vat_json_object_add_uint(node, "is_ipv6", mp->is_ipv6 ? 1 : 0);
8240 }
8241
8242 static int api_vxlan_gpe_tunnel_dump (vat_main_t * vam)
8243 {
8244     unformat_input_t * i = vam->input;
8245     vl_api_vxlan_gpe_tunnel_dump_t *mp;
8246     f64 timeout;
8247     u32 sw_if_index;
8248     u8 sw_if_index_set = 0;
8249
8250     /* Parse args required to build the message */
8251     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8252         if (unformat (i, "sw_if_index %d", &sw_if_index))
8253             sw_if_index_set = 1;
8254         else
8255             break;
8256     }
8257
8258     if (sw_if_index_set == 0) {
8259         sw_if_index = ~0;
8260     }
8261
8262     if (!vam->json_output) {
8263         fformat(vam->ofp, "%11s%24s%24s%13s%15s%14s%14s\n",
8264                 "sw_if_index", "local", "remote", "vni",
8265                                 "protocol","encap_vrf_id", "decap_vrf_id");
8266     }
8267
8268     /* Get list of vxlan-tunnel interfaces */
8269     M(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump);
8270
8271     mp->sw_if_index = htonl(sw_if_index);
8272
8273     S;
8274
8275     /* Use a control ping for synchronization */
8276     {
8277         vl_api_control_ping_t * mp;
8278         M(CONTROL_PING, control_ping);
8279         S;
8280     }
8281     W;
8282 }
8283
8284 u8 * format_l2_fib_mac_address (u8 * s, va_list * args)
8285 {
8286   u8 * a = va_arg (*args, u8 *);
8287
8288   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
8289                  a[2], a[3], a[4], a[5], a[6], a[7]);
8290 }
8291
8292 static void vl_api_l2_fib_table_entry_t_handler
8293 (vl_api_l2_fib_table_entry_t * mp)
8294 {
8295     vat_main_t * vam = &vat_main;
8296
8297     fformat(vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
8298             "       %d       %d     %d\n",
8299             ntohl(mp->bd_id), format_l2_fib_mac_address, &mp->mac,
8300             ntohl(mp->sw_if_index), mp->static_mac, mp->filter_mac,
8301             mp->bvi_mac);
8302 }
8303
8304 static void vl_api_l2_fib_table_entry_t_handler_json
8305 (vl_api_l2_fib_table_entry_t * mp)
8306 {
8307     vat_main_t * vam = &vat_main;
8308     vat_json_node_t *node = NULL;
8309
8310     if (VAT_JSON_ARRAY != vam->json_tree.type) {
8311         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
8312         vat_json_init_array(&vam->json_tree);
8313     }
8314     node = vat_json_array_add(&vam->json_tree);
8315
8316     vat_json_init_object(node);
8317     vat_json_object_add_uint(node, "bd_id", ntohl(mp->bd_id));
8318     vat_json_object_add_uint(node, "mac", clib_net_to_host_u64(mp->mac));
8319     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
8320     vat_json_object_add_uint(node, "static_mac", mp->static_mac);
8321     vat_json_object_add_uint(node, "filter_mac", mp->filter_mac);
8322     vat_json_object_add_uint(node, "bvi_mac", mp->bvi_mac);
8323 }
8324
8325 static int api_l2_fib_table_dump (vat_main_t * vam)
8326 {
8327     unformat_input_t * i = vam->input;
8328     vl_api_l2_fib_table_dump_t *mp;
8329     f64 timeout;
8330     u32 bd_id;
8331     u8 bd_id_set = 0;
8332
8333     /* Parse args required to build the message */
8334     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8335         if (unformat (i, "bd_id %d", &bd_id))
8336             bd_id_set = 1;
8337         else
8338             break;
8339     }
8340
8341     if (bd_id_set == 0) {
8342         errmsg ("missing bridge domain\n");
8343         return -99;
8344     }
8345
8346     fformat(vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI\n");
8347
8348     /* Get list of l2 fib entries */
8349     M(L2_FIB_TABLE_DUMP, l2_fib_table_dump);
8350
8351     mp->bd_id = ntohl(bd_id);
8352     S;
8353
8354     /* Use a control ping for synchronization */
8355     {
8356         vl_api_control_ping_t * mp;
8357         M(CONTROL_PING, control_ping);
8358         S;
8359     }
8360     W;
8361 }
8362
8363
8364 static int
8365 api_interface_name_renumber (vat_main_t * vam)
8366 {
8367     unformat_input_t * line_input = vam->input;
8368     vl_api_interface_name_renumber_t *mp;
8369     u32 sw_if_index = ~0;
8370     f64 timeout;
8371     u32 new_show_dev_instance = ~0;
8372
8373     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8374         if (unformat (line_input, "%U", unformat_sw_if_index, vam, 
8375                       &sw_if_index))
8376             ;
8377         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8378             ;
8379         else if (unformat (line_input, "new_show_dev_instance %d", 
8380                            &new_show_dev_instance))
8381             ;
8382         else
8383             break;
8384     }
8385
8386     if (sw_if_index == ~0) {
8387         errmsg ("missing interface name or sw_if_index\n");
8388         return -99;
8389     }
8390
8391     if (new_show_dev_instance == ~0) {
8392         errmsg ("missing new_show_dev_instance\n");
8393         return -99;
8394     }
8395
8396     M(INTERFACE_NAME_RENUMBER, interface_name_renumber);
8397
8398     mp->sw_if_index = ntohl (sw_if_index);
8399     mp->new_show_dev_instance = ntohl (new_show_dev_instance);
8400
8401     S; W;
8402 }
8403
8404 static int
8405 api_want_ip4_arp_events (vat_main_t * vam)
8406 {
8407     unformat_input_t * line_input = vam->input;
8408     vl_api_want_ip4_arp_events_t * mp;
8409     f64 timeout;
8410     ip4_address_t address;
8411     int address_set = 0;
8412     u32 enable_disable = 1;
8413
8414     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8415         if (unformat (line_input, "address %U", 
8416                       unformat_ip4_address, &address))
8417             address_set = 1;
8418         else if (unformat (line_input, "del"))
8419             enable_disable = 0;
8420         else
8421             break;
8422     }
8423     
8424     if (address_set == 0) {
8425         errmsg ("missing addresses\n");
8426         return -99;
8427     }
8428         
8429     M(WANT_IP4_ARP_EVENTS, want_ip4_arp_events);
8430     mp->enable_disable = enable_disable;
8431     mp->pid = getpid();
8432     mp->address = address.as_u32;
8433
8434     S; W; 
8435 }
8436
8437 static int api_input_acl_set_interface (vat_main_t * vam)
8438 {
8439     unformat_input_t * i = vam->input;
8440     vl_api_input_acl_set_interface_t *mp;
8441     f64 timeout;
8442     u32 sw_if_index;
8443     int sw_if_index_set;
8444     u32 ip4_table_index = ~0;
8445     u32 ip6_table_index = ~0;
8446     u32 l2_table_index = ~0;
8447     u8 is_add = 1;
8448
8449     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8450         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8451             sw_if_index_set = 1;
8452         else if (unformat (i, "sw_if_index %d", &sw_if_index))
8453             sw_if_index_set = 1;
8454         else if (unformat (i, "del"))
8455             is_add = 0;
8456         else if (unformat (i, "ip4-table %d", &ip4_table_index))
8457             ;
8458         else if (unformat (i, "ip6-table %d", &ip6_table_index))
8459             ;
8460         else if (unformat (i, "l2-table %d", &l2_table_index))
8461             ;
8462         else {
8463             clib_warning ("parse error '%U'", format_unformat_error, i);
8464             return -99;
8465         }
8466     }
8467
8468     if (sw_if_index_set == 0) {
8469         errmsg ("missing interface name or sw_if_index\n");
8470         return -99;
8471     }
8472
8473     M(INPUT_ACL_SET_INTERFACE, input_acl_set_interface);
8474
8475     mp->sw_if_index = ntohl(sw_if_index);
8476     mp->ip4_table_index = ntohl(ip4_table_index);
8477     mp->ip6_table_index = ntohl(ip6_table_index);
8478     mp->l2_table_index = ntohl(l2_table_index);
8479     mp->is_add = is_add;
8480
8481     S; W;
8482     /* NOTREACHED */
8483     return 0;
8484 }
8485
8486 static int
8487 api_ip_address_dump (vat_main_t * vam)
8488 {
8489     unformat_input_t * i = vam->input;
8490     vl_api_ip_address_dump_t * mp;
8491     u32 sw_if_index = ~0;
8492     u8 sw_if_index_set = 0;
8493     u8 ipv4_set = 0;
8494     u8 ipv6_set = 0;
8495     f64 timeout;
8496
8497     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8498         if (unformat (i, "sw_if_index %d", &sw_if_index))
8499             sw_if_index_set = 1;
8500         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8501             sw_if_index_set = 1;
8502         else if (unformat (i, "ipv4"))
8503             ipv4_set = 1;
8504         else if (unformat (i, "ipv6"))
8505             ipv6_set = 1;
8506         else
8507             break;
8508     }
8509
8510     if (ipv4_set && ipv6_set) {
8511         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
8512         return -99;
8513     }
8514
8515     if ((!ipv4_set) && (!ipv6_set)) {
8516         errmsg ("no ipv4 nor ipv6 flag set\n");
8517         return -99;
8518     }
8519
8520     if (sw_if_index_set == 0) {
8521         errmsg ("missing interface name or sw_if_index\n");
8522         return -99;
8523     }
8524
8525     vam->current_sw_if_index = sw_if_index;
8526     vam->is_ipv6 = ipv6_set;
8527
8528     M(IP_ADDRESS_DUMP, ip_address_dump);
8529     mp->sw_if_index = ntohl(sw_if_index);
8530     mp->is_ipv6 = ipv6_set;
8531     S;
8532
8533     /* Use a control ping for synchronization */
8534     {
8535         vl_api_control_ping_t * mp;
8536         M(CONTROL_PING, control_ping);
8537         S;
8538     }
8539     W;
8540 }
8541
8542 static int
8543 api_ip_dump (vat_main_t * vam)
8544 {
8545     vl_api_ip_dump_t * mp;
8546     unformat_input_t * in = vam->input;
8547     int ipv4_set = 0;
8548     int ipv6_set = 0;
8549     int is_ipv6;
8550     f64 timeout;
8551     int i;
8552
8553     while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT) {
8554         if (unformat (in, "ipv4"))
8555             ipv4_set = 1;
8556         else if (unformat (in, "ipv6"))
8557             ipv6_set = 1;
8558         else
8559             break;
8560     }
8561
8562     if (ipv4_set && ipv6_set) {
8563         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
8564         return -99;
8565     }
8566
8567     if ((!ipv4_set) && (!ipv6_set)) {
8568         errmsg ("no ipv4 nor ipv6 flag set\n");
8569         return -99;
8570     }
8571
8572     is_ipv6 = ipv6_set;
8573     vam->is_ipv6 = is_ipv6;
8574
8575     /* free old data */
8576     for (i = 0; i < vec_len(vam->ip_details_by_sw_if_index[is_ipv6]); i++) {
8577         vec_free(vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
8578     }
8579     vec_free(vam->ip_details_by_sw_if_index[is_ipv6]);
8580
8581     M(IP_DUMP, ip_dump);
8582     mp->is_ipv6 = ipv6_set;
8583     S;
8584
8585     /* Use a control ping for synchronization */
8586     {
8587         vl_api_control_ping_t * mp;
8588         M(CONTROL_PING, control_ping);
8589         S;
8590     }
8591     W;
8592 }
8593
8594 static int
8595 api_ipsec_spd_add_del (vat_main_t * vam)
8596 {
8597 #if DPDK > 0
8598     unformat_input_t * i = vam->input;
8599     vl_api_ipsec_spd_add_del_t *mp;
8600     f64 timeout;
8601     u32 spd_id = ~0;
8602     u8 is_add = 1;
8603
8604     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8605         if (unformat (i, "spd_id %d", &spd_id))
8606             ;
8607         else if (unformat (i, "del"))
8608             is_add = 0;
8609         else {
8610             clib_warning ("parse error '%U'", format_unformat_error, i);
8611             return -99;
8612         }
8613     }
8614     if (spd_id == ~0) {
8615         errmsg ("spd_id must be set\n");
8616         return -99;
8617     }
8618
8619     M(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del);
8620
8621     mp->spd_id = ntohl(spd_id);
8622     mp->is_add = is_add;
8623
8624     S; W;
8625     /* NOTREACHED */
8626     return 0;
8627 #else
8628     clib_warning ("unsupported (no dpdk)");
8629     return -99;
8630 #endif
8631 }
8632
8633 static int
8634 api_ipsec_interface_add_del_spd (vat_main_t * vam)
8635 {
8636 #if DPDK > 0
8637     unformat_input_t * i = vam->input;
8638     vl_api_ipsec_interface_add_del_spd_t *mp;
8639     f64 timeout;
8640     u32 sw_if_index;
8641     u8 sw_if_index_set = 0;
8642     u32 spd_id = (u32) ~0;
8643     u8 is_add = 1;
8644
8645     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8646         if (unformat (i, "del"))
8647             is_add = 0;
8648         else if (unformat (i, "spd_id %d", &spd_id))
8649             ;
8650         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
8651             sw_if_index_set = 1;
8652         else if (unformat (i, "sw_if_index %d", &sw_if_index))
8653             sw_if_index_set = 1;
8654         else {
8655             clib_warning ("parse error '%U'", format_unformat_error, i);
8656             return -99;
8657         }
8658
8659     }
8660
8661     if (spd_id == (u32) ~0) {
8662         errmsg ("spd_id must be set\n");
8663         return -99;
8664     }
8665
8666     if (sw_if_index_set == 0) {
8667         errmsg ("missing interface name or sw_if_index\n");
8668         return -99;
8669     }
8670
8671     M(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd);
8672
8673     mp->spd_id = ntohl(spd_id);
8674     mp->sw_if_index = ntohl (sw_if_index);
8675     mp->is_add = is_add;
8676
8677     S; W;
8678     /* NOTREACHED */
8679     return 0;
8680 #else
8681     clib_warning ("unsupported (no dpdk)");
8682     return -99;
8683 #endif
8684 }
8685
8686 static int
8687 api_ipsec_spd_add_del_entry (vat_main_t * vam)
8688 {
8689 #if DPDK > 0
8690     unformat_input_t * i = vam->input;
8691     vl_api_ipsec_spd_add_del_entry_t *mp;
8692     f64 timeout;
8693     u8 is_add = 1, is_outbound = 0, is_ipv6 = 0, is_ip_any = 1;
8694     u32 spd_id, sa_id, protocol = 0, policy = 0;
8695     i32 priority;
8696     u32 rport_start = 0, rport_stop = (u32) ~0;
8697     u32 lport_start = 0, lport_stop = (u32) ~0;
8698     ip4_address_t laddr4_start, laddr4_stop, raddr4_start, raddr4_stop;
8699     ip6_address_t laddr6_start, laddr6_stop, raddr6_start, raddr6_stop;
8700
8701     laddr4_start.as_u32 = raddr4_start.as_u32 = 0;
8702     laddr4_stop.as_u32 = raddr4_stop.as_u32 = (u32) ~0;
8703     laddr6_start.as_u64[0] = raddr6_start.as_u64[0] = 0;
8704     laddr6_start.as_u64[1] = raddr6_start.as_u64[1] = 0;
8705     laddr6_stop.as_u64[0] = raddr6_stop.as_u64[0] = (u64) ~0;
8706     laddr6_stop.as_u64[1] = raddr6_stop.as_u64[1] = (u64) ~0;
8707
8708     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8709         if (unformat (i, "del"))
8710             is_add = 0;
8711         if (unformat (i, "outbound"))
8712             is_outbound = 1;
8713         if (unformat (i, "inbound"))
8714             is_outbound = 0;
8715         else if (unformat (i, "spd_id %d", &spd_id))
8716             ;
8717         else if (unformat (i, "sa_id %d", &sa_id))
8718             ;
8719         else if (unformat (i, "priority %d", &priority))
8720             ;
8721         else if (unformat (i, "protocol %d", &protocol))
8722             ;
8723         else if (unformat (i, "lport_start %d", &lport_start))
8724             ;
8725         else if (unformat (i, "lport_stop %d", &lport_stop))
8726             ;
8727         else if (unformat (i, "rport_start %d", &rport_start))
8728             ;
8729         else if (unformat (i, "rport_stop %d", &rport_stop))
8730             ;
8731         else if (unformat (i, "laddr_start %U", unformat_ip4_address, &laddr4_start))
8732           {
8733             is_ipv6 = 0;
8734             is_ip_any =0;
8735           }
8736         else if (unformat (i, "laddr_stop %U", unformat_ip4_address, &laddr4_stop))
8737           {
8738             is_ipv6 = 0;
8739             is_ip_any = 0;
8740           }
8741         else if (unformat (i, "raddr_start %U", unformat_ip4_address, &raddr4_start))
8742           {
8743             is_ipv6 = 0;
8744             is_ip_any = 0;
8745           }
8746         else if (unformat (i, "raddr_stop %U", unformat_ip4_address, &raddr4_stop))
8747           {
8748             is_ipv6 = 0;
8749             is_ip_any = 0;
8750           }
8751         else if (unformat (i, "laddr_start %U", unformat_ip6_address, &laddr6_start))
8752           {
8753             is_ipv6 = 1;
8754             is_ip_any = 0;
8755           }
8756         else if (unformat (i, "laddr_stop %U", unformat_ip6_address, &laddr6_stop))
8757           {
8758             is_ipv6 = 1;
8759             is_ip_any = 0;
8760           }
8761         else if (unformat (i, "raddr_start %U", unformat_ip6_address, &raddr6_start))
8762           {
8763             is_ipv6 = 1;
8764             is_ip_any = 0;
8765           }
8766         else if (unformat (i, "raddr_stop %U", unformat_ip6_address, &raddr6_stop))
8767           {
8768             is_ipv6 = 1;
8769             is_ip_any = 0;
8770           }
8771         else if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
8772           {
8773             if (policy == IPSEC_POLICY_ACTION_RESOLVE) {
8774                 clib_warning ("unsupported action: 'resolve'");
8775                 return -99;
8776             }
8777           }
8778         else {
8779             clib_warning ("parse error '%U'", format_unformat_error, i);
8780             return -99;
8781         }
8782
8783     }
8784
8785     M(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry);
8786
8787     mp->spd_id = ntohl(spd_id);
8788     mp->priority = ntohl(priority);
8789     mp->is_outbound = is_outbound;
8790
8791     mp->is_ipv6 = is_ipv6;
8792     if (is_ipv6 || is_ip_any) {
8793         clib_memcpy (mp->remote_address_start, &raddr6_start, sizeof(ip6_address_t));
8794         clib_memcpy (mp->remote_address_stop, &raddr6_stop, sizeof(ip6_address_t));
8795         clib_memcpy (mp->local_address_start, &laddr6_start, sizeof(ip6_address_t));
8796         clib_memcpy (mp->local_address_stop, &laddr6_stop, sizeof(ip6_address_t));
8797     } else {
8798         clib_memcpy (mp->remote_address_start, &raddr4_start, sizeof(ip4_address_t));
8799         clib_memcpy (mp->remote_address_stop, &raddr4_stop, sizeof(ip4_address_t));
8800         clib_memcpy (mp->local_address_start, &laddr4_start, sizeof(ip4_address_t));
8801         clib_memcpy (mp->local_address_stop, &laddr4_stop, sizeof(ip4_address_t));
8802     }
8803     mp->protocol = (u8) protocol;
8804     mp->local_port_start = ntohs((u16) lport_start);
8805     mp->local_port_stop = ntohs((u16) lport_stop);
8806     mp->remote_port_start = ntohs((u16) rport_start);
8807     mp->remote_port_stop = ntohs((u16) rport_stop);
8808     mp->policy = (u8) policy;
8809     mp->sa_id = ntohl(sa_id);
8810     mp->is_add = is_add;
8811     mp->is_ip_any = is_ip_any;
8812     S; W;
8813     /* NOTREACHED */
8814     return 0;
8815 #else
8816     clib_warning ("unsupported (no dpdk)");
8817     return -99;
8818 #endif
8819 }
8820
8821 static int
8822 api_ipsec_sad_add_del_entry (vat_main_t * vam)
8823 {
8824 #if DPDK > 0
8825     unformat_input_t * i = vam->input;
8826     vl_api_ipsec_sad_add_del_entry_t *mp;
8827     f64 timeout;
8828     u32 sad_id, spi;
8829     u8 * ck, * ik;
8830     u8 is_add = 1;
8831
8832     u8 protocol = IPSEC_PROTOCOL_AH;
8833     u8 is_tunnel = 0, is_tunnel_ipv6 = 0;
8834     u32 crypto_alg = 0, integ_alg = 0;
8835     ip4_address_t tun_src4;
8836     ip4_address_t tun_dst4;
8837     ip6_address_t tun_src6;
8838     ip6_address_t tun_dst6;
8839
8840     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8841         if (unformat (i, "del"))
8842             is_add = 0;
8843         else if (unformat (i, "sad_id %d", &sad_id))
8844             ;
8845         else if (unformat (i, "spi %d", &spi))
8846             ;
8847         else if (unformat (i, "esp"))
8848             protocol = IPSEC_PROTOCOL_ESP;
8849         else if (unformat (i, "tunnel_src %U", unformat_ip4_address, &tun_src4)) {
8850             is_tunnel = 1;
8851             is_tunnel_ipv6 = 0;
8852         }
8853         else if (unformat (i, "tunnel_dst %U", unformat_ip4_address, &tun_dst4)) {
8854             is_tunnel = 1;
8855             is_tunnel_ipv6 = 0;
8856         }
8857         else if (unformat (i, "tunnel_src %U", unformat_ip6_address, &tun_src6)) {
8858             is_tunnel = 1;
8859             is_tunnel_ipv6 = 1;
8860         }
8861         else if (unformat (i, "tunnel_dst %U", unformat_ip6_address, &tun_dst6)) {
8862             is_tunnel = 1;
8863             is_tunnel_ipv6 = 1;
8864         }
8865         else if (unformat (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg)) {
8866             if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
8867                 crypto_alg > IPSEC_INTEG_ALG_SHA_512_256) {
8868                 clib_warning ("unsupported crypto-alg: '%U'",
8869                               format_ipsec_crypto_alg, crypto_alg);
8870                 return -99;
8871             }
8872         }
8873         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8874             ;
8875         else if (unformat (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) {
8876             if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
8877                 integ_alg > IPSEC_INTEG_ALG_SHA_512_256) {
8878                 clib_warning ("unsupported integ-alg: '%U'",
8879                               format_ipsec_integ_alg, integ_alg);
8880                 return -99;
8881             }
8882         }
8883         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8884             ;
8885         else {
8886             clib_warning ("parse error '%U'", format_unformat_error, i);
8887             return -99;
8888         }
8889
8890     }
8891
8892     M(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry);
8893
8894     mp->sad_id = ntohl(sad_id);
8895     mp->is_add = is_add;
8896     mp->protocol = protocol;
8897     mp->spi = ntohl(spi);
8898     mp->is_tunnel = is_tunnel;
8899     mp->is_tunnel_ipv6 = is_tunnel_ipv6;
8900     mp->crypto_algorithm = crypto_alg;
8901     mp->integrity_algorithm = integ_alg;
8902     mp->crypto_key_length = vec_len(ck);
8903     mp->integrity_key_length = vec_len(ik);
8904
8905     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8906       mp->crypto_key_length = sizeof(mp->crypto_key);
8907
8908     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8909       mp->integrity_key_length = sizeof(mp->integrity_key);
8910
8911     clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8912     clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8913
8914     if (is_tunnel) {
8915       if (is_tunnel_ipv6) {
8916         clib_memcpy (mp->tunnel_src_address, &tun_src6, sizeof(ip6_address_t));
8917         clib_memcpy (mp->tunnel_dst_address, &tun_dst6, sizeof(ip6_address_t));
8918       } else {
8919         clib_memcpy (mp->tunnel_src_address, &tun_src4, sizeof(ip4_address_t));
8920         clib_memcpy (mp->tunnel_dst_address, &tun_dst4, sizeof(ip4_address_t));
8921       }
8922     }
8923
8924     S; W;
8925     /* NOTREACHED */
8926     return 0;
8927 #else
8928     clib_warning ("unsupported (no dpdk)");
8929     return -99;
8930 #endif
8931 }
8932
8933 static int
8934 api_ipsec_sa_set_key (vat_main_t * vam)
8935 {
8936 #if DPDK > 0
8937     unformat_input_t * i = vam->input;
8938     vl_api_ipsec_sa_set_key_t *mp;
8939     f64 timeout;
8940     u32 sa_id;
8941     u8 * ck, * ik;
8942
8943     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8944         if (unformat (i, "sa_id %d", &sa_id))
8945             ;
8946         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8947             ;
8948         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8949             ;
8950         else {
8951             clib_warning ("parse error '%U'", format_unformat_error, i);
8952             return -99;
8953         }
8954     }
8955
8956     M(IPSEC_SA_SET_KEY, ipsec_set_sa_key);
8957
8958     mp->sa_id = ntohl(sa_id);
8959     mp->crypto_key_length = vec_len(ck);
8960     mp->integrity_key_length = vec_len(ik);
8961
8962     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8963       mp->crypto_key_length = sizeof(mp->crypto_key);
8964
8965     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8966       mp->integrity_key_length = sizeof(mp->integrity_key);
8967
8968     clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8969     clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8970
8971     S; W;
8972     /* NOTREACHED */
8973     return 0;
8974 #else
8975     clib_warning ("unsupported (no dpdk)");
8976     return -99;
8977 #endif
8978 }
8979
8980 static int
8981 api_ikev2_profile_add_del (vat_main_t * vam)
8982 {
8983 #if DPDK > 0
8984     unformat_input_t * i = vam->input;
8985     vl_api_ikev2_profile_add_del_t * mp;
8986     f64 timeout;
8987     u8 is_add = 1;
8988     u8 * name = 0;
8989
8990     const char * valid_chars = "a-zA-Z0-9_";
8991
8992     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8993         if (unformat (i, "del"))
8994             is_add = 0;
8995         else if (unformat (i, "name %U", unformat_token, valid_chars, &name))
8996             vec_add1 (name, 0);
8997         else {
8998             errmsg ("parse error '%U'", format_unformat_error, i);
8999             return -99;
9000         }
9001     }
9002
9003     if (!vec_len (name)) {
9004         errmsg ("profile name must be specified");
9005         return -99;
9006     }
9007
9008     if (vec_len (name) > 64) {
9009         errmsg ("profile name too long");
9010         return -99;
9011     }
9012
9013     M(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del);
9014
9015     clib_memcpy(mp->name, name, vec_len (name));
9016     mp->is_add = is_add;
9017     vec_free (name);
9018
9019     S; W;
9020     /* NOTREACHED */
9021     return 0;
9022 #else
9023     clib_warning ("unsupported (no dpdk)");
9024     return -99;
9025 #endif
9026 }
9027
9028 static int
9029 api_ikev2_profile_set_auth (vat_main_t * vam)
9030 {
9031 #if DPDK > 0
9032     unformat_input_t * i = vam->input;
9033     vl_api_ikev2_profile_set_auth_t * mp;
9034     f64 timeout;
9035     u8 * name = 0;
9036     u8 * data = 0;
9037     u32 auth_method = 0;
9038     u8 is_hex = 0;
9039
9040     const char * valid_chars = "a-zA-Z0-9_";
9041
9042     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9043         if (unformat (i, "name %U", unformat_token, valid_chars, &name))
9044             vec_add1 (name, 0);
9045         else if (unformat (i, "auth_method %U",
9046                            unformat_ikev2_auth_method, &auth_method))
9047             ;
9048         else if (unformat (i, "auth_data 0x%U", unformat_hex_string, &data))
9049             is_hex = 1;
9050         else if (unformat (i, "auth_data %v", &data))
9051             ;
9052         else {
9053             errmsg ("parse error '%U'", format_unformat_error, i);
9054             return -99;
9055         }
9056     }
9057
9058     if (!vec_len (name)) {
9059         errmsg ("profile name must be specified");
9060         return -99;
9061     }
9062
9063     if (vec_len (name) > 64) {
9064         errmsg ("profile name too long");
9065         return -99;
9066     }
9067
9068     if (!vec_len(data)) {
9069         errmsg ("auth_data must be specified");
9070         return -99;
9071     }
9072
9073     if (!auth_method) {
9074         errmsg ("auth_method must be specified");
9075         return -99;
9076     }
9077
9078     M(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth);
9079
9080     mp->is_hex = is_hex;
9081     mp->auth_method = (u8) auth_method;
9082     mp->data_len = vec_len (data);
9083     clib_memcpy (mp->name, name, vec_len (name));
9084     clib_memcpy (mp->data, data, vec_len (data));
9085     vec_free (name);
9086     vec_free (data);
9087
9088     S; W;
9089     /* NOTREACHED */
9090     return 0;
9091 #else
9092     clib_warning ("unsupported (no dpdk)");
9093     return -99;
9094 #endif
9095 }
9096
9097 static int
9098 api_ikev2_profile_set_id (vat_main_t * vam)
9099 {
9100 #if DPDK > 0
9101     unformat_input_t * i = vam->input;
9102     vl_api_ikev2_profile_set_id_t * mp;
9103     f64 timeout;
9104     u8 * name = 0;
9105     u8 * data = 0;
9106     u8 is_local = 0;
9107     u32 id_type = 0;
9108     ip4_address_t ip4;
9109
9110     const char * valid_chars = "a-zA-Z0-9_";
9111
9112     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9113         if (unformat (i, "name %U", unformat_token, valid_chars, &name))
9114             vec_add1 (name, 0);
9115         else if (unformat (i, "id_type %U",
9116                            unformat_ikev2_id_type, &id_type))
9117             ;
9118         else if (unformat (i, "id_data %U", unformat_ip4_address, &ip4))
9119           {
9120             data = vec_new(u8, 4);
9121             clib_memcpy(data, ip4.as_u8, 4);
9122           }
9123         else if (unformat (i, "id_data 0x%U", unformat_hex_string, &data))
9124             ;
9125         else if (unformat (i, "id_data %v", &data))
9126             ;
9127         else if (unformat (i, "local"))
9128             is_local = 1;
9129         else if (unformat (i, "remote"))
9130             is_local = 0;
9131         else {
9132             errmsg ("parse error '%U'", format_unformat_error, i);
9133             return -99;
9134         }
9135     }
9136
9137     if (!vec_len (name)) {
9138         errmsg ("profile name must be specified");
9139         return -99;
9140     }
9141
9142     if (vec_len (name) > 64) {
9143         errmsg ("profile name too long");
9144         return -99;
9145     }
9146
9147     if (!vec_len(data)) {
9148         errmsg ("id_data must be specified");
9149         return -99;
9150     }
9151
9152     if (!id_type) {
9153         errmsg ("id_type must be specified");
9154         return -99;
9155     }
9156
9157     M(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id);
9158
9159     mp->is_local = is_local;
9160     mp->id_type = (u8) id_type;
9161     mp->data_len = vec_len (data);
9162     clib_memcpy (mp->name, name, vec_len (name));
9163     clib_memcpy (mp->data, data, vec_len (data));
9164     vec_free (name);
9165     vec_free (data);
9166
9167     S; W;
9168     /* NOTREACHED */
9169     return 0;
9170 #else
9171     clib_warning ("unsupported (no dpdk)");
9172     return -99;
9173 #endif
9174 }
9175
9176 static int
9177 api_ikev2_profile_set_ts (vat_main_t * vam)
9178 {
9179 #if DPDK > 0
9180     unformat_input_t * i = vam->input;
9181     vl_api_ikev2_profile_set_ts_t * mp;
9182     f64 timeout;
9183     u8 * name = 0;
9184     u8 is_local = 0;
9185     u32 proto = 0, start_port = 0, end_port = (u32) ~0;
9186     ip4_address_t start_addr, end_addr;
9187
9188     const char * valid_chars = "a-zA-Z0-9_";
9189
9190     start_addr.as_u32 = 0;
9191     end_addr.as_u32 = (u32) ~0;
9192
9193     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9194         if (unformat (i, "name %U", unformat_token, valid_chars, &name))
9195             vec_add1 (name, 0);
9196         else if (unformat (i, "protocol %d", &proto))
9197             ;
9198         else if (unformat (i, "start_port %d", &start_port))
9199             ;
9200         else if (unformat (i, "end_port %d", &end_port))
9201             ;
9202         else if (unformat (i, "start_addr %U", unformat_ip4_address, &start_addr))
9203             ;
9204         else if (unformat (i, "end_addr %U", unformat_ip4_address, &end_addr))
9205             ;
9206         else if (unformat (i, "local"))
9207             is_local = 1;
9208         else if (unformat (i, "remote"))
9209             is_local = 0;
9210         else {
9211             errmsg ("parse error '%U'", format_unformat_error, i);
9212             return -99;
9213         }
9214     }
9215
9216     if (!vec_len (name)) {
9217         errmsg ("profile name must be specified");
9218         return -99;
9219     }
9220
9221     if (vec_len (name) > 64) {
9222         errmsg ("profile name too long");
9223         return -99;
9224     }
9225
9226     M(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts);
9227
9228     mp->is_local = is_local;
9229     mp->proto = (u8) proto;
9230     mp->start_port = (u16) start_port;
9231     mp->end_port = (u16) end_port;
9232     mp->start_addr = start_addr.as_u32;
9233     mp->end_addr = end_addr.as_u32;
9234     clib_memcpy (mp->name, name, vec_len (name));
9235     vec_free (name);
9236
9237     S; W;
9238     /* NOTREACHED */
9239     return 0;
9240 #else
9241     clib_warning ("unsupported (no dpdk)");
9242     return -99;
9243 #endif
9244 }
9245
9246 static int
9247 api_ikev2_set_local_key (vat_main_t * vam)
9248 {
9249 #if DPDK > 0
9250     unformat_input_t * i = vam->input;
9251     vl_api_ikev2_set_local_key_t * mp;
9252     f64 timeout;
9253     u8 * file = 0;
9254
9255     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9256         if (unformat (i, "file %v", &file))
9257             vec_add1 (file, 0);
9258         else {
9259             errmsg ("parse error '%U'", format_unformat_error, i);
9260             return -99;
9261         }
9262     }
9263
9264     if (!vec_len (file)) {
9265         errmsg ("RSA key file must be specified");
9266         return -99;
9267     }
9268
9269     if (vec_len (file) > 256) {
9270         errmsg ("file name too long");
9271         return -99;
9272     }
9273
9274     M(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key);
9275
9276     clib_memcpy (mp->key_file, file, vec_len (file));
9277     vec_free (file);
9278
9279     S; W;
9280     /* NOTREACHED */
9281     return 0;
9282 #else
9283     clib_warning ("unsupported (no dpdk)");
9284     return -99;
9285 #endif
9286 }
9287
9288 /*
9289  * MAP
9290  */
9291 static int api_map_add_domain (vat_main_t * vam)
9292 {
9293   unformat_input_t *i = vam->input;
9294   vl_api_map_add_domain_t *mp;
9295   f64 timeout;
9296
9297   ip4_address_t ip4_prefix;
9298   ip6_address_t ip6_prefix;
9299   ip6_address_t ip6_src;
9300   u32 num_m_args = 0;
9301   u32 ip6_prefix_len, ip4_prefix_len, ea_bits_len, psid_offset,
9302     psid_length;
9303   u8 is_translation = 0;
9304   u32 mtu = 0;
9305   u8 ip6_src_len = 128;
9306
9307   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9308     if (unformat (i, "ip4-pfx %U/%d", unformat_ip4_address,
9309                   &ip4_prefix, &ip4_prefix_len))
9310       num_m_args++;
9311     else if (unformat (i, "ip6-pfx %U/%d", unformat_ip6_address,
9312                        &ip6_prefix, &ip6_prefix_len))
9313       num_m_args++;
9314     else if (unformat (i, "ip6-src %U/%d", unformat_ip6_address, &ip6_src, &ip6_src_len))
9315       num_m_args++;
9316     else if (unformat (i, "ip6-src %U", unformat_ip6_address, &ip6_src))
9317       num_m_args++;
9318     else if (unformat (i, "ea-bits-len %d", &ea_bits_len))
9319       num_m_args++;
9320     else if (unformat (i, "psid-offset %d", &psid_offset))
9321       num_m_args++;
9322     else if (unformat (i, "psid-len %d", &psid_length))
9323       num_m_args++;
9324     else if (unformat (i, "mtu %d", &mtu))
9325       num_m_args++;
9326     else if (unformat (i, "map-t"))
9327       is_translation = 1;
9328     else {
9329       clib_warning ("parse error '%U'", format_unformat_error, i);
9330       return -99;
9331     }
9332   }
9333
9334   if (num_m_args != 6) {
9335     errmsg("mandatory argument(s) missing\n");
9336     return -99;
9337   }
9338
9339   /* Construct the API message */
9340   M(MAP_ADD_DOMAIN, map_add_domain);
9341
9342   clib_memcpy(mp->ip4_prefix, &ip4_prefix, sizeof(ip4_prefix));
9343   mp->ip4_prefix_len = ip4_prefix_len;
9344
9345   clib_memcpy(mp->ip6_prefix, &ip6_prefix, sizeof(ip6_prefix));
9346   mp->ip6_prefix_len = ip6_prefix_len;
9347
9348   clib_memcpy(mp->ip6_src, &ip6_src, sizeof(ip6_src));
9349   mp->ip6_src_prefix_len = ip6_src_len;
9350
9351   mp->ea_bits_len = ea_bits_len;
9352   mp->psid_offset = psid_offset;
9353   mp->psid_length = psid_length;
9354   mp->is_translation = is_translation;
9355   mp->mtu = htons(mtu);
9356
9357   /* send it... */
9358   S;
9359
9360   /* Wait for a reply, return good/bad news  */
9361   W;
9362 }
9363
9364 static int api_map_del_domain (vat_main_t * vam)
9365 {
9366   unformat_input_t *i = vam->input;
9367   vl_api_map_del_domain_t *mp;
9368   f64 timeout;
9369
9370   u32 num_m_args = 0;
9371   u32 index;
9372
9373   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9374     if (unformat (i, "index %d", &index))
9375       num_m_args++;
9376     else {
9377       clib_warning ("parse error '%U'", format_unformat_error, i);
9378       return -99;
9379     }
9380   }
9381
9382   if (num_m_args != 1) {
9383     errmsg("mandatory argument(s) missing\n");
9384     return -99;
9385   }
9386
9387   /* Construct the API message */
9388   M(MAP_DEL_DOMAIN, map_del_domain);
9389
9390   mp->index = ntohl(index);
9391
9392   /* send it... */
9393   S;
9394
9395   /* Wait for a reply, return good/bad news  */
9396   W;
9397 }
9398
9399 static int api_map_add_del_rule (vat_main_t * vam)
9400 {
9401   unformat_input_t *i = vam->input;
9402   vl_api_map_add_del_rule_t *mp;
9403   f64 timeout;
9404   u8 is_add = 1;
9405   ip6_address_t ip6_dst;
9406   u32 num_m_args = 0, index, psid;
9407
9408   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9409     if (unformat (i, "index %d", &index))
9410       num_m_args++;
9411     else if (unformat (i, "psid %d", &psid))
9412       num_m_args++;
9413     else if (unformat (i, "dst %U", unformat_ip6_address, &ip6_dst))
9414       num_m_args++;
9415     else if (unformat (i, "del")) {
9416       is_add = 0;
9417     } else {
9418       clib_warning ("parse error '%U'", format_unformat_error, i);
9419       return -99;
9420     }
9421   }
9422
9423   /* Construct the API message */
9424   M(MAP_ADD_DEL_RULE, map_add_del_rule);
9425
9426   mp->index = ntohl(index);
9427   mp->is_add = is_add;
9428   clib_memcpy(mp->ip6_dst, &ip6_dst, sizeof(ip6_dst));
9429   mp->psid = ntohs(psid);
9430
9431   /* send it... */
9432   S;
9433
9434   /* Wait for a reply, return good/bad news  */
9435   W;
9436 }
9437
9438 static int api_map_domain_dump (vat_main_t * vam)
9439 {
9440     vl_api_map_domain_dump_t *mp;
9441     f64 timeout;
9442
9443     /* Construct the API message */
9444     M(MAP_DOMAIN_DUMP, map_domain_dump);
9445
9446     /* send it... */
9447     S;
9448
9449     /* Use a control ping for synchronization */
9450     {
9451         vl_api_control_ping_t * mp;
9452         M(CONTROL_PING, control_ping);
9453         S;
9454     }
9455     W;
9456 }
9457
9458 static int api_map_rule_dump (vat_main_t * vam)
9459 {
9460     unformat_input_t *i = vam->input;
9461     vl_api_map_rule_dump_t *mp;
9462     f64 timeout;
9463     u32 domain_index = ~0;
9464
9465     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9466         if (unformat (i, "index %u", &domain_index))
9467             ;
9468         else
9469             break;
9470     }
9471
9472     if (domain_index == ~0) {
9473         clib_warning("parse error: domain index expected");
9474         return -99;
9475     }
9476
9477     /* Construct the API message */
9478     M(MAP_RULE_DUMP, map_rule_dump);
9479
9480     mp->domain_index = htonl(domain_index);
9481
9482     /* send it... */
9483     S;
9484
9485     /* Use a control ping for synchronization */
9486     {
9487         vl_api_control_ping_t * mp;
9488         M(CONTROL_PING, control_ping);
9489         S;
9490     }
9491     W;
9492 }
9493
9494 static void vl_api_map_add_domain_reply_t_handler
9495 (vl_api_map_add_domain_reply_t * mp)
9496 {
9497   vat_main_t * vam = &vat_main;
9498   i32 retval = ntohl(mp->retval);
9499
9500   if (vam->async_mode) {
9501       vam->async_errors += (retval < 0);
9502   } else {
9503       vam->retval = retval;
9504       vam->result_ready = 1;
9505   }
9506 }
9507
9508 static void vl_api_map_add_domain_reply_t_handler_json
9509 (vl_api_map_add_domain_reply_t * mp)
9510 {
9511   vat_main_t * vam = &vat_main;
9512   vat_json_node_t node;
9513
9514   vat_json_init_object(&node);
9515   vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
9516   vat_json_object_add_uint(&node, "index", ntohl(mp->index));
9517
9518   vat_json_print(vam->ofp, &node);
9519   vat_json_free(&node);
9520
9521   vam->retval = ntohl(mp->retval);
9522   vam->result_ready = 1;
9523 }
9524
9525 static int
9526 api_get_first_msg_id (vat_main_t * vam)
9527 {
9528     vl_api_get_first_msg_id_t * mp;
9529     f64 timeout;
9530     unformat_input_t * i = vam->input;
9531     u8 * name;
9532     u8 name_set = 0;
9533     
9534     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
9535         if (unformat (i, "client %s", &name))
9536             name_set = 1;
9537         else 
9538             break;
9539     }
9540
9541     if (name_set == 0) {
9542         errmsg ("missing client name\n");
9543         return -99;
9544     }
9545     vec_add1 (name, 0);
9546
9547     if (vec_len (name) > 63) {
9548         errmsg ("client name too long\n");
9549         return -99;
9550     }
9551
9552     M(GET_FIRST_MSG_ID, get_first_msg_id);
9553     clib_memcpy (mp->name, name, vec_len(name));
9554     S; W;
9555     /* NOTREACHED */
9556     return 0;
9557 }
9558
9559 static int api_cop_interface_enable_disable (vat_main_t * vam)
9560 {
9561     unformat_input_t * line_input = vam->input;
9562     vl_api_cop_interface_enable_disable_t * mp;
9563     f64 timeout;
9564     u32 sw_if_index = ~0;
9565     u8 enable_disable = 1;
9566
9567     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
9568         if (unformat (line_input, "disable"))
9569             enable_disable = 0;
9570         if (unformat (line_input, "enable"))
9571             enable_disable = 1;
9572         else if (unformat (line_input, "%U", unformat_sw_if_index,
9573                            vam, &sw_if_index))
9574             ;
9575         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
9576             ;
9577         else
9578             break;
9579     }
9580         
9581     if (sw_if_index == ~0) {
9582         errmsg ("missing interface name or sw_if_index\n");
9583         return -99;
9584     }
9585
9586     /* Construct the API message */
9587     M(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable);
9588     mp->sw_if_index = ntohl(sw_if_index);
9589     mp->enable_disable = enable_disable;
9590
9591     /* send it... */
9592     S;
9593     /* Wait for the reply */
9594     W;
9595 }
9596
9597 static int api_cop_whitelist_enable_disable (vat_main_t * vam)
9598 {
9599     unformat_input_t * line_input = vam->input;
9600     vl_api_cop_whitelist_enable_disable_t * mp;
9601     f64 timeout;
9602     u32 sw_if_index = ~0;
9603     u8 ip4=0, ip6=0, default_cop=0;
9604     u32 fib_id;
9605
9606     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
9607         if (unformat (line_input, "ip4"))
9608             ip4 = 1;
9609         else if (unformat (line_input, "ip6"))
9610             ip6 = 1;
9611         else if (unformat (line_input, "default"))
9612             default_cop = 1;
9613         else if (unformat (line_input, "%U", unformat_sw_if_index,
9614                            vam, &sw_if_index))
9615             ;
9616         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
9617             ;
9618         else if (unformat (line_input, "fib-id %d", &fib_id))
9619             ;
9620         else
9621             break;
9622     }
9623         
9624     if (sw_if_index == ~0) {
9625         errmsg ("missing interface name or sw_if_index\n");
9626         return -99;
9627     }
9628
9629     /* Construct the API message */
9630     M(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable);
9631     mp->sw_if_index = ntohl(sw_if_index);
9632     mp->fib_id = ntohl(fib_id);
9633     mp->ip4 = ip4;
9634     mp->ip6 = ip6;
9635     mp->default_cop = default_cop;
9636
9637     /* send it... */
9638     S;
9639     /* Wait for the reply */
9640     W;
9641 }
9642
9643 static int api_get_node_graph (vat_main_t * vam)
9644 {
9645     vl_api_get_node_graph_t * mp;
9646     f64 timeout;
9647
9648     M(GET_NODE_GRAPH, get_node_graph);
9649
9650     /* send it... */
9651     S;
9652     /* Wait for the reply */
9653     W;
9654 }
9655
9656 static int
9657 api_lisp_add_del_locator_set(vat_main_t * vam)
9658 {
9659     unformat_input_t * input = vam->input;
9660     vl_api_lisp_add_del_locator_set_t *mp;
9661     f64 timeout = ~0;
9662     u8  is_add = 1;
9663     u8 *locator_set_name = NULL;
9664     u8  locator_set_name_set = 0;
9665
9666     /* Parse args required to build the message */
9667     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
9668         if (unformat(input, "del")) {
9669             is_add = 0;
9670         } else if (unformat(input, "locator-set %s", &locator_set_name)) {
9671             locator_set_name_set = 1;
9672         } else
9673             break;
9674     }
9675
9676     if (locator_set_name_set == 0) {
9677         errmsg ("missing locator-set name");
9678         return -99;
9679     }
9680
9681     if (vec_len(locator_set_name) > 64) {
9682         errmsg ("locator-set name too long\n");
9683         vec_free(locator_set_name);
9684         return -99;
9685     }
9686     vec_add1(locator_set_name, 0);
9687
9688     /* Construct the API message */
9689     M(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set);
9690
9691     mp->is_add = is_add;
9692     clib_memcpy(mp->locator_set_name, locator_set_name,
9693            vec_len(locator_set_name));
9694     vec_free(locator_set_name);
9695
9696     /* send it... */
9697     S;
9698
9699     /* Wait for a reply... */
9700     W;
9701
9702     /* NOTREACHED */
9703     return 0;
9704 }
9705
9706 static int
9707 api_lisp_add_del_locator(vat_main_t * vam)
9708 {
9709     unformat_input_t * input = vam->input;
9710     vl_api_lisp_add_del_locator_t *mp;
9711     f64 timeout = ~0;
9712     u32 tmp_if_index = ~0;
9713     u32 sw_if_index = ~0;
9714     u8  sw_if_index_set = 0;
9715     u8  sw_if_index_if_name_set = 0;
9716     u8  priority = ~0;
9717     u8  priority_set = 0;
9718     u8  weight = ~0;
9719     u8  weight_set = 0;
9720     u8  is_add = 1;
9721     u8  *locator_set_name = NULL;
9722     u8  locator_set_name_set = 0;
9723
9724     /* Parse args required to build the message */
9725     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
9726         if (unformat(input, "del")) {
9727             is_add = 0;
9728         } else if (unformat(input, "locator-set %s", &locator_set_name)) {
9729             locator_set_name_set = 1;
9730         } else if (unformat(input, "iface %U", unformat_sw_if_index, vam,
9731             &tmp_if_index)) {
9732             sw_if_index_if_name_set = 1;
9733             sw_if_index = tmp_if_index;
9734         } else if (unformat(input,"sw_if_index %d", &tmp_if_index)) {
9735             sw_if_index_set = 1;
9736             sw_if_index = tmp_if_index;
9737         } else if (unformat(input, "p %d", &priority)) {
9738             priority_set = 1;
9739         } else if (unformat(input, "w %d", &weight)) {
9740             weight_set = 1;
9741         } else
9742             break;
9743     }
9744
9745     if (locator_set_name_set == 0) {
9746         errmsg ("missing locator-set name");
9747         return -99;
9748     }
9749
9750     if (sw_if_index_set == 0 && sw_if_index_if_name_set == 0) {
9751         errmsg ("missing sw_if_index");
9752         vec_free(locator_set_name);
9753         return -99;
9754     }
9755
9756     if (sw_if_index_set != 0 && sw_if_index_if_name_set != 0) {
9757         errmsg ("cannot use both params interface name and sw_if_index");
9758         vec_free(locator_set_name);
9759         return -99;
9760     }
9761
9762     if (priority_set == 0) {
9763         errmsg ("missing locator-set priority\n");
9764         vec_free(locator_set_name);
9765         return -99;
9766     }
9767
9768     if (weight_set == 0) {
9769         errmsg ("missing locator-set weight\n");
9770         vec_free(locator_set_name);
9771         return -99;
9772     }
9773
9774     if (vec_len(locator_set_name) > 64) {
9775         errmsg ("locator-set name too long\n");
9776         vec_free(locator_set_name);
9777         return -99;
9778     }
9779     vec_add1(locator_set_name, 0);
9780
9781     /* Construct the API message */
9782     M(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator);
9783
9784     mp->is_add = is_add;
9785     mp->sw_if_index = ntohl(sw_if_index);
9786     mp->priority = priority;
9787     mp->weight = weight;
9788     clib_memcpy(mp->locator_set_name, locator_set_name,
9789            vec_len(locator_set_name));
9790     vec_free(locator_set_name);
9791
9792     /* send it... */
9793     S;
9794
9795     /* Wait for a reply... */
9796     W;
9797
9798     /* NOTREACHED */
9799     return 0;
9800 }
9801
9802 static int
9803 api_lisp_add_del_local_eid(vat_main_t * vam)
9804 {
9805     unformat_input_t * input = vam->input;
9806     vl_api_lisp_add_del_local_eid_t *mp;
9807     f64 timeout = ~0;
9808     u8 is_add = 1;
9809     u8 eidv4_set = 0;
9810     u8 eidv6_set = 0;
9811     ip4_address_t eidv4;
9812     ip6_address_t eidv6;
9813     u8 tmp_eid_lenght = ~0;
9814     u8 eid_lenght = ~0;
9815     u8 *locator_set_name = NULL;
9816     u8 locator_set_name_set = 0;
9817
9818     /* Parse args required to build the message */
9819     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
9820         if (unformat(input, "del")) {
9821             is_add = 0;
9822         } else if (unformat(input, "eid %U/%d", unformat_ip4_address,
9823             &eidv4, &tmp_eid_lenght)) {
9824             eid_lenght = tmp_eid_lenght;
9825             eidv4_set = 1;
9826         } else if (unformat(input, "eid %U/%d", unformat_ip6_address,
9827             &eidv6, &tmp_eid_lenght)) {
9828             eid_lenght = tmp_eid_lenght;
9829             eidv6_set = 1;
9830         } else if (unformat(input, "locator-set %s", &locator_set_name)) {
9831             locator_set_name_set = 1;
9832         } else
9833             break;
9834     }
9835
9836     if (locator_set_name_set == 0) {
9837         errmsg ("missing locator-set name\n");
9838         return -99;
9839     }
9840
9841     if (vec_len(locator_set_name) > 64) {
9842         errmsg ("locator-set name too long\n");
9843         vec_free(locator_set_name);
9844         return -99;
9845     }
9846     vec_add1(locator_set_name, 0);
9847
9848     if (eidv4_set && eidv6_set) {
9849         errmsg ("both eid v4 and v6 addresses set\n");
9850         vec_free(locator_set_name);
9851         return -99;
9852     }
9853
9854     if (!eidv4_set && !eidv6_set) {
9855         errmsg ("eid addresses not set\n");
9856         vec_free(locator_set_name);
9857         return -99;
9858     }
9859
9860     if (eidv4_set && eid_lenght > 32) {
9861         errmsg ("eid prefix to big\n");
9862         vec_free(locator_set_name);
9863         return -99;
9864     }
9865
9866     if (eidv6_set && eid_lenght > 128) {
9867         errmsg ("eid prefix to big\n");
9868         vec_free(locator_set_name);
9869         return -99;
9870     }
9871
9872     /* Construct the API message */
9873     M(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid);
9874
9875     mp->is_add = is_add;
9876     if (eidv6_set) {
9877         mp->is_ipv6 = 1;
9878         clib_memcpy(mp->ip_address, &eidv6, sizeof(eidv6));
9879     } else {
9880         mp->is_ipv6 = 0;
9881         clib_memcpy(mp->ip_address, &eidv4, sizeof(eidv4));
9882     }
9883     mp->prefix_len = eid_lenght;
9884     clib_memcpy(mp->locator_set_name, locator_set_name,
9885            vec_len(locator_set_name));
9886     vec_free(locator_set_name);
9887
9888     /* send it... */
9889     S;
9890
9891     /* Wait for a reply... */
9892     W;
9893
9894     /* NOTREACHED */
9895     return 0;
9896 }
9897
9898 static int
9899 api_lisp_gpe_add_del_fwd_entry(vat_main_t * vam)
9900 {
9901     unformat_input_t * input = vam->input;
9902     vl_api_lisp_gpe_add_del_fwd_entry_t *mp;
9903     f64 timeout = ~0;
9904     u8 is_add = 1;
9905     u8 eidv4_set = 0, slocv4_set = 0, dlocv4_set = 0;
9906     u8 eidv6_set = 0, slocv6_set = 0, dlocv6_set = 0;
9907     ip4_address_t eidv4, slocv4, dlocv4;
9908     ip6_address_t eidv6, slocv6, dlocv6;
9909     u8 tmp_eid_lenght = ~0;
9910     u8 eid_lenght = ~0;
9911
9912     /* Parse args required to build the message */
9913     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
9914         if (unformat(input, "del")) {
9915             is_add = 0;
9916         } else if (unformat(input, "eid %U/%d", unformat_ip4_address,
9917                             &eidv4, &tmp_eid_lenght)) {
9918             eid_lenght = tmp_eid_lenght;
9919             eidv4_set = 1;
9920         } else if (unformat(input, "eid %U/%d", unformat_ip6_address,
9921                             &eidv6, &tmp_eid_lenght)) {
9922             eid_lenght = tmp_eid_lenght;
9923             eidv6_set = 1;
9924         } else if (unformat(input, "sloc %U", unformat_ip4_address, &slocv4)) {
9925             slocv4_set = 1;
9926         } else if (unformat(input, "sloc %U", unformat_ip6_address, &slocv6)) {
9927             slocv6_set = 1;
9928         } else if (unformat(input, "dloc %U", unformat_ip4_address, &dlocv4)) {
9929             dlocv4_set = 1;
9930         } else if (unformat(input, "dloc %U", unformat_ip6_address, &dlocv6)) {
9931             dlocv6_set = 1;
9932         } else
9933             break;
9934     }
9935
9936     if (eidv4_set && eidv6_set) {
9937         errmsg ("both eid v4 and v6 addresses set\n");
9938         return -99;
9939     }
9940
9941     if (!eidv4_set && !eidv6_set) {
9942         errmsg ("eid addresses not set\n");
9943         return -99;
9944     }
9945
9946     if (slocv4_set && slocv6_set) {
9947         errmsg ("both source v4 and v6 addresses set\n");
9948         return -99;
9949     }
9950
9951     if (!slocv4_set && !slocv6_set) {
9952         errmsg ("source addresses not set\n");
9953         return -99;
9954     }
9955
9956     if (dlocv4_set && dlocv6_set) {
9957         errmsg ("both destination v4 and v6 addresses set\n");
9958         return -99;
9959     }
9960
9961     if (dlocv4_set && dlocv6_set) {
9962         errmsg ("destination addresses not set\n");
9963         return -99;
9964     }
9965
9966     if (!(slocv4_set == dlocv4_set && slocv6_set == dlocv6_set)) {
9967         errmsg ("mixing type of source and destination address\n");
9968         return -99;
9969     }
9970
9971     /* Construct the API message */
9972     M(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry);
9973
9974     mp->is_add = is_add;
9975     if (eidv6_set) {
9976         mp->eid_is_ipv6 = 1;
9977         clib_memcpy(mp->eid_ip_address, &eidv6, sizeof(eidv6));
9978     } else {
9979         mp->eid_is_ipv6 = 0;
9980         clib_memcpy(mp->eid_ip_address, &eidv4, sizeof(eidv4));
9981     }
9982     mp->eid_prefix_len = eid_lenght;
9983     if (slocv6_set) {
9984         mp->address_is_ipv6 = 1;
9985         clib_memcpy(mp->source_ip_address, &slocv6, sizeof(slocv6));
9986         clib_memcpy(mp->destination_ip_address, &dlocv6, sizeof(dlocv6));
9987     } else {
9988         mp->address_is_ipv6 = 0;
9989         clib_memcpy(mp->source_ip_address, &slocv4, sizeof(slocv4));
9990         clib_memcpy(mp->destination_ip_address, &dlocv4, sizeof(dlocv4));
9991     }
9992
9993     /* send it... */
9994     S;
9995
9996     /* Wait for a reply... */
9997     W;
9998
9999     /* NOTREACHED */
10000     return 0;
10001 }
10002
10003 static int
10004 api_lisp_add_del_map_resolver(vat_main_t * vam)
10005 {
10006     unformat_input_t * input = vam->input;
10007     vl_api_lisp_add_del_map_resolver_t *mp;
10008     f64 timeout = ~0;
10009     u8 is_add = 1;
10010     u8 ipv4_set = 0;
10011     u8 ipv6_set = 0;
10012     ip4_address_t ipv4;
10013     ip6_address_t ipv6;
10014
10015     /* Parse args required to build the message */
10016     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10017         if (unformat(input, "del")) {
10018             is_add = 0;
10019         } else if (unformat(input, "%U", unformat_ip4_address, &ipv4)) {
10020             ipv4_set = 1;
10021         } else if (unformat(input, "%U", unformat_ip6_address, &ipv6)) {
10022             ipv6_set = 1;
10023         } else
10024             break;
10025     }
10026
10027     if (ipv4_set && ipv6_set) {
10028         errmsg ("both eid v4 and v6 addresses set\n");
10029         return -99;
10030     }
10031
10032     if (!ipv4_set && !ipv6_set) {
10033         errmsg ("eid addresses not set\n");
10034         return -99;
10035     }
10036
10037     /* Construct the API message */
10038     M(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver);
10039
10040     mp->is_add = is_add;
10041     if (ipv6_set) {
10042         mp->is_ipv6 = 1;
10043         clib_memcpy(mp->ip_address, &ipv6, sizeof(ipv6));
10044     } else {
10045         mp->is_ipv6 = 0;
10046         clib_memcpy(mp->ip_address, &ipv4, sizeof(ipv4));
10047     }
10048
10049     /* send it... */
10050     S;
10051
10052     /* Wait for a reply... */
10053     W;
10054
10055     /* NOTREACHED */
10056     return 0;
10057 }
10058
10059 static int
10060 api_lisp_gpe_enable_disable (vat_main_t * vam)
10061 {
10062   unformat_input_t * input = vam->input;
10063   vl_api_lisp_gpe_enable_disable_t *mp;
10064   f64 timeout = ~0;
10065   u8 is_set = 0;
10066   u8 is_en = 1;
10067
10068   /* Parse args required to build the message */
10069   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10070       if (unformat(input, "enable")) {
10071           is_set = 1;
10072           is_en = 1;
10073       } else if (unformat(input, "disable")) {
10074           is_set = 1;
10075           is_en = 0;
10076       } else
10077           break;
10078   }
10079
10080   if (is_set == 0) {
10081       errmsg("Value not set\n");
10082       return -99;
10083   }
10084
10085   /* Construct the API message */
10086   M(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable);
10087
10088   mp->is_en = is_en;
10089
10090   /* send it... */
10091   S;
10092
10093   /* Wait for a reply... */
10094   W;
10095
10096   /* NOTREACHED */
10097   return 0;
10098 }
10099
10100 static int
10101 api_lisp_enable_disable (vat_main_t * vam)
10102 {
10103   unformat_input_t * input = vam->input;
10104   vl_api_lisp_enable_disable_t *mp;
10105   f64 timeout = ~0;
10106   u8 is_set = 0;
10107   u8 is_en = 0;
10108
10109   /* Parse args required to build the message */
10110   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10111     {
10112       if (unformat (input, "enable"))
10113         {
10114           is_set = 1;
10115           is_en = 1;
10116         }
10117       else if (unformat (input, "disable"))
10118         {
10119           is_set = 1;
10120         }
10121       else
10122           break;
10123     }
10124
10125   if (!is_set)
10126     {
10127       errmsg ("Value not set\n");
10128       return -99;
10129     }
10130
10131   /* Construct the API message */
10132   M(LISP_ENABLE_DISABLE, lisp_enable_disable);
10133
10134   mp->is_en = is_en;
10135
10136   /* send it... */
10137   S;
10138
10139   /* Wait for a reply... */
10140   W;
10141
10142   /* NOTREACHED */
10143   return 0;
10144 }
10145
10146 /** Used for transferring locators via VPP API */
10147 typedef CLIB_PACKED(struct
10148 {
10149     u8 is_ip4; /**< is locator an IPv4 address? */
10150     u8 addr[16]; /**< IPv4/IPv6 address */
10151 }) rloc_t;
10152
10153 /**
10154  * Enable/disable LISP proxy ITR.
10155  *
10156  * @param vam vpp API test context
10157  * @return return code
10158  */
10159 static int
10160 api_lisp_pitr_set_locator_set (vat_main_t * vam)
10161 {
10162   f64 timeout = ~0;
10163   u8 ls_name_set = 0;
10164   unformat_input_t * input = vam->input;
10165   vl_api_lisp_pitr_set_locator_set_t * mp;
10166   u8 is_add = 1;
10167   u8 * ls_name = 0;
10168
10169   /* Parse args required to build the message */
10170   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
10171     {
10172       if (unformat (input, "del"))
10173         is_add = 0;
10174       else if (unformat (input, "locator-set %s", &ls_name))
10175         ls_name_set = 1;
10176       else
10177         {
10178           errmsg ("parse error '%U'", format_unformat_error, input);
10179           return -99;
10180         }
10181     }
10182
10183   if (!ls_name_set)
10184     {
10185       errmsg ("locator-set name not set!");
10186       return -99;
10187     }
10188
10189   M(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set);
10190
10191   mp->is_add = is_add;
10192   clib_memcpy (mp->ls_name, ls_name, vec_len (ls_name));
10193   vec_free (ls_name);
10194
10195   /* send */
10196   S;
10197
10198   /* wait for reply */
10199   W;
10200
10201   /* notreached*/
10202   return 0;
10203 }
10204
10205 /**
10206  * Add/del remote mapping from LISP control plane and updates
10207  * forwarding entries in data-plane accordingly.
10208  *
10209  * @param vam vpp API test context
10210  * @return return code
10211  */
10212 static int
10213 api_lisp_add_del_remote_mapping (vat_main_t * vam)
10214 {
10215     unformat_input_t * input = vam->input;
10216     vl_api_lisp_add_del_remote_mapping_t *mp;
10217     f64 timeout = ~0;
10218     u32 vni = 0;
10219     u8 seid_set = 0, deid_set = 0;
10220     ip4_address_t seid4, deid4, rloc4;
10221     ip6_address_t seid6, deid6, rloc6;
10222     u32 seid_len = 0, deid_len = 0, len;
10223     u8 deid_is_ip4 = 0, seid_is_ip4 = 0;
10224     u8 is_add = 1, del_all = 0;
10225     u32 action = ~0;
10226     rloc_t * rlocs = 0, rloc;
10227
10228     /* Parse args required to build the message */
10229     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10230         if (unformat(input, "del-all")) {
10231             del_all = 1;
10232         } else if (unformat(input, "del")) {
10233             is_add = 0;
10234         } else if (unformat(input, "add")) {
10235             is_add = 1;
10236         } else if (unformat(input, "deid %U/%d", unformat_ip4_address,
10237                             &deid4, &len)) {
10238             deid_set = 1;
10239             deid_is_ip4 = 1;
10240             deid_len = len;
10241         } else if (unformat(input, "deid %U/%d", unformat_ip6_address,
10242                             &deid6, &len)) {
10243             deid_set = 1;
10244             deid_is_ip4 = 0;
10245             deid_len = len;
10246         } else if (unformat(input, "seid %U/%d", unformat_ip4_address,
10247                             &seid4, &len)) {
10248             seid_set = 1;
10249             seid_is_ip4 = 1;
10250             seid_len = len;
10251         } else if (unformat(input, "seid %U/%d", unformat_ip6_address,
10252                             &seid6, &len)) {
10253             seid_set = 1;
10254             seid_is_ip4 = 0;
10255             seid_len = len;
10256         } else if (unformat(input, "vni %d", &vni)) {
10257             ;
10258         } else if (unformat(input, "rloc %U", unformat_ip4_address, &rloc4)) {
10259             rloc.is_ip4 = 1;
10260             clib_memcpy (&rloc.addr, &rloc4, sizeof (rloc4));
10261             vec_add1 (rlocs, rloc);
10262         } else if (unformat(input, "rloc %U", unformat_ip6_address, &rloc6)) {
10263             rloc.is_ip4 = 0;
10264             clib_memcpy (&rloc.addr, &rloc6, sizeof (rloc6));
10265             vec_add1 (rlocs, rloc);
10266         } else if (unformat(input, "action %d", &action)) {
10267             ;
10268         } else {
10269             clib_warning ("parse error '%U'", format_unformat_error, input);
10270             return -99;
10271         }
10272     }
10273
10274     if (!seid_set || !deid_set) {
10275         errmsg ("missing params!");
10276         return -99;
10277     }
10278
10279     if (seid_is_ip4 != deid_is_ip4) {
10280         errmsg ("source and destination EIDs are not in " "same IP family!");
10281         return -99;
10282     }
10283
10284     if (is_add && (~0 == action)
10285         && 0 == vec_len (rlocs)) {
10286           errmsg ("no action set for negative map-reply!");
10287           return -99;
10288     }
10289
10290     M(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping);
10291     mp->is_add = is_add;
10292     mp->vni = htonl (vni);
10293     mp->seid_len = seid_len;
10294     mp->action = (u8) action;
10295     mp->deid_len = deid_len;
10296     mp->del_all = del_all;
10297     if (seid_is_ip4) {
10298         mp->eid_is_ip4 = 1;
10299         clib_memcpy (mp->seid, &seid4, sizeof (seid4));
10300     } else {
10301         mp->eid_is_ip4 = 0;
10302         clib_memcpy (mp->seid, &seid6, sizeof (seid6));
10303     }
10304
10305     if (deid_is_ip4) {
10306         mp->eid_is_ip4 = 1;
10307         clib_memcpy (mp->deid, &deid4, sizeof (deid4));
10308     } else {
10309         mp->eid_is_ip4 = 0;
10310         clib_memcpy (mp->deid, &deid6, sizeof (deid6));
10311     }
10312
10313     mp->rloc_num = vec_len (rlocs);
10314     clib_memcpy (mp->rlocs, rlocs, (sizeof (rloc_t) * vec_len (rlocs)));
10315     vec_free (rlocs);
10316
10317     /* send it... */
10318     S;
10319
10320     /* Wait for a reply... */
10321     W;
10322
10323     /* NOTREACHED */
10324     return 0;
10325 }
10326
10327 static int
10328 api_lisp_gpe_add_del_iface(vat_main_t * vam)
10329 {
10330     unformat_input_t * input = vam->input;
10331     vl_api_lisp_gpe_add_del_iface_t *mp;
10332     f64 timeout = ~0;
10333     u8 is_set = 0;
10334     u8 is_add = 1;
10335     u32 table_id, vni;
10336
10337     /* Parse args required to build the message */
10338     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
10339         if (unformat(input, "up")) {
10340             is_set = 1;
10341             is_add = 1;
10342         } else if (unformat(input, "down")) {
10343             is_set = 1;
10344             is_add = 0;
10345         } else if (unformat(input, "table_id %d", &table_id)) {
10346             ;
10347         } else if (unformat(input, "vni %d", &vni)) {
10348             ;
10349         } else
10350             break;
10351     }
10352
10353     if (is_set == 0) {
10354         errmsg("Value not set\n");
10355         return -99;
10356     }
10357
10358     /* Construct the API message */
10359     M(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface);
10360
10361     mp->is_add = is_add;
10362     mp->table_id = table_id;
10363     mp->vni = vni;
10364
10365     /* send it... */
10366     S;
10367
10368     /* Wait for a reply... */
10369     W;
10370
10371     /* NOTREACHED */
10372     return 0;
10373 }
10374
10375 static int
10376 api_lisp_locator_set_dump(vat_main_t *vam)
10377 {
10378     vl_api_lisp_locator_set_dump_t *mp;
10379     f64 timeout = ~0;
10380
10381     if (!vam->json_output) {
10382         fformat(vam->ofp, "%=20s%=16s%=16s%=16s\n",
10383                 "Locator-set", "Locator", "Priority", "Weight");
10384     }
10385
10386     M(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump);
10387     /* send it... */
10388     S;
10389
10390     /* Use a control ping for synchronization */
10391     {
10392         vl_api_control_ping_t * mp;
10393         M(CONTROL_PING, control_ping);
10394         S;
10395     }
10396     /* Wait for a reply... */
10397     W;
10398
10399     /* NOTREACHED */
10400     return 0;
10401 }
10402
10403 static int
10404 api_lisp_local_eid_table_dump(vat_main_t *vam)
10405 {
10406     vl_api_lisp_local_eid_table_dump_t *mp;
10407     f64 timeout = ~0;
10408
10409     if (!vam->json_output) {
10410         fformat(vam->ofp, "%=20s%=30s\n",
10411                 "Locator-set", "Eid");
10412     }
10413
10414     M(LISP_LOCAL_EID_TABLE_DUMP, lisp_local_eid_table_dump);
10415     /* send it... */
10416     S;
10417
10418     /* Use a control ping for synchronization */
10419     {
10420         vl_api_control_ping_t * mp;
10421         M(CONTROL_PING, control_ping);
10422         S;
10423     }
10424     /* Wait for a reply... */
10425     W;
10426
10427     /* NOTREACHED */
10428     return 0;
10429 }
10430
10431 static int
10432 api_lisp_gpe_tunnel_dump(vat_main_t *vam)
10433 {
10434     vl_api_lisp_gpe_tunnel_dump_t *mp;
10435     f64 timeout = ~0;
10436
10437     if (!vam->json_output) {
10438         fformat(vam->ofp, "%=20s%=30s%=16s%=16s%=16s%=16s"
10439                 "%=16s%=16s%=16s%=16s%=16s\n",
10440                 "Tunel", "Source", "Destination", "Fib encap", "Fib decap",
10441                 "Decap next", "Lisp version", "Flags", "Next protocol",
10442                 "ver_res", "res", "iid");
10443     }
10444
10445     M(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump);
10446     /* send it... */
10447     S;
10448
10449     /* Use a control ping for synchronization */
10450     {
10451         vl_api_control_ping_t * mp;
10452         M(CONTROL_PING, control_ping);
10453         S;
10454     }
10455     /* Wait for a reply... */
10456     W;
10457
10458     /* NOTREACHED */
10459     return 0;
10460 }
10461
10462 static int
10463 api_lisp_map_resolver_dump(vat_main_t *vam)
10464 {
10465     vl_api_lisp_map_resolver_dump_t *mp;
10466     f64 timeout = ~0;
10467
10468     if (!vam->json_output) {
10469         fformat(vam->ofp, "%=20s\n",
10470                 "Map resolver");
10471     }
10472
10473     M(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump);
10474     /* send it... */
10475     S;
10476
10477     /* Use a control ping for synchronization */
10478     {
10479         vl_api_control_ping_t * mp;
10480         M(CONTROL_PING, control_ping);
10481         S;
10482     }
10483     /* Wait for a reply... */
10484     W;
10485
10486     /* NOTREACHED */
10487     return 0;
10488 }
10489
10490 static int
10491 api_lisp_enable_disable_status_dump(vat_main_t *vam)
10492 {
10493     vl_api_lisp_enable_disable_status_dump_t *mp;
10494     f64 timeout = ~0;
10495
10496     if (!vam->json_output) {
10497         fformat(vam->ofp, "%=20s\n",
10498                 "lisp status:");
10499     }
10500
10501     M(LISP_ENABLE_DISABLE_STATUS_DUMP,
10502       lisp_enable_disable_status_dump);
10503     /* send it... */
10504     S;
10505
10506     /* Use a control ping for synchronization */
10507     {
10508         vl_api_control_ping_t * mp;
10509         M(CONTROL_PING, control_ping);
10510         S;
10511     }
10512     /* Wait for a reply... */
10513     W;
10514
10515     /* NOTREACHED */
10516     return 0;
10517 }
10518
10519 static int
10520 api_af_packet_create (vat_main_t * vam)
10521 {
10522     unformat_input_t * i = vam->input;
10523     vl_api_af_packet_create_t * mp;
10524     f64 timeout;
10525     u8 * host_if_name = 0;
10526     u8 hw_addr[6];
10527     u8 random_hw_addr = 1;
10528
10529     memset (hw_addr, 0, sizeof (hw_addr));
10530
10531     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10532         if (unformat (i, "name %s", &host_if_name))
10533             vec_add1 (host_if_name, 0);
10534         else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
10535             random_hw_addr = 0;
10536         else
10537           break;
10538     }
10539
10540     if (!vec_len (host_if_name)) {
10541         errmsg ("host-interface name must be specified");
10542         return -99;
10543     }
10544
10545     if (vec_len (host_if_name) > 64) {
10546         errmsg ("host-interface name too long");
10547         return -99;
10548     }
10549
10550     M(AF_PACKET_CREATE, af_packet_create);
10551
10552     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
10553     clib_memcpy (mp->hw_addr, hw_addr, 6);
10554     mp->use_random_hw_addr = random_hw_addr;
10555     vec_free (host_if_name);
10556
10557     S; W;
10558     /* NOTREACHED */
10559     return 0;
10560 }
10561
10562 static int
10563 api_af_packet_delete (vat_main_t * vam)
10564 {
10565     unformat_input_t * i = vam->input;
10566     vl_api_af_packet_delete_t * mp;
10567     f64 timeout;
10568     u8 * host_if_name = 0;
10569
10570     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10571         if (unformat (i, "name %s", &host_if_name))
10572             vec_add1 (host_if_name, 0);
10573         else
10574           break;
10575     }
10576
10577     if (!vec_len (host_if_name)) {
10578         errmsg ("host-interface name must be specified");
10579         return -99;
10580     }
10581
10582     if (vec_len (host_if_name) > 64) {
10583         errmsg ("host-interface name too long");
10584         return -99;
10585     }
10586
10587     M(AF_PACKET_DELETE, af_packet_delete);
10588
10589     clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name));
10590     vec_free (host_if_name);
10591
10592     S; W;
10593     /* NOTREACHED */
10594     return 0;
10595 }
10596
10597 static int
10598 api_policer_add_del (vat_main_t * vam)
10599 {
10600     unformat_input_t * i = vam->input;
10601     vl_api_policer_add_del_t * mp;
10602     f64 timeout;
10603     u8 is_add = 1;
10604     u8 * name = 0;
10605     u32 cir = 0;
10606     u32 eir = 0;
10607     u64 cb = 0;
10608     u64 eb = 0;
10609     u8 rate_type = 0;
10610     u8 round_type = 0;
10611     u8 type = 0;
10612
10613     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10614         if (unformat (i, "del"))
10615             is_add = 0;
10616         else if (unformat (i, "name %s", &name))
10617             vec_add1 (name, 0);
10618         else if (unformat (i, "cir %u", &cir))
10619             ;
10620         else if (unformat (i, "eir %u", &eir))
10621             ;
10622         else if (unformat (i, "cb %u", &cb))
10623             ;
10624         else if (unformat (i, "eb %u", &eb))
10625             ;
10626         else if (unformat (i, "rate_type %U", unformat_policer_rate_type,
10627                            &rate_type))
10628             ;
10629         else if (unformat (i, "round_type %U", unformat_policer_round_type,
10630                            &round_type))
10631             ;
10632         else if (unformat (i, "type %U", unformat_policer_type, &type))
10633             ;
10634         else
10635           break;
10636     }
10637
10638     if (!vec_len (name)) {
10639         errmsg ("policer name must be specified");
10640         return -99;
10641     }
10642
10643     if (vec_len (name) > 64) {
10644         errmsg ("policer name too long");
10645         return -99;
10646     }
10647
10648     M(POLICER_ADD_DEL, policer_add_del);
10649
10650     clib_memcpy (mp->name, name, vec_len (name));
10651     vec_free (name);
10652     mp->is_add = is_add;
10653     mp->cir = cir;
10654     mp->eir = eir;
10655     mp->cb = cb;
10656     mp->eb = eb;
10657     mp->rate_type = rate_type;
10658     mp->round_type = round_type;
10659     mp->type = type;
10660
10661     S; W;
10662     /* NOTREACHED */
10663     return 0;
10664 }
10665
10666 static int
10667 api_policer_dump(vat_main_t *vam)
10668 {
10669     unformat_input_t * i = vam->input;
10670     vl_api_policer_dump_t *mp;
10671     f64 timeout = ~0;
10672     u8 *match_name = 0;
10673     u8 match_name_valid = 0;
10674
10675     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10676         if (unformat (i, "name %s", &match_name)) {
10677             vec_add1 (match_name, 0);
10678             match_name_valid = 1;
10679         } else
10680             break;
10681     }
10682
10683     M(POLICER_DUMP, policer_dump);
10684     mp->match_name_valid = match_name_valid;
10685     clib_memcpy (mp->match_name, match_name, vec_len (match_name));
10686     vec_free (match_name);
10687     /* send it... */
10688     S;
10689
10690     /* Use a control ping for synchronization */
10691     {
10692         vl_api_control_ping_t * mp;
10693         M(CONTROL_PING, control_ping);
10694         S;
10695     }
10696     /* Wait for a reply... */
10697     W;
10698
10699     /* NOTREACHED */
10700     return 0;
10701 }
10702
10703 static int
10704 api_netmap_create (vat_main_t * vam)
10705 {
10706     unformat_input_t * i = vam->input;
10707     vl_api_netmap_create_t * mp;
10708     f64 timeout;
10709     u8 * if_name = 0;
10710     u8 hw_addr[6];
10711     u8 random_hw_addr = 1;
10712     u8 is_pipe = 0;
10713     u8 is_master = 0;
10714
10715     memset (hw_addr, 0, sizeof (hw_addr));
10716
10717     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10718         if (unformat (i, "name %s", &if_name))
10719             vec_add1 (if_name, 0);
10720         else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr))
10721             random_hw_addr = 0;
10722         else if (unformat (i, "pipe"))
10723             is_pipe = 1;
10724         else if (unformat (i, "master"))
10725             is_master = 1;
10726         else if (unformat (i, "slave"))
10727             is_master = 0;
10728         else
10729           break;
10730     }
10731
10732     if (!vec_len (if_name)) {
10733         errmsg ("interface name must be specified");
10734         return -99;
10735     }
10736
10737     if (vec_len (if_name) > 64) {
10738         errmsg ("interface name too long");
10739         return -99;
10740     }
10741
10742     M(NETMAP_CREATE, netmap_create);
10743
10744     clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name));
10745     clib_memcpy (mp->hw_addr, hw_addr, 6);
10746     mp->use_random_hw_addr = random_hw_addr;
10747     mp->is_pipe = is_pipe;
10748     mp->is_master = is_master;
10749     vec_free (if_name);
10750
10751     S; W;
10752     /* NOTREACHED */
10753     return 0;
10754 }
10755
10756 static int
10757 api_netmap_delete (vat_main_t * vam)
10758 {
10759     unformat_input_t * i = vam->input;
10760     vl_api_netmap_delete_t * mp;
10761     f64 timeout;
10762     u8 * if_name = 0;
10763
10764     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
10765         if (unformat (i, "name %s", &if_name))
10766             vec_add1 (if_name, 0);
10767         else
10768             break;
10769     }
10770
10771     if (!vec_len (if_name)) {
10772         errmsg ("interface name must be specified");
10773         return -99;
10774     }
10775
10776     if (vec_len (if_name) > 64) {
10777         errmsg ("interface name too long");
10778         return -99;
10779     }
10780
10781     M(NETMAP_DELETE, netmap_delete);
10782
10783     clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name));
10784     vec_free (if_name);
10785
10786     S; W;
10787     /* NOTREACHED */
10788     return 0;
10789 }
10790
10791 static int q_or_quit (vat_main_t * vam)
10792 {
10793     longjmp (vam->jump_buf, 1);
10794     return 0; /* not so much */
10795 }
10796 static int q (vat_main_t * vam) {return q_or_quit (vam);}
10797 static int quit (vat_main_t * vam) {return q_or_quit (vam);}
10798
10799 static int comment (vat_main_t * vam)
10800 {
10801     return 0;
10802 }
10803
10804 static int cmd_cmp (void * a1, void * a2)
10805 {
10806   u8 ** c1 = a1;
10807   u8 ** c2 = a2;
10808
10809   return strcmp ((char *)(c1[0]), (char *)(c2[0]));
10810 }
10811
10812 static int help (vat_main_t * vam)
10813 {
10814     u8 ** cmds = 0;
10815     u8 * name = 0;
10816     hash_pair_t * p;
10817     unformat_input_t * i = vam->input;
10818     int j;
10819
10820     if (unformat (i, "%s", &name)) {
10821         uword *hs;
10822
10823         vec_add1(name, 0);
10824
10825         hs = hash_get_mem (vam->help_by_name, name);
10826         if (hs)
10827             fformat (vam->ofp, "usage: %s %s\n", name, hs[0]);
10828         else
10829             fformat (vam->ofp, "No such msg / command '%s'\n", name);
10830         vec_free(name);
10831         return 0;
10832     }
10833
10834     fformat(vam->ofp, "Help is available for the following:\n");
10835
10836     hash_foreach_pair (p, vam->function_by_name, 
10837     ({
10838         vec_add1 (cmds, (u8 *)(p->key));
10839     }));
10840
10841     vec_sort_with_function (cmds, cmd_cmp);
10842
10843     for (j = 0; j < vec_len(cmds); j++)
10844         fformat (vam->ofp, "%s\n", cmds[j]);
10845
10846     vec_free (cmds);
10847     return 0;
10848 }
10849
10850 static int set (vat_main_t * vam)
10851 {
10852     u8 * name = 0, * value = 0;
10853     unformat_input_t * i = vam->input;
10854
10855     if (unformat (i, "%s", &name)) {
10856         /* The input buffer is a vector, not a string. */
10857         value = vec_dup (i->buffer);
10858         vec_delete (value, i->index, 0);
10859         /* Almost certainly has a trailing newline */
10860         if (value[vec_len(value)-1] == '\n')
10861             value[vec_len(value)-1] = 0;
10862         /* Make sure it's a proper string, one way or the other */
10863         vec_add1 (value, 0);
10864         (void) clib_macro_set_value (&vam->macro_main, 
10865                                      (char *)name, (char *)value);
10866     }
10867     else
10868         errmsg ("usage: set <name> <value>\n");
10869
10870     vec_free (name);
10871     vec_free (value);
10872     return 0;
10873 }
10874
10875 static int unset (vat_main_t * vam)
10876 {
10877     u8 * name = 0;
10878
10879     if (unformat (vam->input, "%s", &name))
10880         if (clib_macro_unset (&vam->macro_main, (char *)name) == 1)
10881             errmsg ("unset: %s wasn't set\n", name);
10882     vec_free (name);
10883     return 0;
10884 }
10885
10886 typedef struct {
10887     u8 * name;
10888     u8 * value;
10889 } macro_sort_t;
10890
10891
10892 static int macro_sort_cmp (void * a1, void * a2)
10893 {
10894   macro_sort_t * s1 = a1;
10895   macro_sort_t * s2 = a2;
10896
10897   return strcmp ((char *)(s1->name), (char *)(s2->name));
10898 }
10899
10900 static int dump_macro_table (vat_main_t * vam)
10901 {
10902     macro_sort_t * sort_me = 0, * sm;    
10903     int i;
10904     hash_pair_t * p;
10905
10906     hash_foreach_pair (p, vam->macro_main.the_value_table_hash, 
10907     ({
10908         vec_add2 (sort_me, sm, 1);
10909         sm->name = (u8 *)(p->key);
10910         sm->value = (u8 *) (p->value[0]);
10911     }));
10912     
10913     vec_sort_with_function (sort_me, macro_sort_cmp);
10914
10915     if (vec_len(sort_me))
10916         fformat (vam->ofp, "%-15s%s\n", "Name", "Value");
10917     else
10918         fformat (vam->ofp, "The macro table is empty...\n");
10919
10920     for (i = 0; i < vec_len (sort_me); i++)
10921         fformat (vam->ofp, "%-15s%s\n", sort_me[i].name,
10922                  sort_me[i].value);
10923     return 0;
10924 }
10925
10926 static int dump_node_table (vat_main_t * vam)
10927 {
10928     int i, j;
10929     vlib_node_t * node, * next_node;
10930
10931     if (vec_len (vam->graph_nodes) == 0) {
10932         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
10933         return 0;
10934     }
10935
10936     for (i = 0; i < vec_len (vam->graph_nodes); i++) {
10937         node = vam->graph_nodes[i];
10938         fformat (vam->ofp, "[%d] %s\n", i, node->name);
10939         for (j = 0; j < vec_len (node->next_nodes); j++) {
10940             if (node->next_nodes[j] != ~0) {
10941                 next_node = vam->graph_nodes[node->next_nodes[j]];
10942                 fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
10943             }
10944         }
10945     }
10946     return 0;
10947 }
10948
10949 static int search_node_table (vat_main_t * vam)
10950 {
10951     unformat_input_t * line_input = vam->input;
10952     u8 * node_to_find;
10953     int j;
10954     vlib_node_t * node, * next_node;
10955     uword * p;
10956
10957     if (vam->graph_node_index_by_name == 0) {
10958         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
10959         return 0;
10960     }
10961
10962     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
10963         if (unformat (line_input, "%s", &node_to_find)) {
10964             vec_add1 (node_to_find, 0);
10965             p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
10966             if (p == 0) {
10967                 fformat (vam->ofp, "%s not found...\n", node_to_find);
10968                 goto out;
10969             }
10970             node = vam->graph_nodes[p[0]];
10971             fformat (vam->ofp, "[%d] %s\n", p[0], node->name);
10972             for (j = 0; j < vec_len (node->next_nodes); j++) {
10973                 if (node->next_nodes[j] != ~0) {
10974                     next_node = vam->graph_nodes[node->next_nodes[j]];
10975                     fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
10976                 }
10977             }
10978         }
10979             
10980         else {
10981             clib_warning ("parse error '%U'", format_unformat_error, 
10982                           line_input);
10983             return -99;
10984         }
10985
10986     out:
10987         vec_free(node_to_find);
10988         
10989     }
10990
10991     return 0;        
10992 }
10993
10994
10995 static int script (vat_main_t * vam)
10996 {
10997     u8 * s = 0;
10998     char * save_current_file;
10999     unformat_input_t save_input;
11000     jmp_buf save_jump_buf;
11001     u32 save_line_number;
11002
11003     FILE * new_fp, * save_ifp;
11004
11005     if (unformat (vam->input, "%s", &s)) {
11006         new_fp = fopen ((char *)s, "r");
11007         if (new_fp == 0) {
11008             errmsg ("Couldn't open script file %s\n", s);
11009             vec_free (s);
11010             return -99;
11011         }
11012     } else {
11013         errmsg ("Missing script name\n");
11014         return -99;
11015     }
11016
11017     clib_memcpy (&save_input, &vam->input, sizeof (save_input));
11018     clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
11019     save_ifp = vam->ifp;
11020     save_line_number = vam->input_line_number;
11021     save_current_file = (char *) vam->current_file;
11022
11023     vam->input_line_number = 0;
11024     vam->ifp = new_fp;
11025     vam->current_file = s;
11026     do_one_file (vam);
11027
11028     clib_memcpy (&vam->input, &save_input, sizeof (vam->input));
11029     clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
11030     vam->ifp = save_ifp;
11031     vam->input_line_number = save_line_number;
11032     vam->current_file = (u8 *) save_current_file;
11033     vec_free (s);
11034
11035     return 0;
11036 }
11037
11038 static int echo (vat_main_t * vam)
11039 {
11040     fformat (vam->ofp, "%v", vam->input->buffer);
11041     return 0;
11042 }
11043
11044 /* List of API message constructors, CLI names map to api_xxx */
11045 #define foreach_vpe_api_msg                                             \
11046 _(create_loopback,"[mac <mac-addr>]")                                   \
11047 _(sw_interface_dump,"")                                                 \
11048 _(sw_interface_set_flags,                                               \
11049   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
11050 _(sw_interface_add_del_address,                                         \
11051   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
11052 _(sw_interface_set_table,                                               \
11053   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
11054 _(sw_interface_set_vpath,                                               \
11055   "<intfc> | sw_if_index <id> enable | disable")                        \
11056 _(sw_interface_set_l2_xconnect,                                         \
11057   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
11058   "enable | disable")                                                   \
11059 _(sw_interface_set_l2_bridge,                                           \
11060   "rx <intfc> | rx_sw_if_index <id> bd_id <bridge-domain-id>\n"         \
11061   "[shg <split-horizon-group>] [bvi]\n"                                 \
11062   "enable | disable")                                                   \
11063 _(bridge_domain_add_del,                                                \
11064   "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [del]\n")\
11065 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")     \
11066 _(l2fib_add_del,                                                        \
11067   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi]\n") \
11068 _(l2_flags,                                                             \
11069   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood]\n")       \
11070 _(bridge_flags,                                                         \
11071   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
11072 _(tap_connect,                                                          \
11073   "tapname <name> mac <mac-addr> | random-mac")                         \
11074 _(tap_modify,                                                           \
11075   "<vpp-if-name> | sw_if_index <id> tapname <name> mac <mac-addr> | random-mac") \
11076 _(tap_delete,                                                           \
11077   "<vpp-if-name> | sw_if_index <id>")                                   \
11078 _(sw_interface_tap_dump, "")                                            \
11079 _(ip_add_del_route,                                                     \
11080   "<addr>/<mask> via <addr> [vrf <n>]\n"                                \
11081   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
11082   "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
11083   "[multipath] [count <n>]")                                            \
11084 _(proxy_arp_add_del,                                                    \
11085   "<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]")                      \
11086 _(proxy_arp_intfc_enable_disable,                                       \
11087   "<intfc> | sw_if_index <id> enable | disable")                        \
11088 _(mpls_add_del_encap,                                                   \
11089   "label <n> dst <ip4-addr> [vrf <n>] [del]")                           \
11090 _(mpls_add_del_decap,                                                   \
11091   "label <n> [rx_vrf_id <n>] [tx_vrf_id] [s-bit-clear][del]")           \
11092 _(mpls_gre_add_del_tunnel,                                              \
11093   "inner_vrf_id <n> outer_vrf_id <n> src <ip4-address> dst <ip4-address>\n" \
11094   "adj <ip4-address>/<mask-width> [del]")                               \
11095 _(sw_interface_set_unnumbered,                                          \
11096   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
11097 _(ip_neighbor_add_del,                                                  \
11098   "<intfc> | sw_if_index <id> dst <ip46-address> mac <mac-addr>")       \
11099 _(reset_vrf, "vrf <id> [ipv6]")                                         \
11100 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
11101 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
11102   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
11103   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
11104   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
11105 _(oam_add_del, "src <ip4-address> dst <ip4-address> [vrf <n>] [del]")   \
11106 _(reset_fib, "vrf <n> [ipv6]")                                          \
11107 _(dhcp_proxy_config,                                                    \
11108   "svr <v46-address> src <v46-address>\n"                               \
11109    "insert-cid <n> [del]")                                              \
11110 _(dhcp_proxy_config_2,                                                  \
11111   "svr <v46-address> src <v46-address>\n"                               \
11112    "rx_vrf_id <nn> server_vrf_id <nn> insert-cid <n> [del]")            \
11113 _(dhcp_proxy_set_vss,                                                   \
11114   "tbl_id <n> fib_id <n> oui <n> [ipv6] [del]")                         \
11115 _(dhcp_client_config,                                                   \
11116   "<intfc> | sw_if_index <id> [hostname <name>] [disable_event] [del]") \
11117 _(set_ip_flow_hash,                                                     \
11118   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
11119 _(sw_interface_ip6_enable_disable,                                      \
11120   "<intfc> | sw_if_index <id> enable | disable")                        \
11121 _(sw_interface_ip6_set_link_local_address,                              \
11122   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>")              \
11123 _(sw_interface_ip6nd_ra_prefix,                                         \
11124   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>\n"             \
11125   "val_life <n> pref_life <n> [def] [noadv] [offl] [noauto]\n"          \
11126   "[nolink] [isno]")                                                    \
11127 _(sw_interface_ip6nd_ra_config,                                         \
11128   "<intfc> | sw_if_index <id> [maxint <n>] [minint <n>]\n"              \
11129   "[life <n>] [count <n>] [interval <n>] [surpress]\n"                  \
11130   "[managed] [other] [ll] [send] [cease] [isno] [def]")                 \
11131 _(set_arp_neighbor_limit, "arp_nbr_limit <n> [ipv6]")                   \
11132 _(l2_patch_add_del,                                                     \
11133   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
11134   "enable | disable")                                                   \
11135 _(mpls_ethernet_add_del_tunnel,                                         \
11136   "tx <intfc> | tx_sw_if_index <n> dst <mac-addr>\n"                    \
11137   "adj <ip4-addr>/<mw> dst <mac-addr> [del]")                           \
11138 _(mpls_ethernet_add_del_tunnel_2,                                       \
11139   "inner_vrf_id <n> outer_vrf_id <n> next-hop <ip4-addr>\n"             \
11140   "resolve-attempts <n> resolve-if-needed 0 | 1 [del]")                 \
11141 _(sr_tunnel_add_del,                                                    \
11142   "[name <name>] src <ip6-addr> dst <ip6-addr>/<mw> \n"                 \
11143   "(next <ip6-addr>)+ [tag <ip6-addr>]* [clean] [reroute] \n"           \
11144   "[policy <policy_name>]")                                             \
11145 _(sr_policy_add_del,                                                    \
11146   "name <name> tunnel <tunnel-name> [tunnel <tunnel-name>]* [del]")     \
11147 _(sr_multicast_map_add_del,                                             \
11148   "address [ip6 multicast address] sr-policy [policy name] [del]")      \
11149 _(classify_add_del_table,                                               \
11150   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
11151   "[del] mask <mask-value>\n"                                           \
11152   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>")              \
11153 _(classify_add_del_session,                                             \
11154   "[hit-next|l2-hit-next|acl-hit-next] <name|nn> table-index <nn>\n"    \
11155   "skip_n <nn> match_n <nn> match [hex] [l2] [l3 [ip4|ip6]]")           \
11156 _(classify_set_interface_ip_table,                                      \
11157   "<intfc> | sw_if_index <nn> table <nn>")                              \
11158 _(classify_set_interface_l2_tables,                                     \
11159   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
11160   "  [other-table <nn>]")                                               \
11161 _(get_node_index, "node <node-name")                                    \
11162 _(add_node_next, "node <node-name> next <next-node-name>")              \
11163 _(l2tpv3_create_tunnel,                                                 \
11164   "client_address <ip6-addr> our_address <ip6-addr>\n"                  \
11165   "[local_session_id <nn>][remote_session_id <nn>][local_cookie <nn>]\n"\
11166   "[remote_cookie <nn>]\n[l2-sublayer-preset]\n")                       \
11167 _(l2tpv3_set_tunnel_cookies,                                            \
11168   "<intfc> | sw_if_index <nn> [new_local_cookie <nn>]\n"                \
11169   "[new_remote_cookie <nn>]\n")                                         \
11170 _(l2tpv3_interface_enable_disable,                                      \
11171   "<intfc> | sw_if_index <nn> enable | disable")                        \
11172 _(l2tpv3_set_lookup_key,                                                \
11173   "lookup_v6_src | lookup_v6_dst | lookup_session_id")                  \
11174 _(sw_if_l2tpv3_tunnel_dump, "")                                         \
11175 _(vxlan_add_del_tunnel,                                                 \
11176   "src <ip-addr> dst <ip-addr> vni <vni> [encap-vrf-id <nn>]\n"         \
11177   " [decap-next l2|ip4|ip6] [del]")                                     \
11178 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
11179 _(gre_add_del_tunnel,                                                   \
11180   "src <ip4-addr> dst <ip4-addr> [outer-fib-id <nn>] [del]\n")          \
11181 _(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                      \
11182 _(l2_fib_clear_table, "")                                               \
11183 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
11184 _(l2_interface_vlan_tag_rewrite,                                        \
11185   "<intfc> | sw_if_index <nn> \n"                                       \
11186   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
11187   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
11188 _(create_vhost_user_if,                                                 \
11189         "socket <filename> [server] [renumber <dev_instance>] "         \
11190         "[mac <mac_address>]")                                          \
11191 _(modify_vhost_user_if,                                                 \
11192         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
11193         "[server] [renumber <dev_instance>]")                           \
11194 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
11195 _(sw_interface_vhost_user_dump, "")                                     \
11196 _(show_version, "")                                                     \
11197 _(vxlan_gpe_add_del_tunnel,                                             \
11198   "local <addr> remote <addr> vni <nn>\n"                               \
11199     "[encap-vrf-id <nn>] [decap-vrf-id <nn>] [next-ip4][next-ip6]"      \
11200   "[next-ethernet] [next-nsh]\n")                                       \
11201 _(vxlan_gpe_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                \
11202 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
11203 _(interface_name_renumber,                                              \
11204   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
11205 _(input_acl_set_interface,                                              \
11206   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
11207   "  [l2-table <nn>] [del]")                                            \
11208 _(want_ip4_arp_events, "address <ip4-address> [del]")                   \
11209 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
11210 _(ip_dump, "ipv4 | ipv6")                                               \
11211 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
11212 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
11213   "  spid_id <n> ")                                                     \
11214 _(ipsec_sad_add_del_entry, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
11215   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
11216   "  integ_alg <alg> integ_key <hex>")                                  \
11217 _(ipsec_spd_add_del_entry, "spd_id <n> priority <n> action <action>\n"  \
11218   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
11219   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
11220   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" )\
11221 _(ipsec_sa_set_key, "sa_id <n> crypto_key <hex> integ_key <hex>")       \
11222 _(ikev2_profile_add_del, "name <profile_name> [del]")                   \
11223 _(ikev2_profile_set_auth, "name <profile_name> auth_method <method>\n"  \
11224   "(auth_data 0x<data> | auth_data <data>)")                            \
11225 _(ikev2_profile_set_id, "name <profile_name> id_type <type>\n"          \
11226   "(id_data 0x<data> | id_data <data>) (local|remote)")                 \
11227 _(ikev2_profile_set_ts, "name <profile_name> protocol <proto>\n"        \
11228   "start_port <port> end_port <port> start_addr <ip4> end_addr <ip4>\n" \
11229   "(local|remote)")                                                     \
11230 _(ikev2_set_local_key, "file <absolute_file_path>")                     \
11231 _(delete_loopback,"sw_if_index <nn>")                                   \
11232 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
11233 _(map_add_domain,                                                       \
11234   "ip4-pfx <ip4pfx> ip6-pfx <ip6pfx> "                                  \
11235   "ip6-src <ip6addr> "                                                  \
11236   "ea-bits-len <n> psid-offset <n> psid-len <n>")                       \
11237 _(map_del_domain, "index <n>")                                          \
11238 _(map_add_del_rule,                                                     \
11239   "index <n> psid <n> dst <ip6addr> [del]")                             \
11240 _(map_domain_dump, "")                                                  \
11241 _(map_rule_dump, "index <map-domain>")                                  \
11242 _(want_interface_events,  "enable|disable")                             \
11243 _(want_stats,"enable|disable")                                          \
11244 _(get_first_msg_id, "client <name>")                                    \
11245 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
11246 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
11247   "fib-id <nn> [ip4][ip6][default]")                                    \
11248 _(get_node_graph, " ")                                                  \
11249 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
11250 _(trace_profile_add, "id <nn> trace-type <0x1f|0x3|0x9|0x11|0x19> "     \
11251   "trace-elts <nn> trace-tsp <0|1|2|3> node-id <node id in hex> "       \
11252   "app-data <app_data in hex> [pow] [ppc <encap|decap>]")               \
11253 _(trace_profile_apply, "id <nn> <ip6-address>/<width>"                  \
11254   " vrf_id <nn>  add | pop | none")                                     \
11255 _(trace_profile_del, "")                                                \
11256 _(lisp_add_del_locator_set, "locator-set <locator_name> [del]")         \
11257 _(lisp_add_del_locator, "locator-set <locator_name> "                   \
11258                         "iface <intf> | sw_if_index <sw_if_index> "     \
11259                         "p <priority> w <weight> [del]")                \
11260 _(lisp_add_del_local_eid, "<ipv4|ipv6>/<prefix> "                       \
11261                           "locator-set <locator_name> [del]")           \
11262 _(lisp_gpe_add_del_fwd_entry, "eid <ip4|6-addr>/<prefix> "              \
11263     "sloc <ip4/6-addr> dloc <ip4|6-addr> [del]")                        \
11264 _(lisp_add_del_map_resolver, "<ip4|6-addr> [del]")                      \
11265 _(lisp_gpe_enable_disable, "enable|disable")                            \
11266 _(lisp_enable_disable, "enable|disable")                                \
11267 _(lisp_gpe_add_del_iface, "up|down")                                    \
11268 _(lisp_add_del_remote_mapping, "add|del vni <vni> table-id <id> "       \
11269                                "deid <dest-eid> seid"                   \
11270                                " <src-eid> rloc <locator> "             \
11271                                "[rloc <loc> ... ]")                     \
11272 _(lisp_pitr_set_locator_set, "locator-set <loc-set-name> | del")        \
11273 _(lisp_locator_set_dump, "")                                            \
11274 _(lisp_local_eid_table_dump, "")                                        \
11275 _(lisp_gpe_tunnel_dump, "")                                             \
11276 _(lisp_map_resolver_dump, "")                                           \
11277 _(lisp_enable_disable_status_dump, "")                                  \
11278 _(af_packet_create, "name <host interface name> [hw_addr <mac>]")       \
11279 _(af_packet_delete, "name <host interface name>")                       \
11280 _(policer_add_del, "name <policer name> <params> [del]")                \
11281 _(policer_dump, "[name <policer name>]")                                \
11282 _(netmap_create, "name <interface name> [hw-addr <mac>] [pipe] "        \
11283     "[master|slave]")                                                   \
11284 _(netmap_delete, "name <interface name>")
11285
11286 /* List of command functions, CLI names map directly to functions */
11287 #define foreach_cli_function                                    \
11288 _(comment, "usage: comment <ignore-rest-of-line>")              \
11289 _(dump_interface_table, "usage: dump_interface_table")          \
11290 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
11291 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
11292 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
11293 _(dump_stats_table, "usage: dump_stats_table")                  \
11294 _(dump_macro_table, "usage: dump_macro_table ")                 \
11295 _(dump_node_table, "usage: dump_node_table")                    \
11296 _(echo, "usage: echo <message>")                                \
11297 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
11298 _(help, "usage: help")                                          \
11299 _(q, "usage: quit")                                             \
11300 _(quit, "usage: quit")                                          \
11301 _(search_node_table, "usage: search_node_table <name>...")      \
11302 _(set, "usage: set <variable-name> <value>")                    \
11303 _(script, "usage: script <file-name>")                          \
11304 _(unset, "usage: unset <variable-name>")
11305
11306 #define _(N,n)                                  \
11307     static void vl_api_##n##_t_handler_uni      \
11308     (vl_api_##n##_t * mp)                       \
11309     {                                           \
11310         vat_main_t * vam = &vat_main;           \
11311         if (vam->json_output) {                 \
11312             vl_api_##n##_t_handler_json(mp);    \
11313         } else {                                \
11314             vl_api_##n##_t_handler(mp);         \
11315         }                                       \
11316     }
11317 foreach_vpe_api_reply_msg;
11318 #undef _
11319
11320 void vat_api_hookup (vat_main_t *vam)
11321 {
11322 #define _(N,n)                                                  \
11323     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
11324                            vl_api_##n##_t_handler_uni,          \
11325                            vl_noop_handler,                     \
11326                            vl_api_##n##_t_endian,               \
11327                            vl_api_##n##_t_print,                \
11328                            sizeof(vl_api_##n##_t), 1); 
11329     foreach_vpe_api_reply_msg;
11330 #undef _
11331
11332     vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
11333
11334     vam->sw_if_index_by_interface_name = 
11335         hash_create_string (0, sizeof (uword));
11336
11337     vam->function_by_name = 
11338         hash_create_string (0, sizeof(uword));
11339
11340     vam->help_by_name = 
11341         hash_create_string (0, sizeof(uword));
11342
11343     /* API messages we can send */
11344 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
11345     foreach_vpe_api_msg;
11346 #undef _
11347
11348     /* Help strings */
11349 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
11350     foreach_vpe_api_msg;
11351 #undef _
11352
11353     /* CLI functions */
11354 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
11355     foreach_cli_function;
11356 #undef _
11357
11358     /* Help strings */
11359 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
11360     foreach_cli_function;
11361 #undef _
11362 }
11363
11364 #undef vl_api_version
11365 #define vl_api_version(n,v) static u32 vpe_api_version = v;
11366 #include <api/vpe.api.h>
11367 #undef vl_api_version
11368
11369 void vl_client_add_api_signatures (vl_api_memclnt_create_t *mp) 
11370 {
11371     /* 
11372      * Send the main API signature in slot 0. This bit of code must
11373      * match the checks in ../vpe/api/api.c: vl_msg_api_version_check().
11374      */
11375     mp->api_versions[0] = clib_host_to_net_u32 (vpe_api_version);
11376 }