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