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