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