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