Add vpe-api message to get vxlan tunnel details.
[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 _(VXLAN_TUNNEL_DETAILS, vxlan_tunnel_details)                           \
1884 _(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply)                   \
1885 _(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply)         \
1886 _(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \
1887 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
1888 _(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply)               \
1889 _(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply)               \
1890 _(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply)               \
1891 _(SHOW_VERSION_REPLY, show_version_reply)                               \
1892 _(NSH_GRE_ADD_DEL_TUNNEL_REPLY, nsh_gre_add_del_tunnel_reply)           \
1893 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
1894 _(NSH_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, nsh_vxlan_gpe_add_del_tunnel_reply) \
1895 _(LISP_GPE_ADD_DEL_TUNNEL_REPLY, lisp_gpe_add_del_tunnel_reply)         \
1896 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
1897 _(WANT_IP4_ARP_EVENTS_REPLY, want_ip4_arp_events_reply)                 \
1898 _(IP4_ARP_EVENT, ip4_arp_event)                                         \
1899 _(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply)         \
1900 _(IP_ADDRESS_DETAILS, ip_address_details)                               \
1901 _(IP_DETAILS, ip_details)                                               \
1902 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
1903 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
1904 _(IPSEC_SPD_ADD_DEL_ENTRY_REPLY, ipsec_spd_add_del_entry_reply)         \
1905 _(IPSEC_SAD_ADD_DEL_ENTRY_REPLY, ipsec_sad_add_del_entry_reply)         \
1906 _(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply)                       \
1907 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
1908 _(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply)                     \
1909 _(DHCP_COMPL_EVENT, dhcp_compl_event)                                   \
1910 _(VNET_INTERFACE_COUNTERS, vnet_interface_counters)                     \
1911 _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters)                         \
1912 _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters)                         \
1913 _(MAP_ADD_DOMAIN_REPLY, map_add_domain_reply)                           \
1914 _(MAP_DEL_DOMAIN_REPLY, map_del_domain_reply)                           \
1915 _(MAP_ADD_DEL_RULE_REPLY, map_add_del_rule_reply)                                   \
1916 _(MAP_DOMAIN_DETAILS, map_domain_details)                               \
1917 _(MAP_RULE_DETAILS, map_rule_details)                                   \
1918 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
1919 _(WANT_STATS_REPLY, want_stats_reply)                                   \
1920 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)    
1921
1922 /* M: construct, but don't yet send a message */
1923
1924 #define M(T,t)                                  \
1925 do {                                            \
1926     vam->result_ready = 0;                      \
1927     mp = vl_msg_api_alloc(sizeof(*mp));         \
1928     memset (mp, 0, sizeof (*mp));               \
1929     mp->_vl_msg_id = ntohs (VL_API_##T);        \
1930     mp->client_index = vam->my_client_index;    \
1931 } while(0);
1932
1933 #define M2(T,t,n)                               \
1934 do {                                            \
1935     vam->result_ready = 0;                      \
1936     mp = vl_msg_api_alloc(sizeof(*mp)+(n));     \
1937     memset (mp, 0, sizeof (*mp));               \
1938     mp->_vl_msg_id = ntohs (VL_API_##T);        \
1939     mp->client_index = vam->my_client_index;    \
1940 } while(0);
1941
1942
1943 /* S: send a message */
1944 #define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp))
1945
1946 /* W: wait for results, with timeout */
1947 #define W                                       \
1948 do {                                            \
1949     timeout = vat_time_now (vam) + 1.0;         \
1950                                                 \
1951     while (vat_time_now (vam) < timeout) {      \
1952         if (vam->result_ready == 1) {           \
1953             return (vam->retval);               \
1954         }                                       \
1955     }                                           \
1956     return -99;                                 \
1957 } while(0);
1958
1959 typedef struct {
1960     u8 * name;
1961     u32 value;
1962 } name_sort_t;
1963
1964
1965 #define STR_VTR_OP_CASE(op)     \
1966     case L2_VTR_ ## op:         \
1967         return "" # op;
1968
1969 static const char *str_vtr_op(u32 vtr_op)
1970 {
1971     switch(vtr_op) {
1972         STR_VTR_OP_CASE(DISABLED);
1973         STR_VTR_OP_CASE(PUSH_1);
1974         STR_VTR_OP_CASE(PUSH_2);
1975         STR_VTR_OP_CASE(POP_1);
1976         STR_VTR_OP_CASE(POP_2);
1977         STR_VTR_OP_CASE(TRANSLATE_1_1);
1978         STR_VTR_OP_CASE(TRANSLATE_1_2);
1979         STR_VTR_OP_CASE(TRANSLATE_2_1);
1980         STR_VTR_OP_CASE(TRANSLATE_2_2);
1981     }
1982
1983     return "UNKNOWN";
1984 }
1985
1986 static int dump_sub_interface_table (vat_main_t * vam)
1987 {
1988     const sw_interface_subif_t * sub = NULL;
1989
1990     if (vam->json_output) {
1991         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
1992         return -99;
1993     }
1994
1995     fformat (vam->ofp,
1996              "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s\n",
1997              "Interface", "sw_if_index",
1998              "sub id", "dot1ad", "tags", "outer id",
1999              "inner id", "exact", "default",
2000              "outer any", "inner any");
2001
2002     vec_foreach (sub, vam->sw_if_subif_table) {
2003         fformat (vam->ofp,
2004                  "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d\n",
2005                  sub->interface_name,
2006                  sub->sw_if_index,
2007                  sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
2008                  sub->sub_number_of_tags, sub->sub_outer_vlan_id,
2009                  sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
2010                  sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2011         if (sub->vtr_op != L2_VTR_DISABLED) {
2012             fformat (vam->ofp,
2013                      "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2014                      "tag1: %d tag2: %d ]\n",
2015                      str_vtr_op(sub->vtr_op), sub->vtr_push_dot1q, 
2016                      sub->vtr_tag1, sub->vtr_tag2);
2017         }
2018     }
2019
2020     return 0;
2021 }
2022
2023 static int name_sort_cmp (void * a1, void * a2)
2024 {
2025   name_sort_t * n1 = a1;
2026   name_sort_t * n2 = a2;
2027
2028   return strcmp ((char *)n1->name, (char *)n2->name);
2029 }
2030
2031 static int dump_interface_table (vat_main_t * vam)
2032 {
2033     hash_pair_t * p;
2034     name_sort_t * nses = 0, * ns;
2035
2036     if (vam->json_output) {
2037         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
2038         return -99;
2039     }
2040
2041     hash_foreach_pair (p, vam->sw_if_index_by_interface_name, 
2042     ({
2043         vec_add2 (nses, ns, 1);
2044         ns->name = (u8 *)(p->key);
2045         ns->value = (u32) p->value[0];
2046     }));
2047
2048     vec_sort_with_function (nses, name_sort_cmp);
2049
2050     fformat (vam->ofp, "%-25s%-15s\n", "Interface", "sw_if_index");
2051     vec_foreach (ns, nses) {
2052         fformat (vam->ofp, "%-25s%-15d\n", ns->name, ns->value);
2053     }
2054     vec_free (nses);
2055     return 0;
2056 }
2057
2058 static int dump_ip_table (vat_main_t * vam, int is_ipv6)
2059 {
2060     const ip_details_t * det = NULL;
2061     const ip_address_details_t * address = NULL;
2062     u32 i = ~0;
2063
2064     fformat (vam->ofp,
2065              "%-12s\n",
2066              "sw_if_index");
2067
2068     if (0 == vam->ip_details_by_sw_if_index) {
2069         return 0;
2070     }
2071
2072     vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6]) {
2073         i++;
2074         if (!det->present) {
2075             continue;
2076         }
2077         fformat (vam->ofp,
2078                  "%-12d\n",
2079                  i);
2080         fformat (vam->ofp,
2081                  "            %-30s%-13s\n",
2082                  "Address", "Prefix length");
2083         if (!det->addr) {
2084             continue;
2085         }
2086         vec_foreach (address, det->addr) {
2087             fformat (vam->ofp,
2088                      "            %-30U%-13d\n",
2089                      is_ipv6 ? format_ip6_address : format_ip4_address,
2090                      address->ip,
2091                      address->prefix_length);
2092         }
2093     }
2094
2095     return 0;
2096 }
2097
2098 static int dump_ipv4_table (vat_main_t * vam)
2099 {
2100     if (vam->json_output) {
2101         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
2102         return -99;
2103     }
2104
2105     return dump_ip_table (vam, 0);
2106 }
2107
2108 static int dump_ipv6_table (vat_main_t * vam)
2109 {
2110     if (vam->json_output) {
2111         clib_warning ("JSON output supported only for VPE API calls and dump_stats_table");
2112         return -99;
2113     }
2114
2115     return dump_ip_table (vam, 1);
2116 }
2117
2118 static char* counter_type_to_str (u8 counter_type, u8 is_combined)
2119 {
2120     if (!is_combined) {
2121         switch(counter_type) {
2122         case VNET_INTERFACE_COUNTER_DROP:
2123             return "drop";
2124         case VNET_INTERFACE_COUNTER_PUNT:
2125             return "punt";
2126         case VNET_INTERFACE_COUNTER_IP4:
2127             return "ip4";
2128         case VNET_INTERFACE_COUNTER_IP6:
2129             return "ip6";
2130         case VNET_INTERFACE_COUNTER_RX_NO_BUF:
2131             return "rx-no-buf";
2132         case VNET_INTERFACE_COUNTER_RX_MISS:
2133             return "rx-miss";
2134         case VNET_INTERFACE_COUNTER_RX_ERROR:
2135             return "rx-error";
2136         case VNET_INTERFACE_COUNTER_TX_ERROR:
2137             return "tx-error";
2138         default:
2139             return "INVALID-COUNTER-TYPE";
2140         }
2141     } else {
2142         switch(counter_type) {
2143         case VNET_INTERFACE_COUNTER_RX:
2144             return "rx";
2145         case VNET_INTERFACE_COUNTER_TX:
2146             return "tx";
2147         default:
2148             return "INVALID-COUNTER-TYPE";
2149         }
2150     }
2151 }
2152
2153 static int dump_stats_table (vat_main_t * vam)
2154 {
2155     vat_json_node_t node;
2156     vat_json_node_t *msg_array;
2157     vat_json_node_t *msg;
2158     vat_json_node_t *counter_array;
2159     vat_json_node_t *counter;
2160     interface_counter_t c;
2161     u64 packets;
2162     ip4_fib_counter_t *c4;
2163     ip6_fib_counter_t *c6;
2164     int i, j;
2165
2166     if (!vam->json_output) {
2167         clib_warning ("dump_stats_table supported only in JSON format");
2168         return -99;
2169     }
2170
2171     vat_json_init_object(&node);
2172
2173     /* interface counters */
2174     msg_array = vat_json_object_add(&node, "interface_counters");
2175     vat_json_init_array(msg_array);
2176     for (i = 0; i < vec_len(vam->simple_interface_counters); i++) {
2177         msg = vat_json_array_add(msg_array);
2178         vat_json_init_object(msg);
2179         vat_json_object_add_string_copy(msg, "vnet_counter_type",
2180                 (u8*)counter_type_to_str(i, 0));
2181         vat_json_object_add_int(msg, "is_combined", 0);
2182         counter_array = vat_json_object_add(msg, "data");
2183         vat_json_init_array(counter_array);
2184         for (j = 0; j < vec_len(vam->simple_interface_counters[i]); j++) {
2185             packets = vam->simple_interface_counters[i][j];
2186             vat_json_array_add_uint(counter_array, packets);
2187         }
2188     }
2189     for (i = 0; i < vec_len(vam->combined_interface_counters); i++) {
2190         msg = vat_json_array_add(msg_array);
2191         vat_json_init_object(msg);
2192         vat_json_object_add_string_copy(msg, "vnet_counter_type",
2193                 (u8*)counter_type_to_str(i, 1));
2194         vat_json_object_add_int(msg, "is_combined", 1);
2195         counter_array = vat_json_object_add(msg, "data");
2196         vat_json_init_array(counter_array);
2197         for (j = 0; j < vec_len(vam->combined_interface_counters[i]); j++) {
2198             c = vam->combined_interface_counters[i][j];
2199             counter = vat_json_array_add(counter_array);
2200             vat_json_init_object(counter);
2201             vat_json_object_add_uint(counter, "packets", c.packets);
2202             vat_json_object_add_uint(counter, "bytes", c.bytes);
2203         }
2204     }
2205
2206     /* ip4 fib counters */
2207     msg_array = vat_json_object_add(&node, "ip4_fib_counters");
2208     vat_json_init_array(msg_array);
2209     for (i = 0; i < vec_len(vam->ip4_fib_counters); i++) {
2210         msg = vat_json_array_add(msg_array);
2211         vat_json_init_object(msg);
2212         vat_json_object_add_uint(msg, "vrf_id", vam->ip4_fib_counters_vrf_id_by_index[i]);
2213         counter_array = vat_json_object_add(msg, "c");
2214         vat_json_init_array(counter_array);
2215         for (j = 0; j < vec_len(vam->ip4_fib_counters[i]); j++) {
2216             counter = vat_json_array_add(counter_array);
2217             vat_json_init_object(counter);
2218             c4 = &vam->ip4_fib_counters[i][j];
2219             vat_json_object_add_ip4(counter, "address", c4->address);
2220             vat_json_object_add_uint(counter, "address_length", c4->address_length);
2221             vat_json_object_add_uint(counter, "packets", c4->packets);
2222             vat_json_object_add_uint(counter, "bytes", c4->bytes);
2223         }
2224     }
2225
2226     /* ip6 fib counters */
2227     msg_array = vat_json_object_add(&node, "ip6_fib_counters");
2228     vat_json_init_array(msg_array);
2229     for (i = 0; i < vec_len(vam->ip6_fib_counters); i++) {
2230         msg = vat_json_array_add(msg_array);
2231         vat_json_init_object(msg);
2232         vat_json_object_add_uint(msg, "vrf_id", vam->ip6_fib_counters_vrf_id_by_index[i]);
2233         counter_array = vat_json_object_add(msg, "c");
2234         vat_json_init_array(counter_array);
2235         for (j = 0; j < vec_len(vam->ip6_fib_counters[i]); j++) {
2236             counter = vat_json_array_add(counter_array);
2237             vat_json_init_object(counter);
2238             c6 = &vam->ip6_fib_counters[i][j];
2239             vat_json_object_add_ip6(counter, "address", c6->address);
2240             vat_json_object_add_uint(counter, "address_length", c6->address_length);
2241             vat_json_object_add_uint(counter, "packets", c6->packets);
2242             vat_json_object_add_uint(counter, "bytes", c6->bytes);
2243         }
2244     }
2245
2246     vat_json_print(vam->ofp, &node);
2247     vat_json_free(&node);
2248
2249     return 0;
2250 }
2251
2252 int exec (vat_main_t * vam)
2253 {
2254     api_main_t * am = &api_main;
2255     vl_api_cli_request_t *mp;
2256     f64 timeout;
2257     void * oldheap;
2258     u8 * cmd = 0;
2259     unformat_input_t * i = vam->input;
2260
2261     if (vec_len(i->buffer) == 0)
2262         return -1;
2263
2264     if (vam->exec_mode == 0 && unformat (i, "mode")) {        
2265         vam->exec_mode = 1;
2266         return 0;
2267     }
2268     if (vam->exec_mode == 1 && 
2269         (unformat (i, "exit") || unformat (i, "quit"))) {
2270         vam->exec_mode = 0;
2271         return 0;
2272     }
2273     
2274
2275     M(CLI_REQUEST, cli_request);
2276
2277     /* 
2278      * Copy cmd into shared memory.
2279      * In order for the CLI command to work, it
2280      * must be a vector ending in \n, not a C-string ending
2281      * in \n\0.
2282      */
2283     pthread_mutex_lock (&am->vlib_rp->mutex);
2284     oldheap = svm_push_data_heap (am->vlib_rp);
2285
2286     vec_validate (cmd, vec_len(vam->input->buffer)-1);
2287     memcpy (cmd, vam->input->buffer, vec_len(vam->input->buffer));
2288
2289     svm_pop_heap (oldheap);
2290     pthread_mutex_unlock (&am->vlib_rp->mutex);
2291
2292     mp->cmd_in_shmem = (u64) cmd;
2293     S;
2294     timeout = vat_time_now (vam) + 10.0;
2295
2296     while (vat_time_now (vam) < timeout) {
2297         if (vam->result_ready == 1) {
2298             u8 * free_me;
2299             fformat (vam->ofp, "%s", vam->shmem_result);
2300             pthread_mutex_lock (&am->vlib_rp->mutex);
2301             oldheap = svm_push_data_heap (am->vlib_rp);
2302             
2303             free_me = (u8 *)vam->shmem_result;
2304             vec_free (free_me);
2305
2306             svm_pop_heap (oldheap);
2307             pthread_mutex_unlock (&am->vlib_rp->mutex);
2308             return 0;
2309         }
2310     }
2311     return -99;
2312 }
2313
2314 static int api_create_loopback (vat_main_t * vam)
2315 {
2316     unformat_input_t * i = vam->input;
2317     vl_api_create_loopback_t *mp;
2318     f64 timeout;
2319     u8 mac_address[6];
2320     u8 mac_set = 0;
2321
2322     memset (mac_address, 0, sizeof (mac_address));
2323
2324     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2325       {
2326         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
2327             mac_set = 1;
2328         else
2329           break;
2330       }
2331
2332     /* Construct the API message */
2333     M(CREATE_LOOPBACK, create_loopback);
2334     if (mac_set)
2335         memcpy (mp->mac_address, mac_address, sizeof (mac_address));
2336
2337     S; W;
2338 }
2339
2340 static int api_delete_loopback (vat_main_t * vam)
2341 {
2342     unformat_input_t * i = vam->input;
2343     vl_api_delete_loopback_t *mp;
2344     f64 timeout;
2345     u32 sw_if_index = ~0;
2346
2347     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2348       {
2349         if (unformat (i, "sw_if_index %d", &sw_if_index))
2350           ;
2351         else
2352           break;
2353       }
2354
2355     if (sw_if_index == ~0)
2356       {
2357         errmsg ("missing sw_if_index\n");
2358         return -99;
2359       }
2360
2361     /* Construct the API message */
2362     M(DELETE_LOOPBACK, delete_loopback);
2363     mp->sw_if_index = ntohl (sw_if_index);
2364
2365     S; W;
2366 }
2367
2368 static int api_want_stats (vat_main_t * vam)
2369 {
2370     unformat_input_t * i = vam->input;
2371     vl_api_want_stats_t * mp;
2372     f64 timeout;
2373     int enable = -1;
2374
2375     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2376       {
2377         if (unformat (i, "enable"))
2378           enable = 1;
2379         else if (unformat (i, "disable"))
2380           enable = 0;
2381         else
2382           break;
2383       }
2384
2385     if (enable == -1)
2386       {
2387         errmsg ("missing enable|disable\n");
2388         return -99;
2389       }
2390
2391     M(WANT_STATS, want_stats);
2392     mp->enable_disable = enable;
2393
2394     S; W;
2395 }
2396
2397 static int api_want_interface_events (vat_main_t * vam)
2398 {
2399     unformat_input_t * i = vam->input;
2400     vl_api_want_interface_events_t * mp;
2401     f64 timeout;
2402     int enable = -1;
2403
2404     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2405       {
2406         if (unformat (i, "enable"))
2407           enable = 1;
2408         else if (unformat (i, "disable"))
2409           enable = 0;
2410         else
2411           break;
2412       }
2413
2414     if (enable == -1)
2415       {
2416         errmsg ("missing enable|disable\n");
2417         return -99;
2418       }
2419
2420     M(WANT_INTERFACE_EVENTS, want_interface_events);
2421     mp->enable_disable = enable;
2422
2423     vam->interface_event_display = enable;
2424
2425     S; W;
2426 }
2427
2428
2429 /* Note: non-static, called once to set up the initial intfc table */
2430 int api_sw_interface_dump (vat_main_t * vam)
2431 {
2432     vl_api_sw_interface_dump_t *mp;
2433     f64 timeout;
2434     hash_pair_t * p;
2435     name_sort_t * nses = 0, * ns;
2436     sw_interface_subif_t * sub = NULL;
2437
2438     /* Toss the old name table */
2439     hash_foreach_pair (p, vam->sw_if_index_by_interface_name, 
2440     ({
2441         vec_add2 (nses, ns, 1);
2442         ns->name = (u8 *)(p->key);
2443         ns->value = (u32) p->value[0];
2444     }));
2445
2446     hash_free (vam->sw_if_index_by_interface_name);
2447
2448     vec_foreach (ns, nses)
2449         vec_free (ns->name);
2450
2451     vec_free (nses);
2452
2453     vec_foreach (sub, vam->sw_if_subif_table) {
2454         vec_free (sub->interface_name);
2455     }
2456     vec_free (vam->sw_if_subif_table);
2457
2458     /* recreate the interface name hash table */
2459     vam->sw_if_index_by_interface_name 
2460         = hash_create_string (0, sizeof(uword));
2461
2462     /* Get list of ethernets */
2463     M(SW_INTERFACE_DUMP, sw_interface_dump);
2464     mp->name_filter_valid = 1;
2465     strncpy ((char *) mp->name_filter, "Ether", sizeof(mp->name_filter-1)); 
2466     S;
2467
2468     /* and local / loopback interfaces */
2469     M(SW_INTERFACE_DUMP, sw_interface_dump);
2470     mp->name_filter_valid = 1;
2471     strncpy ((char *) mp->name_filter, "lo", sizeof(mp->name_filter-1)); 
2472     S;
2473
2474     /* and vxlan tunnel interfaces */
2475     M(SW_INTERFACE_DUMP, sw_interface_dump);
2476     mp->name_filter_valid = 1;
2477     strncpy ((char *) mp->name_filter, "vxlan", sizeof(mp->name_filter-1)); 
2478     S;
2479
2480     /* and l2tpv3 tunnel interfaces */
2481     M(SW_INTERFACE_DUMP, sw_interface_dump);
2482     mp->name_filter_valid = 1;
2483     strncpy ((char *) mp->name_filter, "l2tpv3_tunnel", sizeof(mp->name_filter-1));
2484     S;
2485
2486     /* Use a control ping for synchronization */
2487     {
2488         vl_api_control_ping_t * mp;
2489         M(CONTROL_PING, control_ping);
2490         S;
2491     }
2492     W;
2493 }
2494
2495 static int api_sw_interface_set_flags (vat_main_t * vam)
2496 {
2497     unformat_input_t * i = vam->input;
2498     vl_api_sw_interface_set_flags_t *mp;
2499     f64 timeout;
2500     u32 sw_if_index;
2501     u8 sw_if_index_set = 0;
2502     u8 admin_up = 0, link_up = 0;
2503     
2504     /* Parse args required to build the message */
2505     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2506         if (unformat (i, "admin-up"))
2507             admin_up = 1;
2508         else if (unformat (i, "admin-down"))
2509             admin_up = 0;
2510         else if (unformat (i, "link-up"))
2511             link_up = 1;
2512         else if (unformat (i, "link-down"))
2513             link_up = 0;
2514         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2515             sw_if_index_set = 1;
2516         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2517             sw_if_index_set = 1;
2518         else
2519             break;
2520     }
2521
2522     if (sw_if_index_set == 0) {
2523         errmsg ("missing interface name or sw_if_index\n");
2524         return -99;
2525     }
2526
2527     /* Construct the API message */
2528     M(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags);
2529     mp->sw_if_index = ntohl (sw_if_index);
2530     mp->admin_up_down = admin_up;
2531     mp->link_up_down = link_up;
2532
2533     /* send it... */
2534     S;
2535
2536     /* Wait for a reply, return the good/bad news... */
2537     W;
2538 }
2539
2540 static int api_sw_interface_add_del_address (vat_main_t * vam)
2541 {
2542     unformat_input_t * i = vam->input;
2543     vl_api_sw_interface_add_del_address_t *mp;
2544     f64 timeout;
2545     u32 sw_if_index;
2546     u8 sw_if_index_set = 0;
2547     u8 is_add = 1, del_all = 0;
2548     u32 address_length = 0;
2549     u8 v4_address_set = 0;
2550     u8 v6_address_set = 0;
2551     ip4_address_t v4address;
2552     ip6_address_t v6address;
2553     
2554     /* Parse args required to build the message */
2555     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2556         if (unformat (i, "del-all"))
2557             del_all = 1;
2558         else if (unformat (i, "del"))
2559             is_add = 0;
2560         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2561             sw_if_index_set = 1;
2562         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2563             sw_if_index_set = 1;
2564         else if (unformat (i, "%U/%d", 
2565                            unformat_ip4_address, &v4address, 
2566                            &address_length))
2567             v4_address_set = 1;
2568         else if (unformat (i, "%U/%d", 
2569                            unformat_ip6_address, &v6address, 
2570                            &address_length))
2571             v6_address_set = 1;
2572         else
2573             break;
2574     }
2575
2576     if (sw_if_index_set == 0) {
2577         errmsg ("missing interface name or sw_if_index\n");
2578         return -99;
2579     }
2580     if (v4_address_set && v6_address_set) {
2581         errmsg ("both v4 and v6 addresses set\n");
2582         return -99;
2583     }
2584     if (!v4_address_set && !v6_address_set && !del_all) {
2585         errmsg ("no addresses set\n");
2586         return -99;
2587     }
2588
2589     /* Construct the API message */
2590     M(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address);
2591
2592     mp->sw_if_index = ntohl (sw_if_index);
2593     mp->is_add = is_add;
2594     mp->del_all = del_all;
2595     if (v6_address_set) {
2596         mp->is_ipv6 = 1;
2597         memcpy (mp->address, &v6address, sizeof (v6address));
2598     } else {
2599         memcpy (mp->address, &v4address, sizeof (v4address));
2600     }
2601     mp->address_length = address_length;
2602
2603     /* send it... */
2604     S;
2605
2606     /* Wait for a reply, return good/bad news  */
2607     W;
2608 }
2609
2610 static int api_sw_interface_set_table (vat_main_t * vam)
2611 {
2612     unformat_input_t * i = vam->input;
2613     vl_api_sw_interface_set_table_t *mp;
2614     f64 timeout;
2615     u32 sw_if_index, vrf_id = 0;
2616     u8 sw_if_index_set = 0;
2617     u8 is_ipv6 = 0;
2618     
2619     /* Parse args required to build the message */
2620     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2621         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2622             sw_if_index_set = 1;
2623         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2624             sw_if_index_set = 1;
2625         else if (unformat (i, "vrf %d", &vrf_id))
2626             ;
2627         else if (unformat (i, "ipv6"))
2628             is_ipv6 = 1;
2629         else
2630             break;
2631     }
2632
2633     if (sw_if_index_set == 0) {
2634         errmsg ("missing interface name or sw_if_index\n");
2635         return -99;
2636     }
2637
2638     /* Construct the API message */
2639     M(SW_INTERFACE_SET_TABLE, sw_interface_set_table);
2640
2641     mp->sw_if_index = ntohl (sw_if_index);
2642     mp->is_ipv6 = is_ipv6;
2643     mp->vrf_id = ntohl (vrf_id);
2644
2645     /* send it... */
2646     S;
2647
2648     /* Wait for a reply... */
2649     W;
2650 }
2651
2652 static int api_sw_interface_set_vpath (vat_main_t * vam)
2653 {
2654     unformat_input_t * i = vam->input;
2655     vl_api_sw_interface_set_vpath_t *mp;
2656     f64 timeout;
2657     u32 sw_if_index = 0;
2658     u8 sw_if_index_set = 0;
2659     u8 is_enable = 0;
2660     
2661     /* Parse args required to build the message */
2662     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2663         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2664             sw_if_index_set = 1;
2665         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2666             sw_if_index_set = 1;
2667         else if (unformat (i, "enable"))
2668             is_enable = 1;
2669         else if (unformat (i, "disable"))
2670             is_enable = 0;
2671         else
2672             break;
2673     }
2674
2675     if (sw_if_index_set == 0) {
2676         errmsg ("missing interface name or sw_if_index\n");
2677         return -99;
2678     }
2679
2680     /* Construct the API message */
2681     M(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath);
2682
2683     mp->sw_if_index = ntohl (sw_if_index);
2684     mp->enable = is_enable;
2685
2686     /* send it... */
2687     S;
2688
2689     /* Wait for a reply... */
2690     W;
2691 }
2692
2693 static int api_sw_interface_set_l2_xconnect (vat_main_t * vam)
2694 {
2695     unformat_input_t * i = vam->input;
2696     vl_api_sw_interface_set_l2_xconnect_t *mp;
2697     f64 timeout;
2698     u32 rx_sw_if_index;
2699     u8 rx_sw_if_index_set = 0;
2700     u32 tx_sw_if_index;
2701     u8 tx_sw_if_index_set = 0;
2702     u8 enable = 1;
2703     
2704     /* Parse args required to build the message */
2705     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2706         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
2707             rx_sw_if_index_set = 1;     
2708         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
2709             tx_sw_if_index_set = 1;
2710         else if (unformat (i, "rx")) {
2711             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2712                 if (unformat (i, "%U", unformat_sw_if_index, vam,
2713                               &rx_sw_if_index))
2714                     rx_sw_if_index_set = 1;
2715             } else
2716                 break;
2717         } else if (unformat (i, "tx")) {
2718             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2719                 if (unformat (i, "%U", unformat_sw_if_index, vam,
2720                               &tx_sw_if_index))
2721                     tx_sw_if_index_set = 1;
2722             } else
2723                 break;
2724         } else if (unformat (i, "enable"))
2725             enable = 1;
2726         else if (unformat (i, "disable")) 
2727             enable = 0;
2728         else
2729             break;
2730     }
2731
2732     if (rx_sw_if_index_set == 0) {
2733         errmsg ("missing rx interface name or rx_sw_if_index\n");
2734         return -99;
2735     }
2736
2737     if (enable && (tx_sw_if_index_set == 0)) {
2738         errmsg ("missing tx interface name or tx_sw_if_index\n");
2739         return -99;
2740     }
2741     
2742     M(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect);
2743
2744     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
2745     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
2746     mp->enable = enable;
2747
2748     S; W;
2749     /* NOTREACHED */
2750     return 0;
2751 }
2752
2753 static int api_sw_interface_set_l2_bridge (vat_main_t * vam)
2754 {
2755     unformat_input_t * i = vam->input;
2756     vl_api_sw_interface_set_l2_bridge_t *mp;
2757     f64 timeout;
2758     u32 rx_sw_if_index;
2759     u8 rx_sw_if_index_set = 0;
2760     u32 bd_id;
2761     u8 bd_id_set = 0;
2762     u8 bvi = 0;
2763     u32 shg = 0;
2764     u8 enable = 1;
2765     
2766     /* Parse args required to build the message */
2767     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2768         if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
2769             rx_sw_if_index_set = 1;     
2770         else if (unformat (i, "bd_id %d", &bd_id))
2771             bd_id_set = 1;
2772         else if (unformat (i, "%U", unformat_sw_if_index, vam,
2773                            &rx_sw_if_index))
2774             rx_sw_if_index_set = 1;
2775         else if (unformat (i, "shg %d", &shg)) 
2776             ;
2777         else if (unformat (i, "bvi"))
2778             bvi = 1;
2779         else if (unformat (i, "enable"))
2780             enable = 1;
2781         else if (unformat (i, "disable")) 
2782             enable = 0;
2783         else
2784             break;
2785     }
2786
2787     if (rx_sw_if_index_set == 0) {
2788         errmsg ("missing rx interface name or sw_if_index\n");
2789         return -99;
2790     }
2791
2792     if (enable && (bd_id_set == 0)) {
2793         errmsg ("missing bridge domain\n");
2794         return -99;
2795     }
2796     
2797     M(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge);
2798
2799     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
2800     mp->bd_id = ntohl(bd_id);
2801     mp->shg = (u8)shg;
2802     mp->bvi = bvi;
2803     mp->enable = enable;
2804
2805     S; W;
2806     /* NOTREACHED */
2807     return 0;
2808 }
2809
2810 static int api_bridge_domain_dump (vat_main_t * vam)
2811 {
2812     unformat_input_t * i = vam->input;
2813     vl_api_bridge_domain_dump_t *mp;
2814     f64 timeout;
2815     u32 bd_id = ~0;
2816
2817     /* Parse args required to build the message */
2818     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2819         if (unformat (i, "bd_id %d", &bd_id))
2820             ;
2821         else
2822             break;
2823     }
2824
2825     M(BRIDGE_DOMAIN_DUMP, bridge_domain_dump);
2826     mp->bd_id = ntohl(bd_id);
2827     S;
2828
2829     /* Use a control ping for synchronization */
2830     {
2831         vl_api_control_ping_t * mp;
2832         M(CONTROL_PING, control_ping);
2833         S;
2834     }
2835
2836     W;
2837     /* NOTREACHED */
2838     return 0;
2839 }
2840
2841 static int api_bridge_domain_add_del (vat_main_t * vam)
2842 {
2843     unformat_input_t * i = vam->input;
2844     vl_api_bridge_domain_add_del_t *mp;
2845     f64 timeout;
2846     u32 bd_id = ~0;
2847     u8 is_add = 1;
2848     u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
2849
2850     /* Parse args required to build the message */
2851     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2852         if (unformat (i, "bd_id %d", &bd_id))
2853             ;
2854         else if (unformat (i, "flood %d", &flood))
2855              ;
2856         else if (unformat (i, "uu-flood %d", &uu_flood))
2857              ;
2858         else if (unformat (i, "forward %d", &forward))
2859              ;
2860         else if (unformat (i, "learn %d", &learn))
2861              ;
2862         else if (unformat (i, "arp-term %d", &arp_term))
2863              ;
2864         else if (unformat (i, "del")) {
2865              is_add = 0;
2866              flood = uu_flood = forward = learn = 0;
2867         }
2868         else
2869             break;
2870     }
2871
2872     if (bd_id == ~0) {
2873         errmsg ("missing bridge domain\n");
2874         return -99;
2875     }
2876
2877     M(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del);
2878
2879     mp->bd_id = ntohl(bd_id);
2880     mp->flood = flood;
2881     mp->uu_flood = uu_flood;
2882     mp->forward = forward;
2883     mp->learn = learn;
2884     mp->arp_term = arp_term;
2885     mp->is_add = is_add;
2886
2887     S; W;
2888     /* NOTREACHED */
2889     return 0;
2890 }
2891
2892 static int api_l2fib_add_del (vat_main_t * vam)
2893 {
2894     unformat_input_t * i = vam->input;
2895     vl_api_l2fib_add_del_t *mp;
2896     f64 timeout;
2897     u64 mac = 0;
2898     u8 mac_set = 0;
2899     u32 bd_id;
2900     u8 bd_id_set = 0;
2901     u32 sw_if_index;
2902     u8 sw_if_index_set = 0;
2903     u8 is_add = 1;
2904     u8 static_mac = 0;
2905     u8 filter_mac = 0;
2906
2907     /* Parse args required to build the message */
2908     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2909         if (unformat (i, "mac %U", unformat_ethernet_address, &mac))
2910             mac_set = 1;
2911         else if (unformat (i, "bd_id %d", &bd_id))
2912             bd_id_set = 1;
2913         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2914             sw_if_index_set = 1;        
2915         else if (unformat (i, "sw_if")) {
2916             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2917                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2918                     sw_if_index_set = 1;
2919             } else
2920                 break;
2921         } else if (unformat (i, "static"))
2922                 static_mac = 1;
2923         else if (unformat (i, "filter")) {
2924                 filter_mac = 1;
2925                 static_mac = 1;
2926         } else if (unformat (i, "del"))
2927                 is_add = 0;
2928         else
2929             break;
2930     }
2931
2932     if (mac_set == 0) {
2933         errmsg ("missing mac address\n");
2934         return -99;
2935     }
2936
2937     if (bd_id_set == 0) {
2938         errmsg ("missing bridge domain\n");
2939         return -99;
2940     }
2941
2942     if (is_add && (sw_if_index_set == 0)) {
2943         errmsg ("missing interface name or sw_if_index\n");
2944         return -99;
2945     }
2946
2947     M(L2FIB_ADD_DEL, l2fib_add_del);
2948
2949     mp->mac = mac;
2950     mp->bd_id = ntohl(bd_id);
2951     mp->is_add = is_add;
2952
2953     if (is_add) {
2954         mp->sw_if_index = ntohl(sw_if_index);
2955         mp->static_mac = static_mac;
2956         mp->filter_mac = filter_mac;
2957     }
2958     
2959     S; W;
2960     /* NOTREACHED */
2961     return 0;
2962 }
2963
2964 static int api_l2_flags (vat_main_t * vam)
2965 {
2966     unformat_input_t * i = vam->input;
2967     vl_api_l2_flags_t *mp;
2968     f64 timeout;
2969     u32 sw_if_index;
2970     u32 feature_bitmap = 0;
2971     u8 sw_if_index_set = 0;
2972
2973     /* Parse args required to build the message */
2974     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2975         if (unformat (i, "sw_if_index %d", &sw_if_index))
2976             sw_if_index_set = 1;        
2977         else if (unformat (i, "sw_if")) {
2978             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2979                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2980                     sw_if_index_set = 1;
2981             } else
2982                 break;
2983         } else if (unformat (i, "learn"))
2984             feature_bitmap |= L2INPUT_FEAT_LEARN;
2985         else if (unformat (i, "forward"))
2986             feature_bitmap |= L2INPUT_FEAT_FWD;
2987         else if (unformat (i, "flood"))
2988             feature_bitmap |= L2INPUT_FEAT_FLOOD;
2989         else if (unformat (i, "uu-flood"))
2990             feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
2991         else
2992             break;
2993     }
2994
2995     if (sw_if_index_set == 0) {
2996         errmsg ("missing interface name or sw_if_index\n");
2997         return -99;
2998     }
2999
3000     M(L2_FLAGS, l2_flags);
3001
3002     mp->sw_if_index = ntohl(sw_if_index);
3003     mp->feature_bitmap = ntohl(feature_bitmap);
3004
3005     S; W;
3006     /* NOTREACHED */
3007     return 0;
3008 }
3009
3010 static int api_bridge_flags (vat_main_t * vam)
3011 {
3012     unformat_input_t * i = vam->input;
3013     vl_api_bridge_flags_t *mp;
3014     f64 timeout;
3015     u32 bd_id;
3016     u8 bd_id_set = 0;
3017     u8 is_set = 1;
3018     u32 flags = 0;
3019
3020     /* Parse args required to build the message */
3021     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3022         if (unformat (i, "bd_id %d", &bd_id))
3023             bd_id_set = 1;
3024         else if (unformat (i, "learn"))
3025             flags |= L2_LEARN;
3026         else if (unformat (i, "forward"))
3027             flags |= L2_FWD;
3028         else if (unformat (i, "flood"))
3029             flags |= L2_FLOOD;
3030         else if (unformat (i, "uu-flood"))
3031             flags |= L2_UU_FLOOD;
3032         else if (unformat (i, "arp-term"))
3033             flags |= L2_ARP_TERM;
3034         else if (unformat (i, "off"))
3035             is_set = 0;
3036         else if (unformat (i, "disable"))
3037             is_set = 0;
3038         else
3039             break;
3040     }
3041
3042     if (bd_id_set == 0) {
3043         errmsg ("missing bridge domain\n");
3044         return -99;
3045     }
3046
3047     M(BRIDGE_FLAGS, bridge_flags);
3048
3049     mp->bd_id = ntohl(bd_id);
3050     mp->feature_bitmap = ntohl(flags);
3051     mp->is_set = is_set;
3052
3053     S; W;
3054     /* NOTREACHED */
3055     return 0;
3056 }
3057
3058 static int api_bd_ip_mac_add_del (vat_main_t * vam)
3059 {
3060     unformat_input_t * i = vam->input;
3061     vl_api_bd_ip_mac_add_del_t *mp;
3062     f64 timeout;
3063     u32 bd_id;
3064     u8 is_ipv6 = 0;
3065     u8 is_add = 1;
3066     u8 bd_id_set = 0;
3067     u8 ip_set = 0;
3068     u8 mac_set = 0;
3069     ip4_address_t v4addr;
3070     ip6_address_t v6addr;
3071     u8 macaddr[6];
3072     
3073
3074     /* Parse args required to build the message */
3075     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3076         if (unformat (i, "bd_id %d", &bd_id)) {
3077             bd_id_set++;
3078         } else if (unformat (i, "%U", unformat_ip4_address, &v4addr)) {
3079             ip_set++;
3080         } else if (unformat (i, "%U", unformat_ip6_address, &v6addr)) {
3081             ip_set++;
3082             is_ipv6++;
3083         } else if (unformat (i, "%U", unformat_ethernet_address, macaddr)) {
3084             mac_set++;
3085         } else if (unformat (i, "del"))
3086             is_add = 0;
3087         else
3088             break;
3089     }
3090
3091     if (bd_id_set == 0) {
3092         errmsg ("missing bridge domain\n");
3093         return -99;
3094     } else if (ip_set == 0) {
3095         errmsg ("missing IP address\n");
3096         return -99;
3097     } else if (mac_set == 0) {
3098         errmsg ("missing MAC address\n");
3099         return -99;
3100     }
3101
3102     M(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del);
3103
3104     mp->bd_id = ntohl(bd_id);
3105     mp->is_ipv6 = is_ipv6;
3106     mp->is_add = is_add;
3107     if (is_ipv6)
3108          memcpy (mp->ip_address, &v6addr, sizeof (v6addr));
3109     else memcpy (mp->ip_address, &v4addr, sizeof (v4addr));
3110     memcpy (mp->mac_address, macaddr, 6);
3111     S; W;
3112     /* NOTREACHED */
3113     return 0;
3114 }
3115
3116 static int api_tap_connect (vat_main_t * vam)
3117 {
3118     unformat_input_t * i = vam->input;
3119     vl_api_tap_connect_t *mp;
3120     f64 timeout;
3121     u8 mac_address[6];
3122     u8 random_mac = 1;
3123     u8 name_set = 0;
3124     u8 * tap_name;
3125
3126     memset (mac_address, 0, sizeof (mac_address));
3127     
3128     /* Parse args required to build the message */
3129     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3130         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
3131             random_mac = 0;
3132         }
3133         else if (unformat (i, "random-mac"))
3134             random_mac = 1;
3135         else if (unformat (i, "tapname %s", &tap_name))
3136             name_set = 1;
3137         else
3138             break;
3139     }
3140
3141     if (name_set == 0) {
3142         errmsg ("missing tap name\n");
3143         return -99;
3144     }
3145     if (vec_len (tap_name) > 63) {
3146         errmsg ("tap name too long\n");
3147     }
3148     vec_add1 (tap_name, 0);
3149         
3150     /* Construct the API message */
3151     M(TAP_CONNECT, tap_connect);
3152
3153     mp->use_random_mac = random_mac;
3154     memcpy (mp->mac_address, mac_address, 6);
3155     memcpy (mp->tap_name, tap_name, vec_len (tap_name));
3156     vec_free (tap_name);
3157
3158     /* send it... */
3159     S;
3160
3161     /* Wait for a reply... */
3162     W;
3163 }
3164
3165 static int api_tap_modify (vat_main_t * vam)
3166 {
3167     unformat_input_t * i = vam->input;
3168     vl_api_tap_modify_t *mp;
3169     f64 timeout;
3170     u8 mac_address[6];
3171     u8 random_mac = 1;
3172     u8 name_set = 0;
3173     u8 * tap_name;
3174     u32 sw_if_index = ~0;
3175     u8 sw_if_index_set = 0;
3176
3177     memset (mac_address, 0, sizeof (mac_address));
3178     
3179     /* Parse args required to build the message */
3180     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3181         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3182             sw_if_index_set = 1;
3183         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3184             sw_if_index_set = 1;
3185         else if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
3186             random_mac = 0;
3187         }
3188         else if (unformat (i, "random-mac"))
3189             random_mac = 1;
3190         else if (unformat (i, "tapname %s", &tap_name))
3191             name_set = 1;
3192         else
3193             break;
3194     }
3195
3196     if (sw_if_index_set == 0) {
3197         errmsg ("missing vpp interface name");
3198         return -99;
3199     }
3200     if (name_set == 0) {
3201         errmsg ("missing tap name\n");
3202         return -99;
3203     }
3204     if (vec_len (tap_name) > 63) {
3205         errmsg ("tap name too long\n");
3206     }
3207     vec_add1 (tap_name, 0);
3208         
3209     /* Construct the API message */
3210     M(TAP_MODIFY, tap_modify);
3211
3212     mp->use_random_mac = random_mac;
3213     mp->sw_if_index = ntohl(sw_if_index);
3214     memcpy (mp->mac_address, mac_address, 6);
3215     memcpy (mp->tap_name, tap_name, vec_len (tap_name));
3216     vec_free (tap_name);
3217
3218     /* send it... */
3219     S;
3220
3221     /* Wait for a reply... */
3222     W;
3223 }
3224
3225 static int api_tap_delete (vat_main_t * vam)
3226 {
3227     unformat_input_t * i = vam->input;
3228     vl_api_tap_delete_t *mp;
3229     f64 timeout;
3230     u32 sw_if_index = ~0;
3231     u8 sw_if_index_set = 0;
3232
3233     /* Parse args required to build the message */
3234     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3235         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3236             sw_if_index_set = 1;
3237         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3238             sw_if_index_set = 1;
3239         else
3240             break;
3241     }
3242
3243     if (sw_if_index_set == 0) {
3244         errmsg ("missing vpp interface name");
3245         return -99;
3246     }
3247         
3248     /* Construct the API message */
3249     M(TAP_DELETE, tap_delete);
3250
3251     mp->sw_if_index = ntohl(sw_if_index);
3252
3253     /* send it... */
3254     S;
3255
3256     /* Wait for a reply... */
3257     W;
3258 }
3259
3260 static int api_ip_add_del_route (vat_main_t * vam)
3261 {
3262     unformat_input_t * i = vam->input;
3263     vl_api_ip_add_del_route_t *mp;
3264     f64 timeout;
3265     u32 sw_if_index = 0, vrf_id = 0;
3266     u8 sw_if_index_set = 0;
3267     u8 is_ipv6 = 0;
3268     u8 is_local = 0, is_drop = 0;
3269     u8 create_vrf_if_needed = 0;
3270     u8 is_add = 1;
3271     u8 next_hop_weight = 1;
3272     u8 not_last = 0;
3273     u8 is_multipath = 0;
3274     u8 address_set = 0;
3275     u8 address_length_set = 0;
3276     u32 lookup_in_vrf = 0;
3277     u32 resolve_attempts = 0;
3278     u32 dst_address_length = 0;
3279     u8 next_hop_set = 0;
3280     ip4_address_t v4_dst_address, v4_next_hop_address;
3281     ip6_address_t v6_dst_address, v6_next_hop_address;
3282     int count = 1;
3283     int j;
3284     f64 before = 0;
3285     u32 random_add_del = 0;
3286     u32 * random_vector = 0;
3287     uword * random_hash;
3288     u32 random_seed = 0xdeaddabe;
3289     u32 classify_table_index = ~0;
3290     u8 is_classify = 0;
3291     
3292     /* Parse args required to build the message */
3293     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3294         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3295             sw_if_index_set = 1;
3296         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3297             sw_if_index_set = 1;
3298         else if (unformat (i, "%U", unformat_ip4_address,
3299                            &v4_dst_address)) {
3300             address_set = 1;
3301             is_ipv6 = 0;
3302         }
3303         else if (unformat (i, "%U", unformat_ip6_address, &v6_dst_address)) {
3304             address_set = 1;
3305             is_ipv6 = 1;
3306         }
3307         else if (unformat (i, "/%d", &dst_address_length)) {
3308             address_length_set = 1;
3309         }
3310         
3311         else if (is_ipv6 == 0 && unformat (i, "via %U", unformat_ip4_address, 
3312                                            &v4_next_hop_address)) {
3313             next_hop_set = 1;
3314         }
3315         else if (is_ipv6 == 1 && unformat (i, "via %U", unformat_ip6_address, 
3316                                            &v6_next_hop_address)) {
3317             next_hop_set = 1;
3318         }
3319         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
3320             ;
3321         else if (unformat (i, "weight %d", &next_hop_weight))
3322             ;
3323         else if (unformat (i, "drop")) {
3324             is_drop = 1;
3325         } else if (unformat (i, "local")) {
3326             is_local = 1;
3327         } else if (unformat (i, "classify %d", &classify_table_index)) {
3328             is_classify = 1;
3329         } else if (unformat (i, "del"))
3330             is_add = 0;
3331         else if (unformat (i, "add"))
3332             is_add = 1;
3333         else if (unformat (i, "not-last"))
3334             not_last = 1;
3335         else if (unformat (i, "multipath"))
3336             is_multipath = 1;
3337         else if (unformat (i, "vrf %d", &vrf_id))
3338             ;
3339         else if (unformat (i, "create-vrf"))
3340             create_vrf_if_needed = 1;
3341         else if (unformat (i, "count %d", &count))
3342             ;
3343         else if (unformat (i, "lookup-in-vrf %d", &lookup_in_vrf))
3344             ;
3345         else if (unformat (i, "random"))
3346             random_add_del = 1;
3347         else if (unformat (i, "seed %d", &random_seed))
3348             ;
3349         else {
3350             clib_warning ("parse error '%U'", format_unformat_error, i);
3351             return -99;
3352         }
3353     }
3354
3355     if (resolve_attempts > 0 && sw_if_index_set == 0) {
3356         errmsg ("ARP resolution needs explicit interface or sw_if_index\n");
3357         return -99;
3358     }
3359     
3360     if (!next_hop_set && !is_drop && !is_local && !is_classify) {
3361         errmsg ("next hop / local / drop / classify not set\n");
3362         return -99;
3363     }
3364
3365     if (address_set == 0) {
3366         errmsg ("missing addresses\n");
3367         return -99;
3368     }
3369
3370     if (address_length_set == 0) {
3371         errmsg ("missing address length\n");
3372         return -99;
3373     }
3374     
3375     /* Generate a pile of unique, random routes */
3376     if (random_add_del) {
3377         u32 this_random_address;
3378         random_hash = hash_create (count, sizeof(uword));
3379
3380         hash_set (random_hash, v4_next_hop_address.as_u32, 1);
3381         for (j = 0; j <= count; j++) {
3382             do {
3383                 this_random_address = random_u32 (&random_seed);
3384                 this_random_address = 
3385                     clib_host_to_net_u32 (this_random_address);
3386             } while (hash_get (random_hash, this_random_address));
3387             vec_add1 (random_vector, this_random_address);
3388             hash_set (random_hash, this_random_address, 1);
3389         }
3390         hash_free (random_hash);
3391         v4_dst_address.as_u32 = random_vector[0];
3392     }
3393
3394     if (count > 1) {
3395         /* Turn on async mode */
3396         vam->async_mode = 1;
3397         vam->async_errors = 0;
3398         before = vat_time_now(vam);
3399     }
3400
3401     for (j = 0; j < count; j++) {
3402         /* Construct the API message */
3403         M(IP_ADD_DEL_ROUTE, ip_add_del_route);
3404     
3405         mp->next_hop_sw_if_index = ntohl (sw_if_index);
3406         mp->vrf_id = ntohl (vrf_id);
3407         if (resolve_attempts > 0) {
3408             mp->resolve_attempts = ntohl (resolve_attempts);
3409             mp->resolve_if_needed = 1;
3410         }
3411         mp->create_vrf_if_needed = create_vrf_if_needed;
3412     
3413         mp->is_add = is_add;
3414         mp->is_drop = is_drop;
3415         mp->is_ipv6 = is_ipv6;
3416         mp->is_local = is_local;
3417         mp->is_classify = is_classify;
3418         mp->is_multipath = is_multipath;
3419         mp->not_last = not_last;
3420         mp->next_hop_weight = next_hop_weight;
3421         mp->dst_address_length = dst_address_length;
3422         mp->lookup_in_vrf = ntohl(lookup_in_vrf);
3423         mp->classify_table_index = ntohl(classify_table_index);
3424
3425         if (is_ipv6){
3426             memcpy (mp->dst_address, &v6_dst_address, sizeof (v6_dst_address));
3427             if (next_hop_set)
3428                 memcpy (mp->next_hop_address, &v6_next_hop_address, 
3429                         sizeof (v6_next_hop_address));
3430             increment_v6_address (&v6_dst_address);
3431         } else {
3432             memcpy (mp->dst_address, &v4_dst_address, sizeof (v4_dst_address));
3433             if (next_hop_set)
3434                 memcpy (mp->next_hop_address, &v4_next_hop_address, 
3435                         sizeof (v4_next_hop_address));
3436             if (random_add_del)
3437                 v4_dst_address.as_u32 = random_vector[j+1];
3438             else
3439                 increment_v4_address (&v4_dst_address);
3440         }
3441         /* send it... */
3442         S;
3443     }
3444
3445     /* When testing multiple add/del ops, use a control-ping to sync */
3446     if (count > 1) {
3447         vl_api_control_ping_t * mp;
3448         f64 after;
3449
3450         /* Shut off async mode */
3451         vam->async_mode = 0;
3452
3453         M(CONTROL_PING, control_ping);
3454         S;
3455
3456         timeout = vat_time_now(vam) + 1.0;
3457         while (vat_time_now (vam) < timeout)
3458             if (vam->result_ready == 1)
3459                 goto out;
3460         vam->retval = -99;
3461
3462     out:
3463         if (vam->retval == -99)
3464             errmsg ("timeout\n");
3465
3466         if (vam->async_errors > 0) {
3467             errmsg ("%d asynchronous errors\n", vam->async_errors);
3468             vam->retval = -98;
3469         }
3470         vam->async_errors = 0;
3471         after = vat_time_now(vam);
3472
3473         fformat(vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
3474                 count, after - before, count / (after - before));
3475     } else {
3476         /* Wait for a reply... */
3477         W;
3478     }
3479
3480     /* Return the good/bad news */
3481     return (vam->retval);
3482 }
3483
3484 static int api_proxy_arp_add_del (vat_main_t * vam)
3485 {
3486     unformat_input_t * i = vam->input;
3487     vl_api_proxy_arp_add_del_t *mp;
3488     f64 timeout;
3489     u32 vrf_id = 0;
3490     u8 is_add = 1;
3491     ip4_address_t lo, hi;
3492     u8 range_set = 0;
3493
3494     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3495         if (unformat (i, "vrf %d", &vrf_id))
3496             ;
3497         else if (unformat (i, "%U - %U", unformat_ip4_address, &lo, 
3498                            unformat_ip4_address, &hi))
3499             range_set = 1;
3500         else if (unformat (i, "del"))
3501             is_add = 0;
3502         else {
3503             clib_warning ("parse error '%U'", format_unformat_error, i);
3504             return -99;
3505         }
3506     }
3507     
3508     if (range_set == 0) {
3509         errmsg ("address range not set\n");
3510         return -99;
3511     }
3512
3513     M(PROXY_ARP_ADD_DEL, proxy_arp_add_del);
3514
3515     mp->vrf_id = ntohl(vrf_id);
3516     mp->is_add = is_add;
3517     memcpy(mp->low_address, &lo, sizeof (mp->low_address));
3518     memcpy(mp->hi_address, &hi, sizeof (mp->hi_address));
3519
3520     S; W;
3521     /* NOTREACHED */
3522     return 0;
3523 }
3524
3525 static int api_proxy_arp_intfc_enable_disable (vat_main_t * vam)
3526 {
3527     unformat_input_t * i = vam->input;
3528     vl_api_proxy_arp_intfc_enable_disable_t *mp;
3529     f64 timeout;
3530     u32 sw_if_index;
3531     u8 enable = 1;
3532     u8 sw_if_index_set = 0;
3533
3534     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3535         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3536             sw_if_index_set = 1;
3537         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3538             sw_if_index_set = 1;
3539         else if (unformat (i, "enable"))
3540             enable = 1;
3541         else if (unformat (i, "disable"))
3542             enable = 0;
3543         else {
3544             clib_warning ("parse error '%U'", format_unformat_error, i);
3545             return -99;
3546         }
3547     }
3548     
3549     if (sw_if_index_set == 0) {
3550         errmsg ("missing interface name or sw_if_index\n");
3551         return -99;
3552     }
3553
3554     M(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable);
3555
3556     mp->sw_if_index = ntohl(sw_if_index);
3557     mp->enable_disable = enable;
3558
3559     S; W;
3560     /* NOTREACHED */
3561     return 0;
3562 }
3563
3564 static int api_mpls_add_del_decap (vat_main_t * vam)
3565 {
3566     unformat_input_t * i = vam->input;
3567     vl_api_mpls_add_del_decap_t *mp;
3568     f64 timeout;
3569     u32 rx_vrf_id = 0;
3570     u32 tx_vrf_id = 0;
3571     u32 label = 0;
3572     u8 is_add = 1;
3573     u8 s_bit = 1;
3574     u32 next_index = 1;
3575
3576     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3577         if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
3578             ;
3579         else if (unformat (i, "tx_vrf_id %d", &tx_vrf_id))
3580             ;
3581         else if (unformat (i, "label %d", &label))
3582             ;
3583         else if (unformat (i, "next-index %d", &next_index))
3584             ;
3585         else if (unformat (i, "del"))
3586             is_add = 0;
3587         else if (unformat (i, "s-bit-clear"))
3588             s_bit = 0;
3589         else {
3590             clib_warning ("parse error '%U'", format_unformat_error, i);
3591             return -99;
3592         }
3593     }
3594     
3595     M(MPLS_ADD_DEL_DECAP, mpls_add_del_decap);
3596
3597     mp->rx_vrf_id = ntohl(rx_vrf_id);
3598     mp->tx_vrf_id = ntohl(tx_vrf_id);
3599     mp->label = ntohl(label);
3600     mp->next_index = ntohl(next_index);
3601     mp->s_bit = s_bit;
3602     mp->is_add = is_add;
3603
3604     S; W;
3605     /* NOTREACHED */
3606     return 0;
3607 }
3608
3609 static int api_mpls_add_del_encap (vat_main_t * vam)
3610 {
3611     unformat_input_t * i = vam->input;
3612     vl_api_mpls_add_del_encap_t *mp;
3613     f64 timeout;
3614     u32 vrf_id = 0;
3615     u32 *labels = 0;
3616     u32 label;
3617     ip4_address_t dst_address;
3618     u8 is_add = 1;
3619
3620     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3621         if (unformat (i, "vrf %d", &vrf_id))
3622             ;
3623         else if (unformat (i, "label %d", &label))
3624             vec_add1 (labels, ntohl(label));
3625         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
3626             ;
3627         else if (unformat (i, "del"))
3628             is_add = 0;
3629         else {
3630             clib_warning ("parse error '%U'", format_unformat_error, i);
3631             return -99;
3632         }
3633     }
3634
3635     if (vec_len (labels) == 0) {
3636         errmsg ("missing encap label stack\n");
3637         return -99;
3638     }
3639     
3640     M2(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap, 
3641        sizeof (u32) * vec_len (labels));
3642
3643     mp->vrf_id = ntohl(vrf_id);
3644     memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
3645     mp->is_add = is_add;
3646     mp->nlabels = vec_len (labels);
3647     memcpy(mp->labels, labels, sizeof(u32)*mp->nlabels);
3648
3649     vec_free(labels);
3650
3651     S; W;
3652     /* NOTREACHED */
3653     return 0;
3654 }
3655
3656 static int api_mpls_gre_add_del_tunnel (vat_main_t * vam)
3657 {
3658     unformat_input_t * i = vam->input;
3659     vl_api_mpls_gre_add_del_tunnel_t *mp;
3660     f64 timeout;
3661     u32 inner_vrf_id = 0;
3662     u32 outer_vrf_id = 0;
3663     ip4_address_t src_address;
3664     ip4_address_t dst_address;
3665     ip4_address_t intfc_address;
3666     u32 tmp;
3667     u8 intfc_address_length = 0;
3668     u8 is_add = 1;
3669     u8 l2_only = 0;
3670     
3671     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3672         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
3673             ;
3674         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
3675             ;
3676         else if (unformat (i, "src %U", unformat_ip4_address, &src_address))
3677             ;
3678         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
3679             ;
3680         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
3681                            &intfc_address, &tmp))
3682             intfc_address_length = tmp;
3683         else if (unformat (i, "l2-only"))
3684             l2_only = 1;
3685         else if (unformat (i, "del"))
3686             is_add = 0;
3687         else {
3688             clib_warning ("parse error '%U'", format_unformat_error, i);
3689             return -99;
3690         }
3691     }
3692     
3693     M(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel);
3694
3695     mp->inner_vrf_id = ntohl(inner_vrf_id);
3696     mp->outer_vrf_id = ntohl(outer_vrf_id);
3697     memcpy(mp->src_address, &src_address, sizeof (src_address));
3698     memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
3699     memcpy(mp->intfc_address, &intfc_address, sizeof (intfc_address));
3700     mp->intfc_address_length = intfc_address_length;
3701     mp->l2_only = l2_only;
3702     mp->is_add = is_add;
3703
3704     S; W;
3705     /* NOTREACHED */
3706     return 0;
3707 }
3708
3709 static int api_mpls_ethernet_add_del_tunnel (vat_main_t * vam)
3710 {
3711     unformat_input_t * i = vam->input;
3712     vl_api_mpls_ethernet_add_del_tunnel_t *mp;
3713     f64 timeout;
3714     u32 inner_vrf_id = 0;
3715     ip4_address_t intfc_address;
3716     u8 dst_mac_address[6];
3717     int dst_set = 1;
3718     u32 tmp;
3719     u8 intfc_address_length = 0;
3720     u8 is_add = 1;
3721     u8 l2_only = 0;
3722     u32 tx_sw_if_index;
3723     int tx_sw_if_index_set = 0;
3724     
3725     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3726         if (unformat (i, "vrf %d", &inner_vrf_id))
3727             ;
3728         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
3729                            &intfc_address, &tmp))
3730             intfc_address_length = tmp;
3731         else if (unformat (i, "%U", 
3732                            unformat_sw_if_index, vam, &tx_sw_if_index))
3733             tx_sw_if_index_set = 1;
3734         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
3735             tx_sw_if_index_set = 1;
3736         else if (unformat (i, "dst %U", unformat_ethernet_address, 
3737                            dst_mac_address))
3738             dst_set = 1;
3739         else if (unformat (i, "l2-only"))
3740             l2_only = 1;
3741         else if (unformat (i, "del"))
3742             is_add = 0;
3743         else {
3744             clib_warning ("parse error '%U'", format_unformat_error, i);
3745             return -99;
3746         }
3747     }
3748
3749     if (!dst_set) {
3750         errmsg ("dst (mac address) not set\n");
3751         return -99;
3752     }
3753     if (!tx_sw_if_index_set) {
3754         errmsg ("tx-intfc not set\n");
3755         return -99;
3756     }
3757     
3758     M(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel);
3759
3760     mp->vrf_id = ntohl(inner_vrf_id);
3761     memcpy (mp->adj_address, &intfc_address, sizeof (intfc_address));
3762     mp->adj_address_length = intfc_address_length;
3763     memcpy (mp->dst_mac_address, dst_mac_address, sizeof (dst_mac_address));
3764     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
3765     mp->l2_only = l2_only;
3766     mp->is_add = is_add;
3767
3768     S; W;
3769     /* NOTREACHED */
3770     return 0;
3771 }
3772
3773 static int api_mpls_ethernet_add_del_tunnel_2 (vat_main_t * vam)
3774 {
3775     unformat_input_t * i = vam->input;
3776     vl_api_mpls_ethernet_add_del_tunnel_2_t *mp;
3777     f64 timeout;
3778     u32 inner_vrf_id = 0;
3779     u32 outer_vrf_id = 0;
3780     ip4_address_t adj_address;
3781     int adj_address_set = 0;
3782     ip4_address_t next_hop_address;
3783     int next_hop_address_set = 0;
3784     u32 tmp;
3785     u8 adj_address_length = 0;
3786     u8 l2_only = 0;
3787     u8 is_add = 1;
3788     u32 resolve_attempts = 5;
3789     u8 resolve_if_needed = 1;
3790     
3791     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3792         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
3793             ;
3794         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
3795             ;
3796         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
3797                            &adj_address, &tmp)) {
3798             adj_address_length = tmp;
3799             adj_address_set = 1;
3800         }
3801         else if (unformat (i, "next-hop %U", unformat_ip4_address,
3802                            &next_hop_address))
3803             next_hop_address_set = 1;
3804         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
3805             ;
3806         else if (unformat (i, "resolve-if-needed %d", &tmp))
3807             resolve_if_needed = tmp;
3808         else if (unformat (i, "l2-only"))
3809             l2_only = 1;
3810         else if (unformat (i, "del"))
3811             is_add = 0;
3812         else {
3813             clib_warning ("parse error '%U'", format_unformat_error, i);
3814             return -99;
3815         }
3816     }
3817     
3818     if (!adj_address_set) {
3819         errmsg ("adjacency address/mask not set\n");
3820         return -99;
3821     }
3822     if (!next_hop_address_set) {
3823         errmsg ("ip4 next hop address (in outer fib) not set\n");
3824         return -99;
3825     }
3826     
3827     M(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2);
3828     
3829     mp->inner_vrf_id = ntohl(inner_vrf_id);
3830     mp->outer_vrf_id = ntohl(outer_vrf_id);
3831     mp->resolve_attempts = ntohl(resolve_attempts);
3832     mp->resolve_if_needed = resolve_if_needed;
3833     mp->is_add = is_add;
3834     mp->l2_only = l2_only;
3835     memcpy (mp->adj_address, &adj_address, sizeof (adj_address));
3836     mp->adj_address_length = adj_address_length;
3837     memcpy (mp->next_hop_ip4_address_in_outer_vrf, &next_hop_address, 
3838             sizeof (next_hop_address));
3839
3840     S; W;
3841     /* NOTREACHED */
3842     return 0;
3843 }
3844
3845 static int api_sw_interface_set_unnumbered (vat_main_t * vam)
3846 {
3847     unformat_input_t * i = vam->input;
3848     vl_api_sw_interface_set_unnumbered_t *mp;
3849     f64 timeout;
3850     u32 sw_if_index;
3851     u32 unnum_sw_index;
3852     u8  is_add = 1;
3853     u8 sw_if_index_set = 0;
3854
3855     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3856         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3857             sw_if_index_set = 1;
3858         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3859             sw_if_index_set = 1;
3860         else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
3861             ;
3862         else if (unformat (i, "del"))
3863             is_add = 0;
3864         else {
3865             clib_warning ("parse error '%U'", format_unformat_error, i);
3866             return -99;
3867         }
3868     }
3869     
3870     if (sw_if_index_set == 0) {
3871         errmsg ("missing interface name or sw_if_index\n");
3872         return -99;
3873     }
3874
3875     M(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered);
3876
3877     mp->sw_if_index = ntohl(sw_if_index);
3878     mp->unnumbered_sw_if_index = ntohl(unnum_sw_index);
3879     mp->is_add = is_add;
3880
3881     S; W;
3882     /* NOTREACHED */
3883     return 0;
3884 }
3885
3886 static int api_ip_neighbor_add_del (vat_main_t * vam)
3887 {
3888     unformat_input_t * i = vam->input;
3889     vl_api_ip_neighbor_add_del_t *mp;
3890     f64 timeout;
3891     u32 sw_if_index;
3892     u8 sw_if_index_set = 0;
3893     u32 vrf_id = 0;
3894     u8 is_add = 1;
3895     u8 is_static = 0;
3896     u8 mac_address[6];
3897     u8 mac_set = 0;
3898     u8 v4_address_set = 0;
3899     u8 v6_address_set = 0;
3900     ip4_address_t v4address;
3901     ip6_address_t v6address;
3902     
3903     memset (mac_address, 0, sizeof (mac_address));
3904     
3905     /* Parse args required to build the message */
3906     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3907         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
3908             mac_set = 1;
3909         }
3910         else if (unformat (i, "del"))
3911             is_add = 0;
3912         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3913             sw_if_index_set = 1;
3914         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3915             sw_if_index_set = 1;
3916         else if (unformat (i, "is_static"))
3917             is_static = 1;
3918         else if (unformat (i, "vrf %d", &vrf_id))
3919             ;
3920         else if (unformat (i, "dst %U", 
3921                            unformat_ip4_address, &v4address))
3922                 v4_address_set = 1;
3923         else if (unformat (i, "dst %U", 
3924                            unformat_ip6_address, &v6address))
3925                 v6_address_set = 1;
3926         else {
3927             clib_warning ("parse error '%U'", format_unformat_error, i);
3928             return -99;
3929         }
3930     }
3931
3932     if (sw_if_index_set == 0) {
3933         errmsg ("missing interface name or sw_if_index\n");
3934         return -99;
3935     }
3936     if (v4_address_set && v6_address_set) {
3937         errmsg ("both v4 and v6 addresses set\n");
3938         return -99;
3939     }
3940     if (!v4_address_set && !v6_address_set) {
3941         errmsg ("no addresses set\n");
3942         return -99;
3943     }
3944
3945     /* Construct the API message */
3946     M(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del);
3947
3948     mp->sw_if_index = ntohl (sw_if_index);
3949     mp->is_add = is_add;
3950     mp->vrf_id = ntohl (vrf_id);
3951     mp->is_static = is_static;
3952     if (mac_set)
3953         memcpy (mp->mac_address, mac_address, 6);
3954     if (v6_address_set) {
3955         mp->is_ipv6 = 1;
3956         memcpy (mp->dst_address, &v6address, sizeof (v6address));
3957     } else {
3958         /* mp->is_ipv6 = 0; via memset in M macro above */
3959         memcpy (mp->dst_address, &v4address, sizeof (v4address));
3960     }
3961
3962     /* send it... */
3963     S;
3964
3965     /* Wait for a reply, return good/bad news  */
3966     W;
3967
3968     /* NOTREACHED */
3969     return 0;
3970 }
3971
3972 static int api_reset_vrf (vat_main_t * vam)
3973 {
3974     unformat_input_t * i = vam->input;
3975     vl_api_reset_vrf_t *mp;
3976     f64 timeout;
3977     u32 vrf_id = 0;
3978     u8 is_ipv6 = 0;
3979     u8 vrf_id_set = 0;
3980
3981     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3982         if (unformat (i, "vrf %d", &vrf_id))
3983             vrf_id_set = 1;
3984         else if (unformat (i, "ipv6"))
3985             is_ipv6 = 1;
3986         else {
3987             clib_warning ("parse error '%U'", format_unformat_error, i);
3988             return -99;
3989         }
3990     }
3991
3992     if (vrf_id_set == 0) {
3993         errmsg ("missing vrf id\n");
3994         return -99;
3995     }
3996     
3997     M(RESET_VRF, reset_vrf);
3998
3999     mp->vrf_id = ntohl(vrf_id);
4000     mp->is_ipv6 = is_ipv6;
4001
4002     S; W;
4003     /* NOTREACHED */
4004     return 0;
4005 }
4006
4007 static int api_create_vlan_subif (vat_main_t * vam)
4008 {
4009     unformat_input_t * i = vam->input;
4010     vl_api_create_vlan_subif_t *mp;
4011     f64 timeout;
4012     u32 sw_if_index;
4013     u8  sw_if_index_set = 0;
4014     u32 vlan_id;
4015     u8  vlan_id_set = 0;
4016
4017     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4018         if (unformat (i, "sw_if_index %d", &sw_if_index))
4019             sw_if_index_set = 1;
4020         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4021             sw_if_index_set = 1;
4022         else if (unformat (i, "vlan %d", &vlan_id))
4023             vlan_id_set = 1;
4024         else {
4025             clib_warning ("parse error '%U'", format_unformat_error, i);
4026             return -99;
4027         }
4028     }
4029     
4030     if (sw_if_index_set == 0) {
4031         errmsg ("missing interface name or sw_if_index\n");
4032         return -99;
4033     }
4034
4035     if (vlan_id_set == 0) {
4036         errmsg ("missing vlan_id\n");
4037         return -99;
4038     }
4039     M(CREATE_VLAN_SUBIF, create_vlan_subif);
4040
4041     mp->sw_if_index = ntohl(sw_if_index);
4042     mp->vlan_id = ntohl(vlan_id);
4043
4044     S; W;
4045     /* NOTREACHED */
4046     return 0;
4047 }
4048
4049 #define foreach_create_subif_bit                \
4050 _(no_tags)                                      \
4051 _(one_tag)                                      \
4052 _(two_tags)                                     \
4053 _(dot1ad)                                       \
4054 _(exact_match)                                  \
4055 _(default_sub)                                  \
4056 _(outer_vlan_id_any)                            \
4057 _(inner_vlan_id_any)
4058
4059 static int api_create_subif (vat_main_t * vam)
4060 {
4061     unformat_input_t * i = vam->input;
4062     vl_api_create_subif_t *mp;
4063     f64 timeout;
4064     u32 sw_if_index;
4065     u8  sw_if_index_set = 0;
4066     u32 sub_id;
4067     u8  sub_id_set = 0;
4068     u32 no_tags = 0;
4069     u32 one_tag = 0;
4070     u32 two_tags = 0;
4071     u32 dot1ad = 0;
4072     u32 exact_match = 0;
4073     u32 default_sub = 0;
4074     u32 outer_vlan_id_any = 0;
4075     u32 inner_vlan_id_any = 0;
4076     u32 tmp;
4077     u16 outer_vlan_id = 0;
4078     u16 inner_vlan_id = 0;
4079
4080     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4081         if (unformat (i, "sw_if_index %d", &sw_if_index))
4082             sw_if_index_set = 1;
4083         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4084             sw_if_index_set = 1;
4085         else if (unformat (i, "sub_id %d", &sub_id))
4086             sub_id_set = 1;
4087         else if (unformat (i, "outer_vlan_id %d", &tmp))
4088             outer_vlan_id = tmp;
4089         else if (unformat (i, "inner_vlan_id %d", &tmp))
4090             inner_vlan_id = tmp;
4091
4092 #define _(a) else if (unformat (i, #a)) a = 1 ;
4093         foreach_create_subif_bit
4094 #undef _
4095
4096         else {
4097             clib_warning ("parse error '%U'", format_unformat_error, i);
4098             return -99;
4099         }
4100     }
4101     
4102     if (sw_if_index_set == 0) {
4103         errmsg ("missing interface name or sw_if_index\n");
4104         return -99;
4105     }
4106
4107     if (sub_id_set == 0) {
4108         errmsg ("missing sub_id\n");
4109         return -99;
4110     }
4111     M(CREATE_SUBIF, create_subif);
4112
4113     mp->sw_if_index = ntohl(sw_if_index);
4114     mp->sub_id = ntohl(sub_id);
4115     
4116 #define _(a) mp->a = a;
4117     foreach_create_subif_bit;
4118 #undef _
4119         
4120     mp->outer_vlan_id = ntohs (outer_vlan_id);
4121     mp->inner_vlan_id = ntohs (inner_vlan_id);
4122
4123     S; W;
4124     /* NOTREACHED */
4125     return 0;
4126 }
4127
4128 static int api_oam_add_del (vat_main_t * vam)
4129 {
4130     unformat_input_t * i = vam->input;
4131     vl_api_oam_add_del_t *mp;
4132     f64 timeout;
4133     u32 vrf_id = 0;
4134     u8 is_add = 1;
4135     ip4_address_t src, dst;
4136     u8 src_set = 0;
4137     u8 dst_set = 0;
4138     
4139     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4140         if (unformat (i, "vrf %d", &vrf_id))
4141             ;
4142         else if (unformat (i, "src %U", unformat_ip4_address, &src))
4143             src_set = 1;
4144         else if (unformat (i, "dst %U", unformat_ip4_address, &dst))
4145             dst_set = 1;
4146         else if (unformat (i, "del"))
4147             is_add = 0;
4148         else {
4149             clib_warning ("parse error '%U'", format_unformat_error, i);
4150             return -99;
4151         }
4152     }
4153     
4154     if (src_set == 0) {
4155         errmsg ("missing src addr\n");
4156         return -99;
4157     }
4158
4159     if (dst_set == 0) {
4160         errmsg ("missing dst addr\n");
4161         return -99;
4162     }
4163
4164     M(OAM_ADD_DEL, oam_add_del);
4165
4166     mp->vrf_id = ntohl(vrf_id);
4167     mp->is_add = is_add;
4168     memcpy(mp->src_address, &src, sizeof (mp->src_address));
4169     memcpy(mp->dst_address, &dst, sizeof (mp->dst_address));
4170
4171     S; W;
4172     /* NOTREACHED */
4173     return 0;
4174 }
4175
4176 static int api_reset_fib (vat_main_t * vam)
4177 {
4178     unformat_input_t * i = vam->input;
4179     vl_api_reset_fib_t *mp;
4180     f64 timeout;
4181     u32 vrf_id = 0;
4182     u8 is_ipv6 = 0;
4183     u8 vrf_id_set = 0;
4184
4185     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4186         if (unformat (i, "vrf %d", &vrf_id))
4187             vrf_id_set = 1;
4188         else if (unformat (i, "ipv6"))
4189             is_ipv6 = 1;
4190         else {
4191             clib_warning ("parse error '%U'", format_unformat_error, i);
4192             return -99;
4193         }
4194     }
4195
4196     if (vrf_id_set == 0) {
4197         errmsg ("missing vrf id\n");
4198         return -99;
4199     }
4200     
4201     M(RESET_FIB, reset_fib);
4202
4203     mp->vrf_id = ntohl(vrf_id);
4204     mp->is_ipv6 = is_ipv6;
4205
4206     S; W;
4207     /* NOTREACHED */
4208     return 0;
4209 }
4210
4211 static int api_dhcp_proxy_config (vat_main_t * vam)
4212 {
4213     unformat_input_t * i = vam->input;
4214     vl_api_dhcp_proxy_config_t *mp;
4215     f64 timeout;
4216     u32 vrf_id = 0;
4217     u8 is_add = 1;
4218     u8 insert_cid = 1;
4219     u8 v4_address_set = 0;
4220     u8 v6_address_set = 0;
4221     ip4_address_t v4address;
4222     ip6_address_t v6address;
4223     u8 v4_src_address_set = 0;
4224     u8 v6_src_address_set = 0;
4225     ip4_address_t v4srcaddress;
4226     ip6_address_t v6srcaddress;
4227     
4228     /* Parse args required to build the message */
4229     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4230         if (unformat (i, "del"))
4231             is_add = 0;
4232         else if (unformat (i, "vrf %d", &vrf_id))
4233             ;
4234         else if (unformat (i, "insert-cid %d", &insert_cid))
4235             ;
4236         else if (unformat (i, "svr %U", 
4237                            unformat_ip4_address, &v4address))
4238                 v4_address_set = 1;
4239         else if (unformat (i, "svr %U", 
4240                            unformat_ip6_address, &v6address))
4241                 v6_address_set = 1;
4242         else if (unformat (i, "src %U", 
4243                            unformat_ip4_address, &v4srcaddress))
4244                 v4_src_address_set = 1;
4245         else if (unformat (i, "src %U", 
4246                            unformat_ip6_address, &v6srcaddress))
4247                 v6_src_address_set = 1;
4248         else
4249             break;
4250     }
4251
4252     if (v4_address_set && v6_address_set) {
4253         errmsg ("both v4 and v6 server addresses set\n");
4254         return -99;
4255     }
4256     if (!v4_address_set && !v6_address_set) {
4257         errmsg ("no server addresses set\n");
4258         return -99;
4259     }
4260
4261     if (v4_src_address_set && v6_src_address_set) {
4262         errmsg ("both v4 and v6  src addresses set\n");
4263         return -99;
4264     }
4265     if (!v4_src_address_set && !v6_src_address_set) {
4266         errmsg ("no src addresses set\n");
4267         return -99;
4268     }
4269
4270     if (!(v4_src_address_set && v4_address_set) &&
4271         !(v6_src_address_set && v6_address_set)) {
4272         errmsg ("no matching server and src addresses set\n");
4273         return -99;
4274     }
4275
4276     /* Construct the API message */
4277     M(DHCP_PROXY_CONFIG, dhcp_proxy_config);
4278
4279     mp->insert_circuit_id = insert_cid;
4280     mp->is_add = is_add;
4281     mp->vrf_id = ntohl (vrf_id);
4282     if (v6_address_set) {
4283         mp->is_ipv6 = 1;
4284         memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
4285         memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
4286     } else {
4287         memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
4288         memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
4289     }
4290
4291     /* send it... */
4292     S;
4293
4294     /* Wait for a reply, return good/bad news  */
4295     W;
4296     /* NOTREACHED */
4297     return 0;
4298 }
4299
4300 static int api_dhcp_proxy_config_2 (vat_main_t * vam)
4301 {
4302     unformat_input_t * i = vam->input;
4303     vl_api_dhcp_proxy_config_2_t *mp;
4304     f64 timeout;
4305     u32 rx_vrf_id = 0;
4306     u32 server_vrf_id = 0;
4307     u8 is_add = 1;
4308     u8 insert_cid = 1;
4309     u8 v4_address_set = 0;
4310     u8 v6_address_set = 0;
4311     ip4_address_t v4address;
4312     ip6_address_t v6address;
4313     u8 v4_src_address_set = 0;
4314     u8 v6_src_address_set = 0;
4315     ip4_address_t v4srcaddress;
4316     ip6_address_t v6srcaddress;
4317     
4318     /* Parse args required to build the message */
4319     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4320         if (unformat (i, "del"))
4321             is_add = 0;
4322         else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
4323             ;
4324         else if (unformat (i, "server_vrf_id %d", &server_vrf_id))
4325             ;
4326         else if (unformat (i, "insert-cid %d", &insert_cid))
4327             ;
4328         else if (unformat (i, "svr %U", 
4329                            unformat_ip4_address, &v4address))
4330                 v4_address_set = 1;
4331         else if (unformat (i, "svr %U", 
4332                            unformat_ip6_address, &v6address))
4333                 v6_address_set = 1;
4334         else if (unformat (i, "src %U", 
4335                            unformat_ip4_address, &v4srcaddress))
4336                 v4_src_address_set = 1;
4337         else if (unformat (i, "src %U", 
4338                            unformat_ip6_address, &v6srcaddress))
4339                 v6_src_address_set = 1;
4340         else
4341             break;
4342     }
4343
4344     if (v4_address_set && v6_address_set) {
4345         errmsg ("both v4 and v6 server addresses set\n");
4346         return -99;
4347     }
4348     if (!v4_address_set && !v6_address_set) {
4349         errmsg ("no server addresses set\n");
4350         return -99;
4351     }
4352
4353     if (v4_src_address_set && v6_src_address_set) {
4354         errmsg ("both v4 and v6  src addresses set\n");
4355         return -99;
4356     }
4357     if (!v4_src_address_set && !v6_src_address_set) {
4358         errmsg ("no src addresses set\n");
4359         return -99;
4360     }
4361
4362     if (!(v4_src_address_set && v4_address_set) &&
4363         !(v6_src_address_set && v6_address_set)) {
4364         errmsg ("no matching server and src addresses set\n");
4365         return -99;
4366     }
4367
4368     /* Construct the API message */
4369     M(DHCP_PROXY_CONFIG_2, dhcp_proxy_config_2);
4370
4371     mp->insert_circuit_id = insert_cid;
4372     mp->is_add = is_add;
4373     mp->rx_vrf_id = ntohl (rx_vrf_id);
4374     mp->server_vrf_id = ntohl (server_vrf_id);
4375     if (v6_address_set) {
4376         mp->is_ipv6 = 1;
4377         memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
4378         memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
4379     } else {
4380         memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
4381         memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
4382     }
4383
4384     /* send it... */
4385     S;
4386
4387     /* Wait for a reply, return good/bad news  */
4388     W;
4389     /* NOTREACHED */
4390     return 0;
4391 }
4392
4393 static int api_dhcp_proxy_set_vss (vat_main_t * vam)
4394 {
4395     unformat_input_t * i = vam->input;
4396     vl_api_dhcp_proxy_set_vss_t *mp;
4397     f64 timeout;
4398     u8  is_ipv6 = 0;
4399     u8  is_add = 1;
4400     u32 tbl_id;
4401     u8  tbl_id_set = 0;
4402     u32 oui;
4403     u8  oui_set = 0;
4404     u32 fib_id;
4405     u8  fib_id_set = 0;
4406
4407     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4408         if (unformat (i, "tbl_id %d", &tbl_id))
4409             tbl_id_set = 1;
4410         if (unformat (i, "fib_id %d", &fib_id))
4411             fib_id_set = 1;
4412         if (unformat (i, "oui %d", &oui))
4413             oui_set = 1;
4414         else if (unformat (i, "ipv6"))
4415             is_ipv6 = 1;
4416         else if (unformat (i, "del"))
4417             is_add = 0;
4418         else {
4419             clib_warning ("parse error '%U'", format_unformat_error, i);
4420             return -99;
4421         }
4422     }
4423
4424     if (tbl_id_set == 0) {
4425         errmsg ("missing tbl id\n");
4426         return -99;
4427     }
4428
4429     if (fib_id_set == 0) {
4430         errmsg ("missing fib id\n");
4431         return -99;
4432     }
4433     if (oui_set == 0) {
4434         errmsg ("missing oui\n");
4435         return -99;
4436     }
4437     
4438     M(DHCP_PROXY_SET_VSS, dhcp_proxy_set_vss);
4439     mp->tbl_id = ntohl(tbl_id);
4440     mp->fib_id = ntohl(fib_id);
4441     mp->oui = ntohl(oui);
4442     mp->is_ipv6 = is_ipv6;
4443     mp->is_add = is_add;
4444
4445     S; W;
4446     /* NOTREACHED */
4447     return 0;
4448 }
4449
4450 static int api_dhcp_client_config (vat_main_t * vam)
4451 {
4452     unformat_input_t * i = vam->input;
4453     vl_api_dhcp_client_config_t *mp;
4454     f64 timeout;
4455     u32 sw_if_index;
4456     u8 sw_if_index_set = 0;
4457     u8 is_add = 1;
4458     u8 * hostname = 0;
4459     u8 disable_event = 0;
4460
4461     /* Parse args required to build the message */
4462     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4463         if (unformat (i, "del"))
4464             is_add = 0;
4465         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4466             sw_if_index_set = 1;
4467         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4468             sw_if_index_set = 1;
4469         else if (unformat (i, "hostname %s", &hostname))
4470             ;
4471         else if (unformat (i, "disable_event"))
4472             disable_event = 1;
4473         else
4474             break;
4475     }
4476
4477     if (sw_if_index_set == 0) {
4478         errmsg ("missing interface name or sw_if_index\n");
4479         return -99;
4480     }
4481
4482     if (vec_len (hostname) > 63) {
4483         errmsg ("hostname too long\n");
4484     }
4485     vec_add1 (hostname, 0);
4486
4487     /* Construct the API message */
4488     M(DHCP_CLIENT_CONFIG, dhcp_client_config);
4489
4490     mp->sw_if_index = ntohl (sw_if_index);
4491     memcpy (mp->hostname, hostname, vec_len (hostname));
4492     vec_free (hostname);
4493     mp->is_add = is_add;
4494     mp->want_dhcp_event = disable_event ? 0 : 1;
4495     mp->pid = getpid();
4496    
4497     /* send it... */
4498     S;
4499
4500     /* Wait for a reply, return good/bad news  */
4501     W;
4502     /* NOTREACHED */
4503     return 0;
4504 }
4505
4506 static int api_set_ip_flow_hash (vat_main_t * vam)
4507 {
4508     unformat_input_t * i = vam->input;
4509     vl_api_set_ip_flow_hash_t *mp;
4510     f64 timeout;
4511     u32 vrf_id = 0;
4512     u8 is_ipv6 = 0;
4513     u8 vrf_id_set = 0;
4514     u8 src = 0;
4515     u8 dst = 0;
4516     u8 sport = 0;
4517     u8 dport = 0;
4518     u8 proto = 0;
4519     u8 reverse = 0;
4520
4521     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4522         if (unformat (i, "vrf %d", &vrf_id))
4523             vrf_id_set = 1;
4524         else if (unformat (i, "ipv6"))
4525             is_ipv6 = 1;
4526         else if (unformat (i, "src"))
4527             src = 1;
4528         else if (unformat (i, "dst"))
4529             dst = 1;
4530         else if (unformat (i, "sport"))
4531             sport = 1;
4532         else if (unformat (i, "dport"))
4533             dport = 1;
4534         else if (unformat (i, "proto"))
4535             proto = 1;
4536         else if (unformat (i, "reverse"))
4537             reverse = 1;
4538
4539         else {
4540             clib_warning ("parse error '%U'", format_unformat_error, i);
4541             return -99;
4542         }
4543     }
4544
4545     if (vrf_id_set == 0) {
4546         errmsg ("missing vrf id\n");
4547         return -99;
4548     }
4549     
4550     M(SET_IP_FLOW_HASH, set_ip_flow_hash);
4551     mp->src = src;
4552     mp->dst = dst;
4553     mp->sport = sport;
4554     mp->dport = dport;
4555     mp->proto = proto;
4556     mp->reverse = reverse;
4557     mp->vrf_id = ntohl(vrf_id);
4558     mp->is_ipv6 = is_ipv6;
4559
4560     S; W;
4561     /* NOTREACHED */
4562     return 0;
4563 }
4564
4565 static int api_sw_interface_ip6_enable_disable (vat_main_t * vam)
4566 {
4567     unformat_input_t * i = vam->input;
4568     vl_api_sw_interface_ip6_enable_disable_t *mp;
4569     f64 timeout;
4570     u32 sw_if_index;
4571     u8  sw_if_index_set = 0;
4572     u8  enable = 0;
4573
4574     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4575         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4576             sw_if_index_set = 1;
4577         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4578             sw_if_index_set = 1;
4579         else if (unformat (i, "enable"))
4580             enable = 1;
4581         else if (unformat (i, "disable"))
4582             enable = 0;
4583         else {
4584             clib_warning ("parse error '%U'", format_unformat_error, i);
4585             return -99;
4586         }
4587     }
4588
4589     if (sw_if_index_set == 0) {
4590         errmsg ("missing interface name or sw_if_index\n");
4591         return -99;
4592     }
4593     
4594     M(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable);
4595
4596     mp->sw_if_index = ntohl(sw_if_index);
4597     mp->enable = enable;
4598
4599     S; W;
4600     /* NOTREACHED */
4601     return 0;
4602 }
4603
4604 static int api_sw_interface_ip6_set_link_local_address (vat_main_t * vam)
4605 {
4606     unformat_input_t * i = vam->input;
4607     vl_api_sw_interface_ip6_set_link_local_address_t *mp;
4608     f64 timeout;
4609     u32 sw_if_index;
4610     u8 sw_if_index_set = 0;
4611     u32 address_length = 0;
4612     u8 v6_address_set = 0;
4613     ip6_address_t v6address;
4614     
4615     /* Parse args required to build the message */
4616     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4617         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4618             sw_if_index_set = 1;
4619         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4620             sw_if_index_set = 1;
4621         else if (unformat (i, "%U/%d", 
4622                            unformat_ip6_address, &v6address, 
4623                            &address_length))
4624             v6_address_set = 1;
4625         else
4626             break;
4627     }
4628
4629     if (sw_if_index_set == 0) {
4630         errmsg ("missing interface name or sw_if_index\n");
4631         return -99;
4632     }
4633     if (!v6_address_set) {
4634         errmsg ("no address set\n");
4635         return -99;
4636     }
4637
4638     /* Construct the API message */
4639     M(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
4640       sw_interface_ip6_set_link_local_address);
4641
4642     mp->sw_if_index = ntohl (sw_if_index);
4643     memcpy (mp->address, &v6address, sizeof (v6address));
4644     mp->address_length = address_length;
4645
4646     /* send it... */
4647     S;
4648
4649     /* Wait for a reply, return good/bad news  */
4650     W;
4651
4652     /* NOTREACHED */
4653     return 0;
4654 }
4655
4656
4657 static int api_sw_interface_ip6nd_ra_prefix (vat_main_t * vam)
4658 {
4659     unformat_input_t * i = vam->input;
4660     vl_api_sw_interface_ip6nd_ra_prefix_t *mp;
4661     f64 timeout;
4662     u32 sw_if_index;
4663     u8 sw_if_index_set = 0;
4664     u32 address_length = 0;
4665     u8 v6_address_set = 0;
4666     ip6_address_t v6address;
4667     u8 use_default = 0;
4668     u8 no_advertise = 0;
4669     u8 off_link = 0;
4670     u8 no_autoconfig = 0;
4671     u8 no_onlink = 0;
4672     u8 is_no = 0;
4673     u32 val_lifetime = 0;
4674     u32 pref_lifetime = 0;
4675     
4676     /* Parse args required to build the message */
4677     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4678         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4679             sw_if_index_set = 1;
4680         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4681             sw_if_index_set = 1;
4682         else if (unformat (i, "%U/%d", 
4683                            unformat_ip6_address, &v6address, 
4684                            &address_length))
4685             v6_address_set = 1;
4686         else if (unformat (i, "val_life %d", &val_lifetime))
4687             ;
4688         else if (unformat (i, "pref_life %d", &pref_lifetime))
4689             ;
4690         else if (unformat (i, "def"))
4691             use_default = 1;
4692         else if (unformat (i, "noadv"))
4693             no_advertise = 1;
4694         else if (unformat (i, "offl"))
4695             off_link = 1;
4696         else if (unformat (i, "noauto"))
4697             no_autoconfig = 1;
4698         else if (unformat (i, "nolink"))
4699             no_onlink = 1;
4700         else if (unformat (i, "isno"))
4701             is_no = 1;
4702         else {
4703             clib_warning ("parse error '%U'", format_unformat_error, i);
4704             return -99;
4705         }        
4706     }
4707
4708     if (sw_if_index_set == 0) {
4709         errmsg ("missing interface name or sw_if_index\n");
4710         return -99;
4711     }
4712     if (!v6_address_set) {
4713         errmsg ("no address set\n");
4714         return -99;
4715     }
4716
4717     /* Construct the API message */
4718     M(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix);
4719
4720     mp->sw_if_index = ntohl (sw_if_index);
4721     memcpy (mp->address, &v6address, sizeof (v6address));
4722     mp->address_length = address_length;
4723     mp->use_default = use_default;
4724     mp->no_advertise = no_advertise;
4725     mp->off_link = off_link;
4726     mp->no_autoconfig = no_autoconfig;
4727     mp->no_onlink = no_onlink;
4728     mp->is_no = is_no;
4729     mp->val_lifetime = ntohl(val_lifetime);
4730     mp->pref_lifetime = ntohl(pref_lifetime);
4731
4732     /* send it... */
4733     S;
4734
4735     /* Wait for a reply, return good/bad news  */
4736     W;
4737
4738     /* NOTREACHED */
4739     return 0;
4740 }
4741
4742 static int api_sw_interface_ip6nd_ra_config (vat_main_t * vam)
4743 {
4744     unformat_input_t * i = vam->input;
4745     vl_api_sw_interface_ip6nd_ra_config_t *mp;
4746     f64 timeout;
4747     u32 sw_if_index;
4748     u8 sw_if_index_set = 0;
4749     u8 surpress = 0;
4750     u8 managed = 0;
4751     u8 other = 0;
4752     u8 ll_option = 0;
4753     u8 send_unicast = 0;
4754     u8 cease = 0;
4755     u8 is_no = 0;
4756     u8 default_router = 0;
4757     u32 max_interval = 0;
4758     u32 min_interval = 0;
4759     u32 lifetime = 0;
4760     u32 initial_count = 0;
4761     u32 initial_interval = 0;
4762
4763     
4764     /* Parse args required to build the message */
4765     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4766         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4767             sw_if_index_set = 1;
4768         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4769             sw_if_index_set = 1;
4770         else if (unformat (i, "maxint %d", &max_interval))
4771             ;
4772         else if (unformat (i, "minint %d", &min_interval))
4773             ;
4774         else if (unformat (i, "life %d", &lifetime))
4775             ;
4776         else if (unformat (i, "count %d", &initial_count))
4777             ;
4778         else if (unformat (i, "interval %d", &initial_interval))
4779             ;
4780         else if (unformat (i, "surpress"))
4781             surpress = 1;
4782         else if (unformat (i, "managed"))
4783             managed = 1;
4784         else if (unformat (i, "other"))
4785             other = 1;
4786         else if (unformat (i, "ll"))
4787             ll_option = 1;
4788         else if (unformat (i, "send"))
4789             send_unicast = 1;
4790         else if (unformat (i, "cease"))
4791             cease = 1;
4792         else if (unformat (i, "isno"))
4793             is_no = 1;
4794         else if (unformat (i, "def"))
4795             default_router = 1;
4796         else {
4797             clib_warning ("parse error '%U'", format_unformat_error, i);
4798             return -99;
4799         }        
4800     }
4801
4802     if (sw_if_index_set == 0) {
4803         errmsg ("missing interface name or sw_if_index\n");
4804         return -99;
4805     }
4806
4807     /* Construct the API message */
4808     M(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config);
4809
4810     mp->sw_if_index = ntohl (sw_if_index);
4811     mp->max_interval = ntohl(max_interval);
4812     mp->min_interval = ntohl(min_interval);
4813     mp->lifetime = ntohl(lifetime);
4814     mp->initial_count = ntohl(initial_count);
4815     mp->initial_interval = ntohl(initial_interval);
4816     mp->surpress = surpress;
4817     mp->managed = managed;
4818     mp->other = other;
4819     mp->ll_option = ll_option;
4820     mp->send_unicast = send_unicast;
4821     mp->cease = cease;
4822     mp->is_no = is_no;
4823     mp->default_router = default_router;
4824
4825     /* send it... */
4826     S;
4827
4828     /* Wait for a reply, return good/bad news  */
4829     W;
4830
4831     /* NOTREACHED */
4832     return 0;
4833 }
4834
4835 static int api_set_arp_neighbor_limit (vat_main_t * vam)
4836 {
4837     unformat_input_t * i = vam->input;
4838     vl_api_set_arp_neighbor_limit_t *mp;
4839     f64 timeout;
4840     u32 arp_nbr_limit;
4841     u8 limit_set = 0;
4842     u8 is_ipv6 = 0;
4843
4844     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4845         if (unformat (i, "arp_nbr_limit %d", &arp_nbr_limit))
4846             limit_set = 1;
4847         else if (unformat (i, "ipv6"))
4848             is_ipv6 = 1;
4849         else {
4850             clib_warning ("parse error '%U'", format_unformat_error, i);
4851             return -99;
4852         }
4853     }
4854
4855     if (limit_set == 0) {
4856         errmsg ("missing limit value\n");
4857         return -99;
4858     }
4859     
4860     M(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit);
4861
4862     mp->arp_neighbor_limit = ntohl(arp_nbr_limit);
4863     mp->is_ipv6 = is_ipv6;
4864
4865     S; W;
4866     /* NOTREACHED */
4867     return 0;
4868 }
4869
4870 static int api_l2_patch_add_del (vat_main_t * vam)
4871 {
4872     unformat_input_t * i = vam->input;
4873     vl_api_l2_patch_add_del_t *mp;
4874     f64 timeout;
4875     u32 rx_sw_if_index;
4876     u8 rx_sw_if_index_set = 0;
4877     u32 tx_sw_if_index;
4878     u8 tx_sw_if_index_set = 0;
4879     u8 is_add = 1;
4880     
4881     /* Parse args required to build the message */
4882     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4883         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
4884             rx_sw_if_index_set = 1;     
4885         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
4886             tx_sw_if_index_set = 1;
4887         else if (unformat (i, "rx")) {
4888             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4889                 if (unformat (i, "%U", unformat_sw_if_index, vam,
4890                               &rx_sw_if_index))
4891                     rx_sw_if_index_set = 1;
4892             } else
4893                 break;
4894         } else if (unformat (i, "tx")) {
4895             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4896                 if (unformat (i, "%U", unformat_sw_if_index, vam,
4897                               &tx_sw_if_index))
4898                     tx_sw_if_index_set = 1;
4899             } else
4900                 break;
4901         } else if (unformat (i, "del"))
4902             is_add = 0;
4903         else
4904             break;
4905     }
4906
4907     if (rx_sw_if_index_set == 0) {
4908         errmsg ("missing rx interface name or rx_sw_if_index\n");
4909         return -99;
4910     }
4911
4912     if (tx_sw_if_index_set == 0) {
4913         errmsg ("missing tx interface name or tx_sw_if_index\n");
4914         return -99;
4915     }
4916     
4917     M(L2_PATCH_ADD_DEL, l2_patch_add_del);
4918
4919     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
4920     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
4921     mp->is_add = is_add;
4922
4923     S; W;
4924     /* NOTREACHED */
4925     return 0;
4926 }
4927
4928 static int api_sr_tunnel_add_del (vat_main_t * vam)
4929 {
4930   unformat_input_t * i = vam->input;
4931   vl_api_sr_tunnel_add_del_t *mp;
4932   f64 timeout;
4933   int is_del = 0;
4934   int pl_index;
4935   ip6_address_t src_address;
4936   int src_address_set = 0;
4937   ip6_address_t dst_address;
4938   u32 dst_mask_width;
4939   int dst_address_set = 0;
4940   u16 flags = 0;
4941   u32 rx_table_id = 0;
4942   u32 tx_table_id = 0;
4943   ip6_address_t * segments = 0;
4944   ip6_address_t * this_seg;
4945   ip6_address_t * tags = 0;
4946   ip6_address_t * this_tag;
4947   ip6_address_t next_address, tag;
4948
4949   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4950     {
4951       if (unformat (i, "del"))
4952         is_del = 1;
4953       else if (unformat (i, "rx_fib_id %d", &rx_table_id))
4954         ;
4955       else if (unformat (i, "tx_fib_id %d", &tx_table_id))
4956         ;
4957       else if (unformat (i, "src %U", unformat_ip6_address, &src_address))
4958         src_address_set = 1;
4959       else if (unformat (i, "dst %U/%d", 
4960                          unformat_ip6_address, &dst_address,
4961                          &dst_mask_width))
4962         dst_address_set = 1;
4963       else if (unformat (i, "next %U", unformat_ip6_address,
4964                          &next_address))
4965         {
4966           vec_add2 (segments, this_seg, 1);
4967           memcpy (this_seg->as_u8, next_address.as_u8, sizeof (*this_seg));
4968         }
4969       else if (unformat (i, "tag %U", unformat_ip6_address,
4970                          &tag))
4971         {
4972           vec_add2 (tags, this_tag, 1);
4973           memcpy (this_tag->as_u8, tag.as_u8, sizeof (*this_tag));
4974         }
4975       else if (unformat (i, "clean"))
4976         flags |= IP6_SR_HEADER_FLAG_CLEANUP;
4977       else if (unformat (i, "protected"))
4978         flags |= IP6_SR_HEADER_FLAG_PROTECTED;
4979       else if (unformat (i, "InPE %d", &pl_index))
4980         {
4981           if (pl_index <= 0 || pl_index > 4)
4982             {
4983             pl_index_range_error:
4984               errmsg ("pl index %d out of range\n", pl_index);
4985               return -99;
4986             }
4987           flags |= IP6_SR_HEADER_FLAG_PL_ELT_INGRESS_PE << (3*(pl_index - 1));
4988         }
4989       else if (unformat (i, "EgPE %d", &pl_index))
4990         {
4991           if (pl_index <= 0 || pl_index > 4)
4992             goto pl_index_range_error;
4993           flags |= IP6_SR_HEADER_FLAG_PL_ELT_EGRESS_PE << (3*(pl_index - 1));
4994         }
4995       else if (unformat (i, "OrgSrc %d", &pl_index))
4996         {
4997           if (pl_index <= 0 || pl_index > 4)
4998             goto pl_index_range_error;
4999           flags |= IP6_SR_HEADER_FLAG_PL_ELT_ORIG_SRC_ADDR << (3*(pl_index - 1));
5000         }
5001       else 
5002         break;
5003     }
5004
5005   if (!src_address_set)
5006     {
5007       errmsg ("src address required\n");
5008       return -99;
5009     }
5010
5011   if (!dst_address_set)
5012     {
5013       errmsg ("dst address required\n");
5014       return -99;
5015     }
5016
5017   if (!segments)
5018     {
5019       errmsg ("at least one sr segment required\n");
5020       return -99;
5021     }
5022
5023   M2(SR_TUNNEL_ADD_DEL, sr_tunnel_add_del, 
5024      vec_len(segments) * sizeof (ip6_address_t) 
5025      + vec_len(tags) * sizeof (ip6_address_t));
5026
5027   memcpy (mp->src_address, &src_address, sizeof (mp->src_address));
5028   memcpy (mp->dst_address, &dst_address, sizeof (mp->dst_address));
5029   mp->dst_mask_width = dst_mask_width;
5030   mp->flags_net_byte_order = clib_host_to_net_u16 (flags);
5031   mp->n_segments = vec_len (segments);
5032   mp->n_tags = vec_len (tags);
5033   mp->is_add = is_del == 0;
5034   memcpy (mp->segs_and_tags, segments, 
5035           vec_len(segments)* sizeof (ip6_address_t));
5036   memcpy (mp->segs_and_tags + vec_len(segments)*sizeof (ip6_address_t),
5037           tags, vec_len(tags)* sizeof (ip6_address_t));
5038
5039   mp->outer_vrf_id = ntohl (rx_table_id);
5040   mp->inner_vrf_id = ntohl (tx_table_id);
5041
5042   vec_free (segments);
5043   vec_free (tags);
5044   
5045   S; W;
5046   /* NOTREACHED */
5047 }
5048
5049
5050 #define foreach_ip4_proto_field                 \
5051 _(src_address)                                  \
5052 _(dst_address)                                  \
5053 _(tos)                                          \
5054 _(length)                                       \
5055 _(fragment_id)                                  \
5056 _(ttl)                                          \
5057 _(protocol)                                     \
5058 _(checksum)
5059
5060 uword unformat_ip4_mask (unformat_input_t * input, va_list * args)
5061 {
5062   u8 ** maskp = va_arg (*args, u8 **);
5063   u8 * mask = 0;
5064   u8 found_something = 0;
5065   ip4_header_t * ip;
5066   
5067 #define _(a) u8 a=0;
5068   foreach_ip4_proto_field;
5069 #undef _
5070   u8 version = 0;
5071   u8 hdr_length = 0;
5072   
5073   
5074   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5075     {
5076       if (unformat (input, "version")) 
5077         version = 1;
5078       else if (unformat (input, "hdr_length"))
5079         hdr_length = 1;
5080       else if (unformat (input, "src"))
5081         src_address = 1;
5082       else if (unformat (input, "dst"))
5083         dst_address = 1;
5084       else if (unformat (input, "proto"))
5085         protocol = 1;
5086       
5087 #define _(a) else if (unformat (input, #a)) a=1;
5088       foreach_ip4_proto_field
5089 #undef _
5090       else
5091         break;
5092     }
5093   
5094 #define _(a) found_something += a;
5095   foreach_ip4_proto_field;
5096 #undef _
5097   
5098   if (found_something == 0)
5099     return 0;
5100   
5101   vec_validate (mask, sizeof (*ip) - 1);
5102   
5103   ip = (ip4_header_t *) mask;
5104   
5105 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
5106   foreach_ip4_proto_field;
5107 #undef _
5108   
5109   ip->ip_version_and_header_length = 0;
5110   
5111   if (version)
5112     ip->ip_version_and_header_length |= 0xF0;
5113   
5114   if (hdr_length)
5115     ip->ip_version_and_header_length |= 0x0F;
5116   
5117   *maskp = mask;
5118   return 1;
5119 }
5120
5121 #define foreach_ip6_proto_field                 \
5122 _(src_address)                                  \
5123 _(dst_address)                                  \
5124 _(payload_length)                               \
5125 _(hop_limit)                                    \
5126 _(protocol)
5127
5128 uword unformat_ip6_mask (unformat_input_t * input, va_list * args)
5129 {
5130   u8 ** maskp = va_arg (*args, u8 **);
5131   u8 * mask = 0;
5132   u8 found_something = 0;
5133   ip6_header_t * ip;
5134   u32 ip_version_traffic_class_and_flow_label;
5135   
5136 #define _(a) u8 a=0;
5137   foreach_ip6_proto_field;
5138 #undef _
5139   u8 version = 0;
5140   u8 traffic_class = 0;
5141   u8 flow_label = 0;
5142   
5143   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5144     {
5145       if (unformat (input, "version")) 
5146         version = 1;
5147       else if (unformat (input, "traffic-class"))
5148         traffic_class = 1;
5149       else if (unformat (input, "flow-label"))
5150         flow_label = 1;
5151       else if (unformat (input, "src"))
5152         src_address = 1;
5153       else if (unformat (input, "dst"))
5154         dst_address = 1;
5155       else if (unformat (input, "proto"))
5156         protocol = 1;
5157       
5158 #define _(a) else if (unformat (input, #a)) a=1;
5159       foreach_ip6_proto_field
5160 #undef _
5161       else
5162         break;
5163     }
5164   
5165 #define _(a) found_something += a;
5166   foreach_ip6_proto_field;
5167 #undef _
5168   
5169   if (found_something == 0)
5170     return 0;
5171   
5172   vec_validate (mask, sizeof (*ip) - 1);
5173   
5174   ip = (ip6_header_t *) mask;
5175   
5176 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
5177   foreach_ip6_proto_field;
5178 #undef _
5179   
5180   ip_version_traffic_class_and_flow_label = 0;
5181   
5182   if (version)
5183     ip_version_traffic_class_and_flow_label |= 0xF0000000;
5184
5185   if (traffic_class)
5186     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
5187
5188   if (flow_label)
5189     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
5190
5191   ip->ip_version_traffic_class_and_flow_label = 
5192     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5193   
5194   *maskp = mask;
5195   return 1;
5196 }
5197
5198 uword unformat_l3_mask (unformat_input_t * input, va_list * args)
5199 {
5200   u8 ** maskp = va_arg (*args, u8 **);
5201
5202   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5203     if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
5204       return 1;
5205     else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
5206       return 1;
5207     else
5208       break;
5209   }
5210   return 0;
5211 }
5212
5213 uword unformat_l2_mask (unformat_input_t * input, va_list * args)
5214 {
5215   u8 ** maskp = va_arg (*args, u8 **);
5216   u8 * mask = 0;
5217   u8 src = 0;
5218   u8 dst = 0;
5219   u8 proto = 0;
5220   u8 tag1 = 0;
5221   u8 tag2 = 0;
5222   u8 ignore_tag1 = 0;
5223   u8 ignore_tag2 = 0;
5224   u8 cos1 = 0;
5225   u8 cos2 = 0;
5226   u8 dot1q = 0;
5227   u8 dot1ad = 0;
5228   int len = 14;
5229
5230   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5231     if (unformat (input, "src"))
5232       src = 1;
5233     else if (unformat (input, "dst"))
5234       dst = 1;
5235     else if (unformat (input, "proto"))
5236       proto = 1;
5237     else if (unformat (input, "tag1"))
5238       tag1 = 1;
5239     else if (unformat (input, "tag2"))
5240       tag2 = 1;
5241     else if (unformat (input, "ignore-tag1"))
5242       ignore_tag1 = 1;
5243     else if (unformat (input, "ignore-tag2"))
5244       ignore_tag2 = 1;
5245     else if (unformat (input, "cos1"))
5246       cos1 = 1;
5247     else if (unformat (input, "cos2"))
5248       cos2 = 1;
5249     else if (unformat (input, "dot1q"))
5250       dot1q = 1;
5251     else if (unformat (input, "dot1ad"))
5252       dot1ad = 1;
5253     else
5254       break;
5255   }
5256   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
5257       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5258     return 0;
5259
5260   if (tag1 || ignore_tag1 || cos1 || dot1q)
5261     len = 18;
5262   if (tag2 || ignore_tag2 || cos2 || dot1ad)
5263     len = 22;
5264
5265   vec_validate (mask, len-1);
5266
5267   if (dst)
5268     memset (mask, 0xff, 6);
5269
5270   if (src)
5271     memset (mask + 6, 0xff, 6);
5272   
5273   if (tag2 || dot1ad)
5274     {
5275       /* inner vlan tag */
5276       if (tag2)
5277         {
5278           mask[19] = 0xff;
5279           mask[18] = 0x0f;
5280         }
5281       if (cos2)
5282         mask[18] |= 0xe0;
5283       if (proto)
5284           mask[21] = mask [20] = 0xff;
5285       if (tag1)
5286         {
5287           mask [15] = 0xff;
5288           mask [14] = 0x0f;
5289         }
5290       if (cos1)
5291         mask[14] |= 0xe0;
5292       *maskp = mask;
5293       return 1;
5294     }
5295   if (tag1 | dot1q)
5296     {
5297       if (tag1)
5298         {
5299           mask [15] = 0xff;
5300           mask [14] = 0x0f;
5301         }
5302       if (cos1)
5303         mask[14] |= 0xe0;
5304       if (proto)
5305           mask[16] = mask [17] = 0xff;
5306
5307       *maskp = mask;
5308       return 1;
5309     }
5310   if (cos2)
5311     mask[18] |= 0xe0;
5312   if (cos1)
5313     mask[14] |= 0xe0;
5314   if (proto)
5315     mask[12] = mask [13] = 0xff;
5316     
5317   *maskp = mask;
5318   return 1;
5319 }
5320
5321 uword unformat_classify_mask (unformat_input_t * input, va_list * args)
5322 {
5323   u8 ** maskp = va_arg (*args, u8 **);
5324   u32 * skipp = va_arg (*args, u32 *);
5325   u32 * matchp = va_arg (*args, u32 *);
5326   u32 match;
5327   u8 * mask = 0;
5328   u8 * l2 = 0;
5329   u8 * l3 = 0;
5330   int i;
5331   
5332   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5333     if (unformat (input, "hex %U", unformat_hex_string, &mask))
5334       ;
5335     else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
5336       ;
5337     else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
5338       ;
5339     else
5340       break;
5341   }
5342
5343   if (mask || l2 || l3)
5344     {
5345       if (l2 || l3)
5346         {
5347           /* "With a free Ethernet header in every package" */
5348           if (l2 == 0)
5349             vec_validate (l2, 13);
5350           mask = l2;
5351           vec_append (mask, l3);
5352           vec_free (l3);
5353         }
5354
5355       /* Scan forward looking for the first significant mask octet */
5356       for (i = 0; i < vec_len (mask); i++)
5357         if (mask[i])
5358           break;
5359
5360       /* compute (skip, match) params */
5361       *skipp = i / sizeof(u32x4);
5362       vec_delete (mask, *skipp * sizeof(u32x4), 0);
5363
5364       /* Pad mask to an even multiple of the vector size */
5365       while (vec_len (mask) % sizeof (u32x4))
5366         vec_add1 (mask, 0);
5367
5368       match = vec_len (mask) / sizeof (u32x4);
5369
5370       for (i = match*sizeof(u32x4); i > 0; i-= sizeof(u32x4))
5371         {
5372           u64 *tmp = (u64 *)(mask + (i-sizeof(u32x4)));
5373           if (*tmp || *(tmp+1))
5374             break;
5375           match--;
5376         }
5377       if (match == 0)
5378         clib_warning ("BUG: match 0");
5379
5380       _vec_len (mask) = match * sizeof(u32x4);
5381
5382       *matchp = match;
5383       *maskp = mask;
5384
5385       return 1;
5386     }
5387
5388   return 0;
5389 }
5390
5391 #define foreach_l2_next                         \
5392 _(drop, DROP)                                   \
5393 _(ethernet, ETHERNET_INPUT)                     \
5394 _(ip4, IP4_INPUT)                               \
5395 _(ip6, IP6_INPUT)
5396
5397 uword unformat_l2_next_index (unformat_input_t * input, va_list * args)
5398 {
5399   u32 * miss_next_indexp = va_arg (*args, u32 *);
5400   u32 next_index = 0;
5401   u32 tmp;
5402   
5403 #define _(n,N) \
5404   if (unformat (input, #n)) { next_index = L2_CLASSIFY_NEXT_##N; goto out;}
5405   foreach_l2_next;
5406 #undef _
5407   
5408   if (unformat (input, "%d", &tmp))
5409     { 
5410       next_index = tmp; 
5411       goto out; 
5412     }
5413   
5414   return 0;
5415
5416  out:
5417   *miss_next_indexp = next_index;
5418   return 1;
5419 }
5420
5421 #define foreach_ip_next                         \
5422 _(miss, MISS)                                   \
5423 _(drop, DROP)                                   \
5424 _(local, LOCAL)                                 \
5425 _(rewrite, REWRITE)
5426
5427 uword unformat_ip_next_index (unformat_input_t * input, va_list * args)
5428 {
5429   u32 * miss_next_indexp = va_arg (*args, u32 *);
5430   u32 next_index = 0;
5431   u32 tmp;
5432   
5433 #define _(n,N) \
5434   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
5435   foreach_ip_next;
5436 #undef _
5437   
5438   if (unformat (input, "%d", &tmp))
5439     { 
5440       next_index = tmp; 
5441       goto out; 
5442     }
5443   
5444   return 0;
5445
5446  out:
5447   *miss_next_indexp = next_index;
5448   return 1;
5449 }
5450
5451 #define foreach_acl_next                        \
5452 _(deny, DENY)
5453
5454 uword unformat_acl_next_index (unformat_input_t * input, va_list * args)
5455 {
5456   u32 * miss_next_indexp = va_arg (*args, u32 *);
5457   u32 next_index = 0;
5458   u32 tmp;
5459
5460 #define _(n,N) \
5461   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
5462   foreach_acl_next;
5463 #undef _
5464
5465   if (unformat (input, "permit"))
5466     {
5467       next_index = ~0;
5468       goto out;
5469     }
5470   else if (unformat (input, "%d", &tmp))
5471     {
5472       next_index = tmp;
5473       goto out;
5474     }
5475
5476   return 0;
5477
5478  out:
5479   *miss_next_indexp = next_index;
5480   return 1;
5481 }
5482
5483 static int api_classify_add_del_table (vat_main_t * vam)
5484 {
5485   unformat_input_t * i = vam->input;
5486   vl_api_classify_add_del_table_t *mp;
5487
5488   u32 nbuckets = 2;
5489   u32 skip = ~0;
5490   u32 match = ~0;
5491   int is_add = 1;
5492   u32 table_index = ~0;
5493   u32 next_table_index = ~0;
5494   u32 miss_next_index = ~0;
5495   u32 memory_size = 32<<20;
5496   u8 * mask = 0;
5497   f64 timeout;
5498
5499   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5500     if (unformat (i, "del"))
5501       is_add = 0;
5502     else if (unformat (i, "buckets %d", &nbuckets))
5503       ;
5504     else if (unformat (i, "memory_size %d", &memory_size))
5505       ;
5506     else if (unformat (i, "skip %d", &skip))
5507       ;
5508     else if (unformat (i, "match %d", &match))
5509       ;
5510     else if (unformat (i, "table %d", &table_index))
5511       ;
5512     else if (unformat (i, "mask %U", unformat_classify_mask, 
5513                        &mask, &skip, &match))
5514       ;
5515     else if (unformat (i, "next-table %d", &next_table_index))
5516       ;
5517     else if (unformat (i, "miss-next %U", unformat_ip_next_index,
5518                        &miss_next_index))
5519       ;
5520     else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
5521                        &miss_next_index))
5522       ;
5523     else if (unformat (i, "acl-miss-next %U", unformat_acl_next_index,
5524                        &miss_next_index))
5525       ;
5526     else
5527       break;
5528   }
5529   
5530   if (is_add && mask == 0) {
5531       errmsg ("Mask required\n");
5532       return -99;
5533   }
5534
5535   if (is_add && skip == ~0) {
5536       errmsg ("skip count required\n");
5537       return -99;
5538   }
5539
5540   if (is_add && match == ~0) {
5541       errmsg ("match count required\n");
5542       return -99;
5543   }
5544       
5545   if (!is_add && table_index == ~0) {
5546       errmsg ("table index required for delete\n");
5547       return -99;
5548   }
5549
5550   M2 (CLASSIFY_ADD_DEL_TABLE, classify_add_del_table,
5551       vec_len(mask));
5552
5553   mp->is_add = is_add;
5554   mp->table_index = ntohl(table_index);
5555   mp->nbuckets = ntohl(nbuckets);
5556   mp->memory_size = ntohl(memory_size);
5557   mp->skip_n_vectors = ntohl(skip);
5558   mp->match_n_vectors = ntohl(match);
5559   mp->next_table_index = ntohl(next_table_index);
5560   mp->miss_next_index = ntohl(miss_next_index);
5561   memcpy (mp->mask, mask, vec_len(mask));
5562
5563   vec_free(mask);
5564
5565   S; W;
5566   /* NOTREACHED */
5567 }
5568
5569 uword unformat_ip4_match (unformat_input_t * input, va_list * args)
5570 {
5571   u8 ** matchp = va_arg (*args, u8 **);
5572   u8 * match = 0;
5573   ip4_header_t * ip;
5574   int version = 0;
5575   u32 version_val;
5576   int hdr_length = 0;
5577   u32 hdr_length_val;
5578   int src = 0, dst = 0;
5579   ip4_address_t src_val, dst_val;
5580   int proto = 0;
5581   u32 proto_val;
5582   int tos = 0;
5583   u32 tos_val;
5584   int length = 0;
5585   u32 length_val;
5586   int fragment_id = 0;
5587   u32 fragment_id_val;
5588   int ttl = 0;
5589   int ttl_val;
5590   int checksum = 0;
5591   u32 checksum_val;
5592
5593   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5594     {
5595       if (unformat (input, "version %d", &version_val)) 
5596         version = 1;
5597       else if (unformat (input, "hdr_length %d", &hdr_length_val))
5598         hdr_length = 1;
5599       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
5600         src = 1;
5601       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
5602         dst = 1;
5603       else if (unformat (input, "proto %d", &proto_val))
5604         proto = 1;
5605       else if (unformat (input, "tos %d", &tos_val))
5606         tos = 1;
5607       else if (unformat (input, "length %d", &length_val))
5608         length = 1;
5609       else if (unformat (input, "fragment_id %d", &fragment_id_val))
5610         fragment_id = 1;
5611       else if (unformat (input, "ttl %d", &ttl_val))
5612         ttl = 1;
5613       else if (unformat (input, "checksum %d", &checksum_val))
5614         checksum = 1;
5615       else
5616         break;
5617     }
5618   
5619   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
5620       + ttl + checksum == 0)
5621     return 0;
5622
5623   /* 
5624    * Aligned because we use the real comparison functions
5625    */
5626   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
5627   
5628   ip = (ip4_header_t *) match;
5629   
5630   /* These are realistically matched in practice */
5631   if (src)
5632     ip->src_address.as_u32 = src_val.as_u32;
5633
5634   if (dst)
5635     ip->dst_address.as_u32 = dst_val.as_u32;
5636   
5637   if (proto)
5638     ip->protocol = proto_val;
5639     
5640
5641   /* These are not, but they're included for completeness */
5642   if (version)
5643     ip->ip_version_and_header_length |= (version_val & 0xF)<<4;
5644
5645   if (hdr_length)
5646     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
5647     
5648   if (tos)
5649     ip->tos = tos_val;
5650   
5651   if (length)
5652     ip->length = length_val;
5653   
5654   if (ttl)
5655     ip->ttl = ttl_val;
5656
5657   if (checksum)
5658     ip->checksum = checksum_val;
5659
5660   *matchp = match;
5661   return 1;
5662 }
5663
5664 uword unformat_ip6_match (unformat_input_t * input, va_list * args)
5665 {
5666   u8 ** matchp = va_arg (*args, u8 **);
5667   u8 * match = 0;
5668   ip6_header_t * ip;
5669   int version = 0;
5670   u32 version_val;
5671   u8  traffic_class;
5672   u32 traffic_class_val;
5673   u8  flow_label;
5674   u8  flow_label_val;
5675   int src = 0, dst = 0;
5676   ip6_address_t src_val, dst_val;
5677   int proto = 0;
5678   u32 proto_val;
5679   int payload_length = 0;
5680   u32 payload_length_val;
5681   int hop_limit = 0;
5682   int hop_limit_val;
5683   u32 ip_version_traffic_class_and_flow_label;
5684
5685   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5686     {
5687       if (unformat (input, "version %d", &version_val)) 
5688         version = 1;
5689       else if (unformat (input, "traffic_class %d", &traffic_class_val))
5690         traffic_class = 1;
5691       else if (unformat (input, "flow_label %d", &flow_label_val))
5692         flow_label = 1;
5693       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
5694         src = 1;
5695       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
5696         dst = 1;
5697       else if (unformat (input, "proto %d", &proto_val))
5698         proto = 1;
5699       else if (unformat (input, "payload_length %d", &payload_length_val))
5700         payload_length = 1;
5701       else if (unformat (input, "hop_limit %d", &hop_limit_val))
5702         hop_limit = 1;
5703       else
5704         break;
5705     }
5706   
5707   if (version + traffic_class + flow_label + src + dst + proto +
5708       payload_length + hop_limit == 0)
5709     return 0;
5710
5711   /* 
5712    * Aligned because we use the real comparison functions
5713    */
5714   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
5715   
5716   ip = (ip6_header_t *) match;
5717   
5718   if (src)
5719     memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
5720
5721   if (dst)
5722     memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
5723   
5724   if (proto)
5725     ip->protocol = proto_val;
5726     
5727   ip_version_traffic_class_and_flow_label = 0;
5728
5729   if (version)
5730     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
5731
5732   if (traffic_class)
5733     ip_version_traffic_class_and_flow_label |= (traffic_class_val & 0xFF) << 20;
5734
5735   if (flow_label)
5736     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
5737     
5738   ip->ip_version_traffic_class_and_flow_label = 
5739     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5740
5741   if (payload_length)
5742     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
5743   
5744   if (hop_limit)
5745     ip->hop_limit = hop_limit_val;
5746
5747   *matchp = match;
5748   return 1;
5749 }
5750
5751 uword unformat_l3_match (unformat_input_t * input, va_list * args)
5752 {
5753   u8 ** matchp = va_arg (*args, u8 **);
5754
5755   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5756     if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
5757       return 1;
5758     else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
5759       return 1;
5760     else
5761       break;
5762   }
5763   return 0;
5764 }
5765
5766 uword unformat_vlan_tag (unformat_input_t * input, va_list * args)
5767 {
5768   u8 * tagp = va_arg (*args, u8 *);
5769   u32 tag;
5770
5771   if (unformat(input, "%d", &tag))
5772     {
5773       tagp[0] = (tag>>8) & 0x0F;
5774       tagp[1] = tag & 0xFF;
5775       return 1;
5776     }
5777
5778   return 0;
5779 }
5780
5781 uword unformat_l2_match (unformat_input_t * input, va_list * args)
5782 {
5783   u8 ** matchp = va_arg (*args, u8 **);
5784   u8 * match = 0;
5785   u8 src = 0;
5786   u8 src_val[6];
5787   u8 dst = 0;
5788   u8 dst_val[6];
5789   u8 proto = 0;
5790   u16 proto_val;
5791   u8 tag1 = 0;
5792   u8 tag1_val [2];
5793   u8 tag2 = 0;
5794   u8 tag2_val [2];
5795   int len = 14;
5796   u8 ignore_tag1 = 0;
5797   u8 ignore_tag2 = 0;
5798   u8 cos1 = 0;
5799   u8 cos2 = 0;
5800   u32 cos1_val = 0;
5801   u32 cos2_val = 0;
5802
5803   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5804     if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
5805       src = 1;
5806     else if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
5807       dst = 1;
5808     else if (unformat (input, "proto %U", 
5809                        unformat_ethernet_type_host_byte_order, &proto_val))
5810       proto = 1;
5811     else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
5812       tag1 = 1;
5813     else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
5814       tag2 = 1;
5815     else if (unformat (input, "ignore-tag1"))
5816       ignore_tag1 = 1;
5817     else if (unformat (input, "ignore-tag2"))
5818       ignore_tag2 = 1;
5819     else if (unformat (input, "cos1 %d", &cos1_val))
5820       cos1 = 1;
5821     else if (unformat (input, "cos2 %d", &cos2_val))
5822       cos2 = 1;
5823     else
5824       break;
5825   }
5826   if ((src + dst + proto + tag1 + tag2 +
5827       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5828     return 0;
5829
5830   if (tag1 || ignore_tag1 || cos1)
5831     len = 18;
5832   if (tag2 || ignore_tag2 || cos2)
5833     len = 22;
5834
5835   vec_validate_aligned (match, len-1, sizeof(u32x4));
5836
5837   if (dst)
5838     memcpy (match, dst_val, 6);
5839
5840   if (src)
5841     memcpy (match + 6, src_val, 6);
5842   
5843   if (tag2)
5844     {
5845       /* inner vlan tag */
5846       match[19] = tag2_val[1];
5847       match[18] = tag2_val[0];
5848       if (cos2)
5849         match [18] |= (cos2_val & 0x7) << 5;
5850       if (proto)
5851         {
5852           match[21] = proto_val & 0xff;
5853           match[20] = proto_val >> 8;
5854         }
5855       if (tag1)
5856         {
5857           match [15] = tag1_val[1];
5858           match [14] = tag1_val[0];
5859         }
5860       if (cos1)
5861         match [14] |= (cos1_val & 0x7) << 5;
5862       *matchp = match;
5863       return 1;
5864     }
5865   if (tag1)
5866     {
5867       match [15] = tag1_val[1];
5868       match [14] = tag1_val[0];
5869       if (proto)
5870         {
5871           match[17] = proto_val & 0xff;
5872           match[16] = proto_val >> 8;
5873         }
5874       if (cos1)
5875         match [14] |= (cos1_val & 0x7) << 5;
5876
5877       *matchp = match;
5878       return 1;
5879     }
5880   if (cos2)
5881     match [18] |= (cos2_val & 0x7) << 5;
5882   if (cos1)
5883     match [14] |= (cos1_val & 0x7) << 5;
5884   if (proto)
5885     {
5886       match[13] = proto_val & 0xff;
5887       match[12] = proto_val >> 8;
5888     }
5889   
5890   *matchp = match;
5891   return 1;
5892 }
5893
5894
5895 uword unformat_classify_match (unformat_input_t * input, va_list * args)
5896 {
5897   u8 ** matchp = va_arg (*args, u8 **);
5898   u32 skip_n_vectors = va_arg (*args, u32);
5899   u32 match_n_vectors = va_arg (*args, u32);
5900   
5901   u8 * match = 0;
5902   u8 * l2 = 0;
5903   u8 * l3 = 0;
5904
5905   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5906     if (unformat (input, "hex %U", unformat_hex_string, &match))
5907       ;
5908     else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
5909       ;
5910     else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
5911       ;
5912     else
5913       break;
5914   }
5915
5916   if (match || l2 || l3)
5917     {
5918       if (l2 || l3)
5919         {
5920           /* "Win a free Ethernet header in every packet" */
5921           if (l2 == 0)
5922             vec_validate_aligned (l2, 13, sizeof(u32x4));
5923           match = l2;
5924           vec_append_aligned (match, l3, sizeof(u32x4));
5925           vec_free (l3);
5926         }
5927
5928       /* Make sure the vector is big enough even if key is all 0's */
5929       vec_validate_aligned 
5930           (match, ((match_n_vectors + skip_n_vectors) * sizeof(u32x4)) - 1,
5931            sizeof(u32x4));
5932       
5933       /* Set size, include skipped vectors*/
5934       _vec_len (match) = (match_n_vectors+skip_n_vectors) * sizeof(u32x4);
5935
5936       *matchp = match;
5937
5938       return 1;
5939     }
5940
5941   return 0;
5942 }
5943
5944 static int api_classify_add_del_session (vat_main_t * vam)
5945 {
5946     unformat_input_t * i = vam->input;
5947     vl_api_classify_add_del_session_t *mp;
5948     int is_add = 1;
5949     u32 table_index = ~0;
5950     u32 hit_next_index = ~0;
5951     u32 opaque_index = ~0;
5952     u8 * match = 0;
5953     i32 advance = 0;
5954     f64 timeout;
5955     u32 skip_n_vectors = 0;
5956     u32 match_n_vectors = 0;
5957
5958     /* 
5959      * Warning: you have to supply skip_n and match_n
5960      * because the API client cant simply look at the classify
5961      * table object.
5962      */
5963
5964     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5965         if (unformat (i, "del"))
5966             is_add = 0;
5967         else if (unformat (i, "hit-next %U", unformat_ip_next_index,
5968                            &hit_next_index))
5969             ;
5970         else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
5971                            &hit_next_index))
5972             ;
5973         else if (unformat (i, "acl-hit-next %U", unformat_acl_next_index,
5974                            &hit_next_index))
5975             ;
5976         else if (unformat (i, "opaque-index %d", &opaque_index))
5977             ;
5978         else if (unformat (i, "skip_n %d", &skip_n_vectors))
5979             ;
5980         else if (unformat (i, "match_n %d", &match_n_vectors))
5981             ;
5982         else if (unformat (i, "match %U", unformat_classify_match,
5983                            &match, skip_n_vectors, match_n_vectors))
5984             ;
5985         else if (unformat (i, "advance %d", &advance))
5986             ;
5987         else if (unformat (i, "table-index %d", &table_index))
5988             ;
5989         else
5990             break;
5991     }
5992
5993     if (table_index == ~0) {
5994         errmsg ("Table index required\n");
5995         return -99;
5996     }
5997
5998     if (is_add && match == 0) {
5999         errmsg ("Match value required\n");
6000         return -99;
6001     }
6002
6003     M2 (CLASSIFY_ADD_DEL_SESSION, classify_add_del_session,
6004         vec_len(match));
6005
6006     mp->is_add = is_add;
6007     mp->table_index = ntohl(table_index);
6008     mp->hit_next_index = ntohl(hit_next_index);
6009     mp->opaque_index = ntohl(opaque_index);
6010     mp->advance = ntohl(advance);
6011     memcpy (mp->match, match, vec_len(match));
6012     vec_free(match);
6013
6014     S; W;
6015     /* NOTREACHED */
6016 }
6017
6018 static int api_classify_set_interface_ip_table (vat_main_t * vam)
6019 {
6020     unformat_input_t * i = vam->input;
6021     vl_api_classify_set_interface_ip_table_t *mp;
6022     f64 timeout;
6023     u32 sw_if_index;
6024     int sw_if_index_set;
6025     u32 table_index = ~0;
6026     u8  is_ipv6 = 0;
6027
6028     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6029         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6030             sw_if_index_set = 1;
6031         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6032             sw_if_index_set = 1;
6033         else if (unformat (i, "table %d", &table_index))
6034             ;
6035         else {
6036             clib_warning ("parse error '%U'", format_unformat_error, i);
6037             return -99;
6038         }
6039     }
6040     
6041     if (sw_if_index_set == 0) {
6042         errmsg ("missing interface name or sw_if_index\n");
6043         return -99;
6044     }
6045
6046
6047     M(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table);
6048
6049     mp->sw_if_index = ntohl(sw_if_index);
6050     mp->table_index = ntohl(table_index);
6051     mp->is_ipv6 = is_ipv6;
6052
6053     S; W;
6054     /* NOTREACHED */
6055     return 0;
6056 }
6057
6058 static int api_classify_set_interface_l2_tables (vat_main_t * vam)
6059 {
6060     unformat_input_t * i = vam->input;
6061     vl_api_classify_set_interface_l2_tables_t *mp;
6062     f64 timeout;
6063     u32 sw_if_index;
6064     int sw_if_index_set;
6065     u32 ip4_table_index = ~0;
6066     u32 ip6_table_index = ~0;
6067     u32 other_table_index = ~0;
6068
6069     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6070         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6071             sw_if_index_set = 1;
6072         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6073             sw_if_index_set = 1;
6074         else if (unformat (i, "ip4-table %d", &ip4_table_index))
6075             ;
6076         else if (unformat (i, "ip6-table %d", &ip6_table_index))
6077             ;
6078         else if (unformat (i, "other-table %d", &other_table_index))
6079             ;
6080         else {
6081             clib_warning ("parse error '%U'", format_unformat_error, i);
6082             return -99;
6083         }
6084     }
6085     
6086     if (sw_if_index_set == 0) {
6087         errmsg ("missing interface name or sw_if_index\n");
6088         return -99;
6089     }
6090
6091
6092     M(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables);
6093
6094     mp->sw_if_index = ntohl(sw_if_index);
6095     mp->ip4_table_index = ntohl(ip4_table_index);
6096     mp->ip6_table_index = ntohl(ip6_table_index);
6097     mp->other_table_index = ntohl(other_table_index);
6098
6099
6100     S; W;
6101     /* NOTREACHED */
6102     return 0;
6103 }
6104
6105 static int api_get_node_index (vat_main_t * vam)
6106 {
6107     unformat_input_t * i = vam->input;
6108     vl_api_get_node_index_t * mp;
6109     f64 timeout;
6110     u8 * name = 0;
6111     
6112     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6113         if (unformat (i, "node %s", &name))
6114             ;
6115         else
6116             break;
6117     }
6118     if (name == 0) {
6119         errmsg ("node name required\n");
6120         return -99;
6121     }
6122     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
6123         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
6124         return -99;
6125     }
6126
6127     M(GET_NODE_INDEX, get_node_index);
6128     memcpy (mp->node_name, name, vec_len(name));
6129     vec_free(name);
6130     
6131     S; W;
6132     /* NOTREACHED */
6133     return 0;
6134 }
6135
6136 static int api_add_node_next (vat_main_t * vam)
6137 {
6138     unformat_input_t * i = vam->input;
6139     vl_api_add_node_next_t * mp;
6140     f64 timeout;
6141     u8 * name = 0;
6142     u8 * next = 0;
6143
6144     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6145         if (unformat (i, "node %s", &name))
6146             ;
6147         else if (unformat (i, "next %s", &next))
6148             ;
6149         else
6150             break;
6151     }
6152     if (name == 0) {
6153         errmsg ("node name required\n");
6154         return -99;
6155     }
6156     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
6157         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
6158         return -99;
6159     }
6160     if (next == 0) {
6161         errmsg ("next node required\n");
6162         return -99;
6163     }
6164     if (vec_len (next) >= ARRAY_LEN(mp->next_name)) {
6165         errmsg ("next name too long, max %d\n", ARRAY_LEN(mp->next_name));
6166         return -99;
6167     }
6168     
6169     M(ADD_NODE_NEXT, add_node_next);
6170     memcpy (mp->node_name, name, vec_len(name));
6171     memcpy (mp->next_name, next, vec_len(next));
6172     vec_free(name);
6173     vec_free(next);
6174     
6175     S; W;
6176     /* NOTREACHED */
6177     return 0;
6178 }
6179
6180 static int api_l2tpv3_create_tunnel (vat_main_t * vam)
6181 {
6182     unformat_input_t * i = vam->input;
6183     ip6_address_t client_address, our_address;
6184     int client_address_set = 0;
6185     int our_address_set = 0;
6186     u32 local_session_id = 0;
6187     u32 remote_session_id = 0;
6188     u64 local_cookie = 0;
6189     u64 remote_cookie = 0;
6190     u8 l2_sublayer_present = 0;
6191     vl_api_l2tpv3_create_tunnel_t * mp;
6192     f64 timeout;
6193
6194     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6195         if (unformat (i, "client_address %U", unformat_ip6_address, 
6196                       &client_address))
6197             client_address_set = 1;
6198         else if (unformat (i, "our_address %U", unformat_ip6_address, 
6199                            &our_address))
6200             our_address_set = 1;
6201         else if (unformat (i, "local_session_id %d", &local_session_id))
6202             ;
6203         else if (unformat (i, "remote_session_id %d", &remote_session_id))
6204             ;
6205         else if (unformat (i, "local_cookie %lld", &local_cookie))
6206             ;
6207         else if (unformat (i, "remote_cookie %lld", &remote_cookie))
6208             ;
6209         else if (unformat (i, "l2-sublayer-present"))
6210             l2_sublayer_present = 1;
6211         else
6212             break;
6213     }
6214
6215     if (client_address_set == 0) {
6216         errmsg ("client_address required\n");
6217         return -99;
6218     }
6219
6220     if (our_address_set == 0) {
6221         errmsg ("our_address required\n");
6222         return -99;
6223     }
6224
6225     M(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel);
6226
6227     memcpy (mp->client_address, client_address.as_u8, 
6228             sizeof (mp->client_address));
6229
6230     memcpy (mp->our_address, our_address.as_u8, 
6231             sizeof (mp->our_address));
6232     
6233     mp->local_session_id = ntohl (local_session_id);
6234     mp->remote_session_id = ntohl (remote_session_id);
6235     mp->local_cookie = clib_host_to_net_u64 (local_cookie);
6236     mp->remote_cookie = clib_host_to_net_u64 (remote_cookie);
6237     mp->l2_sublayer_present = l2_sublayer_present;
6238     mp->is_ipv6 = 1;
6239
6240     S; W;
6241     /* NOTREACHED */
6242     return 0;
6243 }
6244
6245 static int api_l2tpv3_set_tunnel_cookies (vat_main_t * vam)
6246 {
6247     unformat_input_t * i = vam->input;
6248     u32 sw_if_index;
6249     u8  sw_if_index_set = 0;
6250     u64 new_local_cookie = 0;
6251     u64 new_remote_cookie = 0;
6252     vl_api_l2tpv3_set_tunnel_cookies_t *mp;
6253     f64 timeout;
6254
6255     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6256         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6257             sw_if_index_set = 1;
6258         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6259             sw_if_index_set = 1;
6260         else if (unformat (i, "new_local_cookie %lld", &new_local_cookie))
6261             ;
6262         else if (unformat (i, "new_remote_cookie %lld", &new_remote_cookie))
6263             ;
6264         else
6265             break;
6266     }
6267
6268     if (sw_if_index_set == 0) {
6269         errmsg ("missing interface name or sw_if_index\n");
6270         return -99;
6271     }
6272
6273     M(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies);
6274
6275     mp->sw_if_index = ntohl(sw_if_index);
6276     mp->new_local_cookie = clib_host_to_net_u64 (new_local_cookie);
6277     mp->new_remote_cookie = clib_host_to_net_u64 (new_remote_cookie);
6278
6279     S; W;
6280     /* NOTREACHED */
6281     return 0;
6282 }
6283
6284 static int api_l2tpv3_interface_enable_disable (vat_main_t * vam)
6285 {
6286     unformat_input_t * i = vam->input;
6287     vl_api_l2tpv3_interface_enable_disable_t *mp;
6288     f64 timeout;
6289     u32 sw_if_index;
6290     u8  sw_if_index_set = 0;
6291     u8  enable_disable = 1;
6292
6293     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6294         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6295             sw_if_index_set = 1;
6296         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6297             sw_if_index_set = 1;
6298         else if (unformat (i, "enable"))
6299             enable_disable = 1;
6300         else if (unformat (i, "disable"))
6301             enable_disable = 0;
6302         else
6303             break;
6304     }
6305
6306     if (sw_if_index_set == 0) {
6307         errmsg ("missing interface name or sw_if_index\n");
6308         return -99;
6309     }
6310     
6311     M(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable);
6312
6313     mp->sw_if_index = ntohl(sw_if_index);
6314     mp->enable_disable = enable_disable;
6315
6316     S; W;
6317     /* NOTREACHED */
6318     return 0;
6319 }
6320
6321 static int api_l2tpv3_set_lookup_key (vat_main_t * vam)
6322 {
6323     unformat_input_t * i = vam->input;
6324     vl_api_l2tpv3_set_lookup_key_t * mp;
6325     f64 timeout;
6326     u8 key = ~0;
6327
6328     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6329         if (unformat (i, "lookup_v6_src"))
6330             key = L2T_LOOKUP_SRC_ADDRESS;
6331         else if (unformat (i, "lookup_v6_dst"))
6332             key = L2T_LOOKUP_DST_ADDRESS;
6333         else if (unformat (i, "lookup_session_id"))
6334             key = L2T_LOOKUP_SESSION_ID;
6335         else
6336             break;
6337     }
6338
6339     if (key == ~0) {
6340         errmsg ("l2tp session lookup key unset\n");
6341         return -99;
6342     }
6343     
6344     M(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key);
6345
6346     mp->key = key;
6347
6348     S; W;
6349     /* NOTREACHED */
6350     return 0;
6351 }
6352
6353 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler
6354 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
6355 {
6356     vat_main_t * vam = &vat_main;
6357
6358     fformat(vam->ofp,  "* %U (our) %U (client) (sw_if_index %d)\n",
6359               format_ip6_address, mp->our_address,
6360               format_ip6_address, mp->client_address,
6361               clib_net_to_host_u32(mp->sw_if_index));
6362
6363     fformat (vam->ofp, "   local cookies %016llx %016llx remote cookie %016llx\n",
6364               clib_net_to_host_u64 (mp->local_cookie[0]),
6365               clib_net_to_host_u64 (mp->local_cookie[1]),
6366               clib_net_to_host_u64 (mp->remote_cookie));
6367
6368     fformat (vam->ofp, "   local session-id %d remote session-id %d\n",
6369               clib_net_to_host_u32 (mp->local_session_id),
6370               clib_net_to_host_u32 (mp->remote_session_id));
6371
6372     fformat (vam->ofp, "   l2 specific sublayer %s\n\n",
6373               mp->l2_sublayer_present ? "preset" : "absent");
6374
6375 }
6376
6377 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler_json
6378 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
6379 {
6380     vat_main_t * vam = &vat_main;
6381     vat_json_node_t *node = NULL;
6382     struct in6_addr addr;
6383
6384     if (VAT_JSON_ARRAY != vam->json_tree.type) {
6385         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
6386         vat_json_init_array(&vam->json_tree);
6387     }
6388     node = vat_json_array_add(&vam->json_tree);
6389
6390     vat_json_init_object(node);
6391
6392     memcpy(&addr, mp->our_address, sizeof(addr));
6393     vat_json_object_add_ip6(node, "our_address", addr);
6394     memcpy(&addr, mp->client_address, sizeof(addr));
6395     vat_json_object_add_ip6(node, "client_address", addr);
6396
6397     vat_json_node_t * lc = vat_json_object_add(node, "local_cookie");
6398     vat_json_init_array(lc);
6399     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[0]));
6400     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[1]));
6401     vat_json_object_add_uint(node, "remote_cookie", clib_net_to_host_u64(mp->remote_cookie));
6402
6403     printf("local id: %u", clib_net_to_host_u32(mp->local_session_id));
6404     vat_json_object_add_uint(node, "local_session_id", clib_net_to_host_u32(mp->local_session_id));
6405     vat_json_object_add_uint(node, "remote_session_id", clib_net_to_host_u32(mp->remote_session_id));
6406     vat_json_object_add_string_copy(node, "l2_sublayer", mp->l2_sublayer_present ?
6407             (u8*)"present" : (u8*)"absent");
6408 }
6409
6410 static int api_sw_if_l2tpv3_tunnel_dump (vat_main_t * vam)
6411 {
6412     vl_api_sw_if_l2tpv3_tunnel_dump_t *mp;
6413     f64 timeout;
6414
6415     /* Get list of l2tpv3-tunnel interfaces */
6416     M(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump);
6417     S;
6418
6419     /* Use a control ping for synchronization */
6420     {
6421         vl_api_control_ping_t * mp;
6422         M(CONTROL_PING, control_ping);
6423         S;
6424     }
6425     W;
6426 }
6427
6428
6429 static void vl_api_sw_interface_tap_details_t_handler
6430 (vl_api_sw_interface_tap_details_t * mp)
6431 {
6432     vat_main_t * vam = &vat_main;
6433
6434     fformat(vam->ofp,  "%-16s %d\n",
6435               mp->dev_name,
6436               clib_net_to_host_u32(mp->sw_if_index));
6437 }
6438
6439 static void vl_api_sw_interface_tap_details_t_handler_json
6440 (vl_api_sw_interface_tap_details_t * mp)
6441 {
6442     vat_main_t * vam = &vat_main;
6443     vat_json_node_t *node = NULL;
6444
6445     if (VAT_JSON_ARRAY != vam->json_tree.type) {
6446         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
6447         vat_json_init_array(&vam->json_tree);
6448     }
6449     node = vat_json_array_add(&vam->json_tree);
6450
6451     vat_json_init_object(node);
6452     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
6453     vat_json_object_add_string_copy(node, "dev_name", mp->dev_name);
6454 }
6455
6456 static int api_sw_interface_tap_dump (vat_main_t * vam)
6457 {
6458     vl_api_sw_interface_tap_dump_t *mp;
6459     f64 timeout;
6460
6461     fformat(vam->ofp,  "\n%-16s %s\n", "dev_name", "sw_if_index");
6462     /* Get list of tap interfaces */
6463     M(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump);
6464     S;
6465
6466     /* Use a control ping for synchronization */
6467     {
6468         vl_api_control_ping_t * mp;
6469         M(CONTROL_PING, control_ping);
6470         S;
6471     }
6472     W;
6473 }
6474
6475 static uword unformat_vxlan_decap_next 
6476 (unformat_input_t * input, va_list * args)
6477 {
6478   u32 * result = va_arg (*args, u32 *);
6479   u32 tmp;
6480   
6481   if (unformat (input, "drop"))
6482     *result = VXLAN_INPUT_NEXT_DROP;
6483   else if (unformat (input, "ip4"))
6484     *result = VXLAN_INPUT_NEXT_IP4_INPUT;
6485   else if (unformat (input, "ip6"))
6486     *result = VXLAN_INPUT_NEXT_IP6_INPUT;
6487   else if (unformat (input, "l2"))
6488     *result = VXLAN_INPUT_NEXT_L2_INPUT;
6489   else if (unformat (input, "%d", &tmp))
6490     *result = tmp;
6491   else
6492     return 0;
6493   return 1;
6494 }
6495
6496 static int api_vxlan_add_del_tunnel (vat_main_t * vam)
6497 {
6498     unformat_input_t * line_input = vam->input;
6499     vl_api_vxlan_add_del_tunnel_t *mp;
6500     f64 timeout;
6501     ip4_address_t src, dst;
6502     u8 is_add = 1;
6503     u8 src_set = 0;
6504     u8 dst_set = 0;
6505     u32 encap_vrf_id = 0;
6506     u32 decap_next_index = ~0;
6507     u32 vni = 0;
6508
6509     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
6510         if (unformat (line_input, "del"))
6511             is_add = 0;
6512         else if (unformat (line_input, "src %U", 
6513                            unformat_ip4_address, &src))
6514             src_set = 1;
6515         else if (unformat (line_input, "dst %U",
6516                            unformat_ip4_address, &dst))
6517             dst_set = 1;
6518         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
6519             ;
6520         else if (unformat (line_input, "decap-next %U", 
6521                            unformat_vxlan_decap_next, &decap_next_index))
6522             ;
6523         else if (unformat (line_input, "vni %d", &vni))
6524             ;
6525         else {
6526             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
6527             return -99;
6528         }
6529     }
6530
6531     if (src_set == 0) {
6532         errmsg ("tunnel src address not specified\n");
6533         return -99;
6534     }
6535     if (dst_set == 0) {
6536         errmsg ("tunnel dst address not specified\n");
6537         return -99;
6538     }
6539
6540     if ((vni == 0) || (vni>>24)) {
6541         errmsg ("vni not specified or out of range\n");
6542         return -99;
6543     }
6544
6545     M (VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel);
6546     
6547     mp->src_address = src.as_u32;
6548     mp->dst_address = dst.as_u32;
6549     mp->encap_vrf_id = ntohl(encap_vrf_id);
6550     mp->decap_next_index = ntohl(decap_next_index);
6551     mp->vni = ntohl(vni);
6552     mp->is_add = is_add;
6553
6554     S; W;
6555     /* NOTREACHED */
6556     return 0;
6557 }
6558
6559 static void vl_api_vxlan_tunnel_details_t_handler
6560 (vl_api_vxlan_tunnel_details_t * mp)
6561 {
6562     vat_main_t * vam = &vat_main;
6563
6564     fformat(vam->ofp, "%11d%13U%13U%14d%18d%13d\n",
6565             ntohl(mp->sw_if_index),
6566             format_ip4_address, &mp->src_address,
6567             format_ip4_address, &mp->dst_address,
6568             ntohl(mp->encap_vrf_id),
6569             ntohl(mp->decap_next_index),
6570             ntohl(mp->vni));
6571 }
6572
6573 static void vl_api_vxlan_tunnel_details_t_handler_json
6574 (vl_api_vxlan_tunnel_details_t * mp)
6575 {
6576     vat_main_t * vam = &vat_main;
6577     vat_json_node_t *node = NULL;
6578     struct in_addr ip4;
6579
6580     if (VAT_JSON_ARRAY != vam->json_tree.type) {
6581         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
6582         vat_json_init_array(&vam->json_tree);
6583     }
6584     node = vat_json_array_add(&vam->json_tree);
6585
6586     vat_json_init_object(node);
6587     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
6588     memcpy(&ip4, &mp->src_address, sizeof(ip4));
6589     vat_json_object_add_ip4(node, "src_address", ip4);
6590     memcpy(&ip4, &mp->dst_address, sizeof(ip4));
6591     vat_json_object_add_ip4(node, "dst_address", ip4);
6592     vat_json_object_add_uint(node, "encap_vrf_id", ntohl(mp->encap_vrf_id));
6593     vat_json_object_add_uint(node, "decap_next_index", ntohl(mp->decap_next_index));
6594     vat_json_object_add_uint(node, "vni", ntohl(mp->vni));
6595 }
6596
6597 static int api_vxlan_tunnel_dump (vat_main_t * vam)
6598 {
6599     unformat_input_t * i = vam->input;
6600     vl_api_vxlan_tunnel_dump_t *mp;
6601     f64 timeout;
6602     u32 sw_if_index;
6603     u8 sw_if_index_set = 0;
6604
6605     /* Parse args required to build the message */
6606     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6607         if (unformat (i, "sw_if_index %d", &sw_if_index))
6608             sw_if_index_set = 1;
6609         else
6610             break;
6611     }
6612
6613     if (sw_if_index_set == 0) {
6614         sw_if_index = ~0;
6615     }
6616
6617     if (!vam->json_output) {
6618         fformat(vam->ofp, "%11s%13s%13s%14s%18s%13s\n",
6619                 "sw_if_index", "src_address", "dst_address",
6620                 "encap_vrf_id", "decap_next_index", "vni");
6621     }
6622
6623     /* Get list of l2tpv3-tunnel interfaces */
6624     M(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump);
6625
6626     mp->sw_if_index = htonl(sw_if_index);
6627
6628     S;
6629
6630     /* Use a control ping for synchronization */
6631     {
6632         vl_api_control_ping_t * mp;
6633         M(CONTROL_PING, control_ping);
6634         S;
6635     }
6636     W;
6637 }
6638
6639 static int api_l2_fib_clear_table (vat_main_t * vam)
6640 {
6641 //  unformat_input_t * i = vam->input;
6642     vl_api_l2_fib_clear_table_t *mp;
6643     f64 timeout;
6644
6645     M(L2_FIB_CLEAR_TABLE, l2_fib_clear_table);
6646
6647     S; W;
6648     /* NOTREACHED */
6649     return 0;
6650 }
6651
6652 static int api_l2_interface_efp_filter (vat_main_t * vam)
6653 {
6654     unformat_input_t * i = vam->input;
6655     vl_api_l2_interface_efp_filter_t *mp;
6656     f64 timeout;
6657     u32 sw_if_index;
6658     u8 enable = 1;
6659     u8 sw_if_index_set = 0;
6660
6661     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6662         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6663             sw_if_index_set = 1;
6664         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6665             sw_if_index_set = 1;
6666         else if (unformat (i, "enable"))
6667             enable = 1;
6668         else if (unformat (i, "disable"))
6669             enable = 0;
6670         else {
6671             clib_warning ("parse error '%U'", format_unformat_error, i);
6672             return -99;
6673         }
6674     }
6675     
6676     if (sw_if_index_set == 0) {
6677         errmsg ("missing sw_if_index\n");
6678         return -99;
6679     }
6680
6681     M(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter);
6682
6683     mp->sw_if_index = ntohl(sw_if_index);
6684     mp->enable_disable = enable;
6685
6686     S; W;
6687     /* NOTREACHED */
6688     return 0;
6689 }
6690
6691 #define foreach_vtr_op                          \
6692 _("disable",  L2_VTR_DISABLED)                  \
6693 _("push-1",  L2_VTR_PUSH_1)                     \
6694 _("push-2",  L2_VTR_PUSH_2)                     \
6695 _("pop-1",  L2_VTR_POP_1)                       \
6696 _("pop-2",  L2_VTR_POP_2)                       \
6697 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
6698 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
6699 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
6700 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
6701
6702 static int api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
6703 {
6704     unformat_input_t * i = vam->input;
6705     vl_api_l2_interface_vlan_tag_rewrite_t *mp;
6706     f64 timeout;
6707     u32 sw_if_index;
6708     u8 sw_if_index_set = 0;
6709     u8 vtr_op_set = 0;
6710     u32 vtr_op = 0;
6711     u32 push_dot1q = 1;
6712     u32 tag1 = ~0;
6713     u32 tag2 = ~0;
6714
6715     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6716         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6717             sw_if_index_set = 1;
6718         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6719             sw_if_index_set = 1;
6720         else if (unformat (i, "vtr_op %d", &vtr_op))
6721             vtr_op_set = 1;
6722 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
6723         foreach_vtr_op
6724 #undef _
6725         
6726         else if (unformat (i, "push_dot1q %d", &push_dot1q))
6727             ;
6728         else if (unformat (i, "tag1 %d", &tag1))
6729             ;
6730         else if (unformat (i, "tag2 %d", &tag2))
6731             ;
6732         else {
6733             clib_warning ("parse error '%U'", format_unformat_error, i);
6734             return -99;
6735         }
6736     }
6737     
6738     if ((sw_if_index_set == 0)||(vtr_op_set == 0)) {
6739         errmsg ("missing vtr operation or sw_if_index\n");
6740         return -99;
6741     }
6742
6743     M(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)
6744
6745     mp->sw_if_index = ntohl(sw_if_index);
6746     mp->vtr_op = ntohl(vtr_op);
6747     mp->push_dot1q = ntohl(push_dot1q);
6748     mp->tag1 = ntohl(tag1);
6749     mp->tag2 = ntohl(tag2);
6750
6751     S; W;
6752     /* NOTREACHED */
6753     return 0;
6754 }
6755
6756 static int api_create_vhost_user_if (vat_main_t * vam)
6757 {
6758     unformat_input_t * i = vam->input;
6759     vl_api_create_vhost_user_if_t *mp;
6760     f64 timeout;
6761     u8 * file_name;
6762     u8 is_server = 0;
6763     u8 file_name_set = 0;
6764     u32 custom_dev_instance = ~0;
6765
6766     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6767       if (unformat (i, "socket %s", &file_name)) {
6768         file_name_set = 1;
6769       }
6770       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
6771         ;
6772       else if (unformat (i, "server"))
6773         is_server = 1;
6774       else
6775         break;
6776     }
6777
6778     if (file_name_set == 0) {
6779       errmsg ("missing socket file name\n");
6780       return -99;
6781     }
6782
6783     if (vec_len (file_name) > 255) {
6784       errmsg ("socket file name too long\n");
6785       return -99;
6786     }
6787     vec_add1 (file_name, 0);
6788
6789     M(CREATE_VHOST_USER_IF, create_vhost_user_if);
6790
6791     mp->is_server = is_server;
6792     memcpy(mp->sock_filename, file_name, vec_len(file_name));
6793     vec_free(file_name);
6794     if (custom_dev_instance != ~0) {
6795         mp->renumber = 1;
6796         mp->custom_dev_instance = ntohl(custom_dev_instance);
6797     }
6798
6799     S; W;
6800     /* NOTREACHED */
6801     return 0;
6802 }
6803
6804 static int api_modify_vhost_user_if (vat_main_t * vam)
6805 {
6806     unformat_input_t * i = vam->input;
6807     vl_api_modify_vhost_user_if_t *mp;
6808     f64 timeout;
6809     u8 * file_name;
6810     u8 is_server = 0;
6811     u8 file_name_set = 0;
6812     u32 custom_dev_instance = ~0;
6813     u8 sw_if_index_set = 0;
6814     u32 sw_if_index = (u32)~0;
6815
6816     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6817       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6818           sw_if_index_set = 1;
6819       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6820           sw_if_index_set = 1;
6821       else if (unformat (i, "socket %s", &file_name)) {
6822         file_name_set = 1;
6823       }
6824       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
6825         ;
6826       else if (unformat (i, "server"))
6827         is_server = 1;
6828       else
6829         break;
6830     }
6831
6832     if (sw_if_index_set == 0) {
6833        errmsg ("missing sw_if_index or interface name\n");
6834        return -99;
6835     }
6836
6837     if (file_name_set == 0) {
6838       errmsg ("missing socket file name\n");
6839       return -99;
6840     }
6841
6842     if (vec_len (file_name) > 255) {
6843       errmsg ("socket file name too long\n");
6844       return -99;
6845     }
6846     vec_add1 (file_name, 0);
6847
6848     M(MODIFY_VHOST_USER_IF, modify_vhost_user_if);
6849
6850     mp->sw_if_index = ntohl(sw_if_index);
6851     mp->is_server = is_server;
6852     memcpy(mp->sock_filename, file_name, vec_len(file_name));
6853     vec_free(file_name);
6854     if (custom_dev_instance != ~0) {
6855         mp->renumber = 1;
6856         mp->custom_dev_instance = ntohl(custom_dev_instance);
6857     }
6858
6859     S; W;
6860     /* NOTREACHED */
6861     return 0;
6862 }
6863
6864 static int api_delete_vhost_user_if (vat_main_t * vam)
6865 {
6866     unformat_input_t * i = vam->input;
6867     vl_api_delete_vhost_user_if_t *mp;
6868     f64 timeout;
6869     u32 sw_if_index = ~0;
6870     u8 sw_if_index_set = 0;
6871
6872     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6873       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6874           sw_if_index_set = 1;
6875       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6876           sw_if_index_set = 1;
6877       else
6878         break;
6879     }
6880
6881     if (sw_if_index_set == 0) {
6882        errmsg ("missing sw_if_index or interface name\n");
6883        return -99;
6884     }
6885
6886
6887     M(DELETE_VHOST_USER_IF, delete_vhost_user_if);
6888
6889     mp->sw_if_index = ntohl(sw_if_index);
6890
6891     S; W;
6892     /* NOTREACHED */
6893     return 0;
6894 }
6895
6896 static void vl_api_sw_interface_vhost_user_details_t_handler
6897 (vl_api_sw_interface_vhost_user_details_t * mp)
6898 {
6899     vat_main_t * vam = &vat_main;
6900
6901     fformat(vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s\n",
6902             (char *)mp->interface_name,
6903             ntohl(mp->sw_if_index), ntohl(mp->virtio_net_hdr_sz),
6904             clib_net_to_host_u64(mp->features), mp->is_server,
6905             ntohl(mp->num_regions), (char *)mp->sock_filename);
6906     fformat(vam->ofp, "    Status: '%s'\n", strerror(ntohl(mp->sock_errno)));
6907 }
6908
6909 static void vl_api_sw_interface_vhost_user_details_t_handler_json
6910 (vl_api_sw_interface_vhost_user_details_t * mp)
6911 {
6912     vat_main_t * vam = &vat_main;
6913     vat_json_node_t *node = NULL;
6914
6915     if (VAT_JSON_ARRAY != vam->json_tree.type) {
6916         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
6917         vat_json_init_array(&vam->json_tree);
6918     }
6919     node = vat_json_array_add(&vam->json_tree);
6920
6921     vat_json_init_object(node);
6922     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
6923     vat_json_object_add_string_copy(node, "interface_name", mp->interface_name);
6924     vat_json_object_add_uint(node, "virtio_net_hdr_sz", ntohl(mp->virtio_net_hdr_sz));
6925     vat_json_object_add_uint(node, "features", clib_net_to_host_u64(mp->features));
6926     vat_json_object_add_uint(node, "is_server", mp->is_server);
6927     vat_json_object_add_string_copy(node, "sock_filename", mp->sock_filename);
6928     vat_json_object_add_uint(node, "num_regions", ntohl(mp->num_regions));
6929     vat_json_object_add_uint(node, "sock_errno", ntohl(mp->sock_errno));
6930 }
6931
6932 static int api_sw_interface_vhost_user_dump (vat_main_t * vam)
6933 {
6934     vl_api_sw_interface_vhost_user_dump_t *mp;
6935     f64 timeout;
6936     fformat(vam->ofp, "Interface name           idx hdr_sz features server regions filename\n");
6937
6938     /* Get list of vhost-user interfaces */
6939     M(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump);
6940     S;
6941
6942     /* Use a control ping for synchronization */
6943     {
6944         vl_api_control_ping_t * mp;
6945         M(CONTROL_PING, control_ping);
6946         S;
6947     }
6948     W;
6949 }
6950
6951 static int api_show_version (vat_main_t * vam)
6952 {
6953     vl_api_show_version_t *mp;
6954     f64 timeout;
6955
6956     M(SHOW_VERSION, show_version);
6957
6958     S; W;
6959     /* NOTREACHED */
6960     return 0;
6961 }
6962
6963 static uword unformat_nsh_gre_decap_next 
6964 (unformat_input_t * input, va_list * args)
6965 {
6966   u32 * result = va_arg (*args, u32 *);
6967   u32 tmp;
6968   
6969   if (unformat (input, "drop"))
6970     *result = NSH_INPUT_NEXT_DROP;
6971   else if (unformat (input, "ip4"))
6972     *result = NSH_INPUT_NEXT_IP4_INPUT;
6973   else if (unformat (input, "ip6"))
6974     *result = NSH_INPUT_NEXT_IP6_INPUT;
6975   else if (unformat (input, "ethernet"))
6976     *result = NSH_INPUT_NEXT_ETHERNET_INPUT;
6977   else if (unformat (input, "%d", &tmp))
6978     *result = tmp;
6979   else
6980     return 0;
6981   return 1;
6982 }
6983
6984 static int api_nsh_gre_add_del_tunnel (vat_main_t * vam)
6985 {
6986     unformat_input_t * line_input = vam->input;
6987     vl_api_nsh_gre_add_del_tunnel_t *mp;
6988     f64 timeout;
6989     ip4_address_t src, dst;
6990     u8 is_add = 1;
6991     u8 src_set = 0;
6992     u8 dst_set = 0;
6993     u32 encap_vrf_id = 0;
6994     u32 decap_vrf_id = 0;
6995     u8 ver_o_c = 0;
6996     u8 md_type = 0;
6997     u8 next_protocol = 1; /* ip4 */
6998     u32 spi;
6999     u8 spi_set = 0;
7000     u32 si;
7001     u8 si_set = 0;
7002     u32 spi_si;
7003     u32 c1 = 0;
7004     u32 c2 = 0;
7005     u32 c3 = 0;
7006     u32 c4 = 0;
7007     u32 *tlvs = 0;
7008     u32 decap_next_index = NSH_INPUT_NEXT_IP4_INPUT;
7009     u32 tmp;
7010     int i;
7011
7012     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7013         if (unformat (line_input, "del"))
7014             is_add = 0;
7015         else if (unformat (line_input, "src %U", 
7016                            unformat_ip4_address, &src))
7017             src_set = 1;
7018         else if (unformat (line_input, "dst %U",
7019                            unformat_ip4_address, &dst))
7020             dst_set = 1;
7021         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7022             ;
7023         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7024             ;
7025         else if (unformat (line_input, "decap-next %U", 
7026                            unformat_nsh_gre_decap_next, &decap_next_index))
7027             ;
7028         else if (unformat (line_input, "version %d", &tmp))
7029             ver_o_c |= (tmp & 3) << 6;
7030         else if (unformat (line_input, "o-bit %d", &tmp))
7031             ver_o_c |= (tmp & 1) << 5;
7032         else if (unformat (line_input, "c-bit %d", &tmp))
7033             ver_o_c |= (tmp & 1) << 4;
7034         else if (unformat (line_input, "md-type %d", &tmp))
7035             md_type = tmp;
7036         else if (unformat(line_input, "next-ip4"))
7037             next_protocol = 1;
7038         else if (unformat(line_input, "next-ip6"))
7039             next_protocol = 2;
7040         else if (unformat(line_input, "next-ethernet"))
7041             next_protocol = 3;
7042         else if (unformat (line_input, "c1 %d", &c1))
7043             ;
7044         else if (unformat (line_input, "c2 %d", &c2))
7045             ;
7046         else if (unformat (line_input, "c3 %d", &c3))
7047             ;
7048         else if (unformat (line_input, "c4 %d", &c4))
7049             ;
7050         else if (unformat (line_input, "spi %d", &spi))
7051             spi_set = 1;
7052         else if (unformat (line_input, "si %d", &si))
7053             si_set = 1;
7054         else if (unformat (line_input, "tlv %x"))
7055             vec_add1 (tlvs, tmp);
7056         else {
7057             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7058             return -99;
7059         }
7060     }
7061
7062     if (src_set == 0) {
7063         errmsg ("tunnel src address not specified\n");
7064         return -99;
7065     }
7066     if (dst_set == 0) {
7067         errmsg ("tunnel dst address not specified\n");
7068         return -99;
7069     }
7070
7071     if (spi_set == 0) {
7072         errmsg ("spi not specified\n");
7073         return -99;
7074     }
7075
7076     if (si_set == 0) {
7077         errmsg ("si not specified\n");
7078         return -99;
7079     }
7080
7081     M2 (NSH_GRE_ADD_DEL_TUNNEL, nsh_gre_add_del_tunnel,
7082         sizeof(u32) * vec_len (tlvs));
7083     
7084     spi_si = (spi<<8) | si;
7085
7086     mp->src = src.as_u32;
7087     mp->dst = dst.as_u32;
7088     mp->encap_vrf_id = ntohl(encap_vrf_id);
7089     mp->decap_vrf_id = ntohl(decap_vrf_id);
7090     mp->decap_next_index = ntohl(decap_next_index);
7091     mp->tlv_len_in_words = vec_len (tlvs);
7092     mp->is_add = is_add;
7093     mp->ver_o_c = ver_o_c;
7094     mp->length = 6 + vec_len(tlvs);
7095     mp->md_type = md_type;
7096     mp->next_protocol = next_protocol;
7097     mp->spi_si = ntohl(spi_si);
7098     mp->c1 = ntohl(c1);
7099     mp->c2 = ntohl(c2);
7100     mp->c3 = ntohl(c3);
7101     mp->c4 = ntohl(c4);
7102     
7103     for (i = 0; i < vec_len(tlvs); i++)
7104         mp->tlvs[i] = ntohl(tlvs[i]);
7105
7106     vec_free (tlvs);
7107
7108     S; W;
7109     /* NOTREACHED */
7110     return 0;
7111 }
7112
7113 static uword unformat_nsh_vxlan_gpe_decap_next 
7114 (unformat_input_t * input, va_list * args)
7115 {
7116   u32 * result = va_arg (*args, u32 *);
7117   u32 tmp;
7118   
7119   if (unformat (input, "drop"))
7120     *result = NSH_VXLAN_GPE_INPUT_NEXT_DROP;
7121   else if (unformat (input, "ip4"))
7122     *result = NSH_VXLAN_GPE_INPUT_NEXT_IP4_INPUT;
7123   else if (unformat (input, "ip6"))
7124     *result = NSH_VXLAN_GPE_INPUT_NEXT_IP6_INPUT;
7125   else if (unformat (input, "ethernet"))
7126     *result = NSH_VXLAN_GPE_INPUT_NEXT_ETHERNET_INPUT;
7127   else if (unformat (input, "nsh-vxlan-gpe"))
7128       *result = NSH_VXLAN_GPE_INPUT_NEXT_ETHERNET_INPUT;
7129   else if (unformat (input, "%d", &tmp))
7130     *result = tmp;
7131   else
7132     return 0;
7133   return 1;
7134 }
7135
7136 static int api_nsh_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
7137 {
7138     unformat_input_t * line_input = vam->input;
7139     vl_api_nsh_vxlan_gpe_add_del_tunnel_t *mp;
7140     f64 timeout;
7141     ip4_address_t src, dst;
7142     u8 is_add = 1;
7143     u8 src_set = 0;
7144     u8 dst_set = 0;
7145     u32 encap_vrf_id = 0;
7146     u32 decap_vrf_id = 0;
7147     u8 ver_o_c = 0;
7148     u8 md_type = 0;
7149     u8 next_protocol = 1; /* ip4 */
7150     u32 spi;
7151     u8 spi_set = 0;
7152     u32 si;
7153     u8 si_set = 0;
7154     u32 spi_si;
7155     u32 c1 = 0;
7156     u32 c2 = 0;
7157     u32 c3 = 0;
7158     u32 c4 = 0;
7159     u32 *tlvs = 0;
7160     u32 decap_next_index = NSH_INPUT_NEXT_IP4_INPUT;
7161     u32 vni;
7162     u8 vni_set = 0;
7163     u32 tmp;
7164     int i;
7165
7166     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7167         if (unformat (line_input, "del"))
7168             is_add = 0;
7169         else if (unformat (line_input, "src %U", 
7170                            unformat_ip4_address, &src))
7171             src_set = 1;
7172         else if (unformat (line_input, "dst %U",
7173                            unformat_ip4_address, &dst))
7174             dst_set = 1;
7175         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7176             ;
7177         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7178             ;
7179         else if (unformat (line_input, "decap-next %U", 
7180                            unformat_nsh_vxlan_gpe_decap_next, 
7181                            &decap_next_index))
7182             ;
7183         else if (unformat (line_input, "vni %d", &vni))
7184             vni_set = 1;
7185         else if (unformat (line_input, "version %d", &tmp))
7186             ver_o_c |= (tmp & 3) << 6;
7187         else if (unformat (line_input, "o-bit %d", &tmp))
7188             ver_o_c |= (tmp & 1) << 5;
7189         else if (unformat (line_input, "c-bit %d", &tmp))
7190             ver_o_c |= (tmp & 1) << 4;
7191         else if (unformat (line_input, "md-type %d", &tmp))
7192             md_type = tmp;
7193         else if (unformat(line_input, "next-ip4"))
7194             next_protocol = 1;
7195         else if (unformat(line_input, "next-ip6"))
7196             next_protocol = 2;
7197         else if (unformat(line_input, "next-ethernet"))
7198             next_protocol = 3;
7199         else if (unformat (line_input, "c1 %d", &c1))
7200             ;
7201         else if (unformat (line_input, "c2 %d", &c2))
7202             ;
7203         else if (unformat (line_input, "c3 %d", &c3))
7204             ;
7205         else if (unformat (line_input, "c4 %d", &c4))
7206             ;
7207         else if (unformat (line_input, "spi %d", &spi))
7208             spi_set = 1;
7209         else if (unformat (line_input, "si %d", &si))
7210             si_set = 1;
7211         else if (unformat (line_input, "tlv %x"))
7212             vec_add1 (tlvs, tmp);
7213         else {
7214             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7215             return -99;
7216         }
7217     }
7218
7219     if (src_set == 0) {
7220         errmsg ("tunnel src address not specified\n");
7221         return -99;
7222     }
7223     if (dst_set == 0) {
7224         errmsg ("tunnel dst address not specified\n");
7225         return -99;
7226     }
7227
7228     if (spi_set == 0) {
7229         errmsg ("spi not specified\n");
7230         return -99;
7231     }
7232
7233     if (si_set == 0) {
7234         errmsg ("si not specified\n");
7235         return -99;
7236     }
7237     if (vni_set == 0) {
7238         errmsg ("vni not specified\n");
7239         return -99;
7240     }
7241
7242     M2 (NSH_VXLAN_GPE_ADD_DEL_TUNNEL, nsh_vxlan_gpe_add_del_tunnel,
7243         sizeof(u32) * vec_len (tlvs));
7244     
7245     spi_si = (spi<<8) | si;
7246
7247     mp->src = src.as_u32;
7248     mp->dst = dst.as_u32;
7249     mp->encap_vrf_id = ntohl(encap_vrf_id);
7250     mp->decap_vrf_id = ntohl(decap_vrf_id);
7251     mp->decap_next_index = ntohl(decap_next_index);
7252     mp->tlv_len_in_words = vec_len (tlvs);
7253     mp->vni = ntohl(vni);
7254     mp->is_add = is_add;
7255     mp->ver_o_c = ver_o_c;
7256     mp->length = 6 + vec_len(tlvs);
7257     mp->md_type = md_type;
7258     mp->next_protocol = next_protocol;
7259     mp->spi_si = ntohl(spi_si);
7260     mp->c1 = ntohl(c1);
7261     mp->c2 = ntohl(c2);
7262     mp->c3 = ntohl(c3);
7263     mp->c4 = ntohl(c4);
7264     
7265     for (i = 0; i < vec_len(tlvs); i++)
7266         mp->tlvs[i] = ntohl(tlvs[i]);
7267
7268     vec_free (tlvs);
7269
7270     S; W;
7271     /* NOTREACHED */
7272     return 0;
7273 }
7274
7275 static uword unformat_lisp_gpe_decap_next (unformat_input_t * input, 
7276                                                va_list * args)
7277 {
7278     u32 * result = va_arg (*args, u32 *);
7279     u32 tmp;
7280   
7281     if (unformat (input, "drop"))
7282         *result = LISP_GPE_INPUT_NEXT_DROP;
7283     else if (unformat (input, "ip4"))
7284         *result = LISP_GPE_INPUT_NEXT_IP4_INPUT;
7285     else if (unformat (input, "ip6"))
7286         *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
7287     else if (unformat (input, "ethernet"))
7288         *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
7289     else if (unformat (input, "lisp-gpe"))
7290         *result = LISP_GPE_INPUT_NEXT_LISP_GPE_ENCAP;
7291     else if (unformat (input, "%d", &tmp))
7292         *result = tmp;
7293     else
7294         return 0;
7295     return 1;
7296 }
7297
7298 static int
7299 api_lisp_gpe_add_del_tunnel (vat_main_t * vam)
7300 {
7301     unformat_input_t * line_input = vam->input;
7302     vl_api_lisp_gpe_add_del_tunnel_t *mp;
7303     f64 timeout;
7304     ip4_address_t src, dst;
7305     u8 is_add = 1;
7306     u8 src_set = 0;
7307     u8 dst_set = 0;
7308     u32 encap_vrf_id = 0;
7309     u32 decap_vrf_id = 0;
7310     u8 next_protocol = LISP_GPE_NEXT_PROTOCOL_IP4;
7311     u32 decap_next_index = LISP_GPE_INPUT_NEXT_IP4_INPUT;
7312     u8 flags = LISP_GPE_FLAGS_P;
7313     u8 ver_res = 0;
7314     u8 res = 0;
7315     u32 iid = 0;
7316     u8 iid_set = 0;
7317     u32 tmp;
7318   
7319     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7320         if (unformat (line_input, "del"))
7321             is_add = 0;
7322         else if (unformat (line_input, "src %U", 
7323                            unformat_ip4_address, &src))
7324             src_set = 1;
7325         else if (unformat (line_input, "dst %U",
7326                            unformat_ip4_address, &dst))
7327             dst_set = 1;
7328         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7329             ;
7330         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7331             ;
7332         else if (unformat (line_input, "decap-next %U", 
7333                            unformat_lisp_gpe_decap_next, 
7334                            &decap_next_index))
7335             ;
7336         else if (unformat(line_input, "next-ip4"))
7337             next_protocol = 1;
7338         else if (unformat(line_input, "next-ip6"))
7339             next_protocol = 2;
7340         else if (unformat(line_input, "next-ethernet"))
7341             next_protocol = 3;
7342         else if (unformat(line_input, "next-nsh"))
7343             next_protocol = 4;
7344         /* Allow the user to specify anything they want in the LISP hdr */
7345         else if (unformat (line_input, "ver_res %x", &tmp))
7346             ver_res = tmp;
7347         else if (unformat (line_input, "res %x", &tmp))
7348             res = tmp;
7349         else if (unformat (line_input, "flags %x", &tmp))
7350             flags = tmp;
7351         else if (unformat (line_input, "n-bit"))
7352             flags |= LISP_GPE_FLAGS_N;
7353         else if (unformat (line_input, "l-bit"))
7354             flags |= LISP_GPE_FLAGS_L;
7355         else if (unformat (line_input, "e-bit"))
7356             flags |= LISP_GPE_FLAGS_E;
7357         else if (unformat (line_input, "v-bit"))
7358             flags |= LISP_GPE_FLAGS_V;
7359         else if (unformat (line_input, "i-bit"))
7360             flags |= LISP_GPE_FLAGS_V;
7361         else if (unformat (line_input, "not-p-bit"))
7362             flags &= !LISP_GPE_FLAGS_P;
7363         else if (unformat (line_input, "p-bit"))
7364             flags |= LISP_GPE_FLAGS_P;
7365         else if (unformat (line_input, "o-bit"))
7366             flags |= LISP_GPE_FLAGS_O;
7367         else if (unformat (line_input, "iidx %x", &iid))
7368             iid_set = 1;
7369         else if (unformat (line_input, "iid %d", &iid))
7370             iid_set = 1;
7371         else {
7372             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7373             return -99;
7374         }
7375     }
7376
7377     if (src_set == 0) {
7378         errmsg ("tunnel src address not specified\n");
7379         return -99;
7380     }
7381     if (dst_set == 0) {
7382         errmsg ("tunnel dst address not specified\n");
7383         return -99;
7384     }
7385     if (iid_set == 0) {
7386         errmsg ("iid not specified\n");
7387         return -99;
7388     }
7389
7390     M(LISP_GPE_ADD_DEL_TUNNEL, lisp_gpe_add_del_tunnel);
7391
7392     mp->src = src.as_u32;
7393     mp->dst = dst.as_u32;
7394     mp->encap_vrf_id = ntohl(encap_vrf_id);
7395     mp->decap_vrf_id = ntohl(decap_vrf_id);
7396     mp->decap_next_index = ntohl(decap_next_index);
7397     mp->is_add = is_add;
7398     mp->flags = flags;
7399     mp->ver_res = ver_res;
7400     mp->res = res;
7401     mp->next_protocol = next_protocol;
7402     mp->iid = ntohl(iid);
7403
7404     S; W; 
7405
7406     /* NOTREACHED */
7407     return 0;
7408 }
7409
7410
7411 u8 * format_l2_fib_mac_address (u8 * s, va_list * args)
7412 {
7413   u8 * a = va_arg (*args, u8 *);
7414
7415   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
7416                  a[2], a[3], a[4], a[5], a[6], a[7]);
7417 }
7418
7419 static void vl_api_l2_fib_table_entry_t_handler
7420 (vl_api_l2_fib_table_entry_t * mp)
7421 {
7422     vat_main_t * vam = &vat_main;
7423
7424     fformat(vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
7425             "       %d       %d     %d\n",
7426             ntohl(mp->bd_id), format_l2_fib_mac_address, &mp->mac,
7427             ntohl(mp->sw_if_index), mp->static_mac, mp->filter_mac,
7428             mp->bvi_mac);
7429 }
7430
7431 static void vl_api_l2_fib_table_entry_t_handler_json
7432 (vl_api_l2_fib_table_entry_t * mp)
7433 {
7434     vat_main_t * vam = &vat_main;
7435     vat_json_node_t *node = NULL;
7436
7437     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7438         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7439         vat_json_init_array(&vam->json_tree);
7440     }
7441     node = vat_json_array_add(&vam->json_tree);
7442
7443     vat_json_init_object(node);
7444     vat_json_object_add_uint(node, "bd_id", ntohl(mp->bd_id));
7445     vat_json_object_add_uint(node, "mac", clib_net_to_host_u64(mp->mac));
7446     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7447     vat_json_object_add_uint(node, "static_mac", mp->static_mac);
7448     vat_json_object_add_uint(node, "filter_mac", mp->filter_mac);
7449     vat_json_object_add_uint(node, "bvi_mac", mp->bvi_mac);
7450 }
7451
7452 static int api_l2_fib_table_dump (vat_main_t * vam)
7453 {
7454     unformat_input_t * i = vam->input;
7455     vl_api_l2_fib_table_dump_t *mp;
7456     f64 timeout;
7457     u32 bd_id;
7458     u8 bd_id_set = 0;
7459
7460     /* Parse args required to build the message */
7461     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7462         if (unformat (i, "bd_id %d", &bd_id))
7463             bd_id_set = 1;
7464         else
7465             break;
7466     }
7467
7468     if (bd_id_set == 0) {
7469         errmsg ("missing bridge domain\n");
7470         return -99;
7471     }
7472
7473     fformat(vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI\n");
7474
7475     /* Get list of l2 fib entries */
7476     M(L2_FIB_TABLE_DUMP, l2_fib_table_dump);
7477
7478     mp->bd_id = ntohl(bd_id);
7479     S;
7480
7481     /* Use a control ping for synchronization */
7482     {
7483         vl_api_control_ping_t * mp;
7484         M(CONTROL_PING, control_ping);
7485         S;
7486     }
7487     W;
7488 }
7489
7490
7491 static int
7492 api_interface_name_renumber (vat_main_t * vam)
7493 {
7494     unformat_input_t * line_input = vam->input;
7495     vl_api_interface_name_renumber_t *mp;
7496     u32 sw_if_index = ~0;
7497     f64 timeout;
7498     u32 new_show_dev_instance = ~0;
7499
7500     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7501         if (unformat (line_input, "%U", unformat_sw_if_index, vam, 
7502                       &sw_if_index))
7503             ;
7504         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
7505             ;
7506         else if (unformat (line_input, "new_show_dev_instance %d", 
7507                            &new_show_dev_instance))
7508             ;
7509         else
7510             break;
7511     }
7512
7513     if (sw_if_index == ~0) {
7514         errmsg ("missing interface name or sw_if_index\n");
7515         return -99;
7516     }
7517
7518     if (new_show_dev_instance == ~0) {
7519         errmsg ("missing new_show_dev_instance\n");
7520         return -99;
7521     }
7522
7523     M(INTERFACE_NAME_RENUMBER, interface_name_renumber);
7524
7525     mp->sw_if_index = ntohl (sw_if_index);
7526     mp->new_show_dev_instance = ntohl (new_show_dev_instance);
7527
7528     S; W;
7529 }
7530
7531 static int
7532 api_want_ip4_arp_events (vat_main_t * vam)
7533 {
7534     unformat_input_t * line_input = vam->input;
7535     vl_api_want_ip4_arp_events_t * mp;
7536     f64 timeout;
7537     ip4_address_t address;
7538     int address_set = 0;
7539     u32 enable_disable = 1;
7540
7541     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7542         if (unformat (line_input, "address %U", 
7543                       unformat_ip4_address, &address))
7544             address_set = 1;
7545         else if (unformat (line_input, "del"))
7546             enable_disable = 0;
7547         else
7548             break;
7549     }
7550     
7551     if (address_set == 0) {
7552         errmsg ("missing addresses\n");
7553         return -99;
7554     }
7555         
7556     M(WANT_IP4_ARP_EVENTS, want_ip4_arp_events);
7557     mp->enable_disable = enable_disable;
7558     mp->pid = getpid();
7559     mp->address = address.as_u32;
7560
7561     S; W; 
7562 }
7563
7564 static int api_input_acl_set_interface (vat_main_t * vam)
7565 {
7566     unformat_input_t * i = vam->input;
7567     vl_api_input_acl_set_interface_t *mp;
7568     f64 timeout;
7569     u32 sw_if_index;
7570     int sw_if_index_set;
7571     u32 ip4_table_index = ~0;
7572     u32 ip6_table_index = ~0;
7573     u32 l2_table_index = ~0;
7574     u8 is_add = 1;
7575
7576     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7577         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7578             sw_if_index_set = 1;
7579         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7580             sw_if_index_set = 1;
7581         else if (unformat (i, "del"))
7582             is_add = 0;
7583         else if (unformat (i, "ip4-table %d", &ip4_table_index))
7584             ;
7585         else if (unformat (i, "ip6-table %d", &ip6_table_index))
7586             ;
7587         else if (unformat (i, "l2-table %d", &l2_table_index))
7588             ;
7589         else {
7590             clib_warning ("parse error '%U'", format_unformat_error, i);
7591             return -99;
7592         }
7593     }
7594
7595     if (sw_if_index_set == 0) {
7596         errmsg ("missing interface name or sw_if_index\n");
7597         return -99;
7598     }
7599
7600     M(INPUT_ACL_SET_INTERFACE, input_acl_set_interface);
7601
7602     mp->sw_if_index = ntohl(sw_if_index);
7603     mp->ip4_table_index = ntohl(ip4_table_index);
7604     mp->ip6_table_index = ntohl(ip6_table_index);
7605     mp->l2_table_index = ntohl(l2_table_index);
7606     mp->is_add = is_add;
7607
7608     S; W;
7609     /* NOTREACHED */
7610     return 0;
7611 }
7612
7613 static int
7614 api_ip_address_dump (vat_main_t * vam)
7615 {
7616     unformat_input_t * i = vam->input;
7617     vl_api_ip_address_dump_t * mp;
7618     u32 sw_if_index = ~0;
7619     u8 sw_if_index_set = 0;
7620     u8 ipv4_set = 0;
7621     u8 ipv6_set = 0;
7622     f64 timeout;
7623
7624     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7625         if (unformat (i, "sw_if_index %d", &sw_if_index))
7626             sw_if_index_set = 1;
7627         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7628             sw_if_index_set = 1;
7629         else if (unformat (i, "ipv4"))
7630             ipv4_set = 1;
7631         else if (unformat (i, "ipv6"))
7632             ipv6_set = 1;
7633         else
7634             break;
7635     }
7636
7637     if (ipv4_set && ipv6_set) {
7638         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
7639         return -99;
7640     }
7641
7642     if ((!ipv4_set) && (!ipv6_set)) {
7643         errmsg ("no ipv4 nor ipv6 flag set\n");
7644         return -99;
7645     }
7646
7647     if (sw_if_index_set == 0) {
7648         errmsg ("missing interface name or sw_if_index\n");
7649         return -99;
7650     }
7651
7652     vam->current_sw_if_index = sw_if_index;
7653     vam->is_ipv6 = ipv6_set;
7654
7655     M(IP_ADDRESS_DUMP, ip_address_dump);
7656     mp->sw_if_index = ntohl(sw_if_index);
7657     mp->is_ipv6 = ipv6_set;
7658     S;
7659
7660     /* Use a control ping for synchronization */
7661     {
7662         vl_api_control_ping_t * mp;
7663         M(CONTROL_PING, control_ping);
7664         S;
7665     }
7666     W;
7667 }
7668
7669 static int
7670 api_ip_dump (vat_main_t * vam)
7671 {
7672     vl_api_ip_dump_t * mp;
7673     unformat_input_t * in = vam->input;
7674     int ipv4_set = 0;
7675     int ipv6_set = 0;
7676     int is_ipv6;
7677     f64 timeout;
7678     int i;
7679
7680     while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT) {
7681         if (unformat (in, "ipv4"))
7682             ipv4_set = 1;
7683         else if (unformat (in, "ipv6"))
7684             ipv6_set = 1;
7685         else
7686             break;
7687     }
7688
7689     if (ipv4_set && ipv6_set) {
7690         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
7691         return -99;
7692     }
7693
7694     if ((!ipv4_set) && (!ipv6_set)) {
7695         errmsg ("no ipv4 nor ipv6 flag set\n");
7696         return -99;
7697     }
7698
7699     is_ipv6 = ipv6_set;
7700     vam->is_ipv6 = is_ipv6;
7701
7702     /* free old data */
7703     for (i = 0; i < vec_len(vam->ip_details_by_sw_if_index[is_ipv6]); i++) {
7704         vec_free(vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
7705     }
7706     vec_free(vam->ip_details_by_sw_if_index[is_ipv6]);
7707
7708     M(IP_DUMP, ip_dump);
7709     mp->is_ipv6 = ipv6_set;
7710     S;
7711
7712     /* Use a control ping for synchronization */
7713     {
7714         vl_api_control_ping_t * mp;
7715         M(CONTROL_PING, control_ping);
7716         S;
7717     }
7718     W;
7719 }
7720
7721 static int
7722 api_ipsec_spd_add_del (vat_main_t * vam)
7723 {
7724     unformat_input_t * i = vam->input;
7725     vl_api_ipsec_spd_add_del_t *mp;
7726     f64 timeout;
7727     u32 spd_id = ~0;
7728     u8 is_add = 1;
7729
7730     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7731         if (unformat (i, "spd_id %d", &spd_id))
7732             ;
7733         else if (unformat (i, "del"))
7734             is_add = 0;
7735         else {
7736             clib_warning ("parse error '%U'", format_unformat_error, i);
7737             return -99;
7738         }
7739     }
7740     if (spd_id == ~0) {
7741         errmsg ("spd_id must be set\n");
7742         return -99;
7743     }
7744
7745     M(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del);
7746
7747     mp->spd_id = ntohl(spd_id);
7748     mp->is_add = is_add;
7749
7750     S; W;
7751     /* NOTREACHED */
7752     return 0;
7753 }
7754
7755 static int
7756 api_ipsec_interface_add_del_spd (vat_main_t * vam)
7757 {
7758     unformat_input_t * i = vam->input;
7759     vl_api_ipsec_interface_add_del_spd_t *mp;
7760     f64 timeout;
7761     u32 sw_if_index;
7762     u8 sw_if_index_set = 0;
7763     u32 spd_id = (u32) ~0;
7764     u8 is_add = 1;
7765
7766     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7767         if (unformat (i, "del"))
7768             is_add = 0;
7769         else if (unformat (i, "spd_id %d", &spd_id))
7770             ;
7771         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7772             sw_if_index_set = 1;
7773         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7774             sw_if_index_set = 1;
7775         else {
7776             clib_warning ("parse error '%U'", format_unformat_error, i);
7777             return -99;
7778         }
7779
7780     }
7781
7782     if (spd_id == (u32) ~0) {
7783         errmsg ("spd_id must be set\n");
7784         return -99;
7785     }
7786
7787     if (sw_if_index_set == 0) {
7788         errmsg ("missing interface name or sw_if_index\n");
7789         return -99;
7790     }
7791
7792     M(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd);
7793
7794     mp->spd_id = ntohl(spd_id);
7795     mp->sw_if_index = ntohl (sw_if_index);
7796     mp->is_add = is_add;
7797
7798     S; W;
7799     /* NOTREACHED */
7800     return 0;
7801 }
7802
7803 static int
7804 api_ipsec_spd_add_del_entry (vat_main_t * vam)
7805 {
7806     unformat_input_t * i = vam->input;
7807     vl_api_ipsec_spd_add_del_entry_t *mp;
7808     f64 timeout;
7809     u8 is_add = 1, is_outbound = 0, is_ipv6 = 0, is_ip_any = 1;
7810     u32 spd_id, sa_id, protocol = 0, policy = 0;
7811     i32 priority;
7812     u32 rport_start = 0, rport_stop = (u32) ~0;
7813     u32 lport_start = 0, lport_stop = (u32) ~0;
7814     ip4_address_t laddr4_start, laddr4_stop, raddr4_start, raddr4_stop;
7815     ip6_address_t laddr6_start, laddr6_stop, raddr6_start, raddr6_stop;
7816
7817     laddr4_start.as_u32 = raddr4_start.as_u32 = 0;
7818     laddr4_stop.as_u32 = raddr4_stop.as_u32 = (u32) ~0;
7819     laddr6_start.as_u64[0] = raddr6_start.as_u64[0] = 0;
7820     laddr6_start.as_u64[1] = raddr6_start.as_u64[1] = 0;
7821     laddr6_stop.as_u64[0] = raddr6_stop.as_u64[0] = (u64) ~0;
7822     laddr6_stop.as_u64[1] = raddr6_stop.as_u64[1] = (u64) ~0;
7823
7824     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7825         if (unformat (i, "del"))
7826             is_add = 0;
7827         if (unformat (i, "outbound"))
7828             is_outbound = 1;
7829         if (unformat (i, "inbound"))
7830             is_outbound = 0;
7831         else if (unformat (i, "spd_id %d", &spd_id))
7832             ;
7833         else if (unformat (i, "sa_id %d", &sa_id))
7834             ;
7835         else if (unformat (i, "priority %d", &priority))
7836             ;
7837         else if (unformat (i, "protocol %d", &protocol))
7838             ;
7839         else if (unformat (i, "lport_start %d", &lport_start))
7840             ;
7841         else if (unformat (i, "lport_stop %d", &lport_stop))
7842             ;
7843         else if (unformat (i, "rport_start %d", &rport_start))
7844             ;
7845         else if (unformat (i, "rport_stop %d", &rport_stop))
7846             ;
7847         else if (unformat (i, "laddr_start %U", unformat_ip4_address, &laddr4_start))
7848           {
7849             is_ipv6 = 0;
7850             is_ip_any =0;
7851           }
7852         else if (unformat (i, "laddr_stop %U", unformat_ip4_address, &laddr4_stop))
7853           {
7854             is_ipv6 = 0;
7855             is_ip_any = 0;
7856           }
7857         else if (unformat (i, "raddr_start %U", unformat_ip4_address, &raddr4_start))
7858           {
7859             is_ipv6 = 0;
7860             is_ip_any = 0;
7861           }
7862         else if (unformat (i, "raddr_stop %U", unformat_ip4_address, &raddr4_stop))
7863           {
7864             is_ipv6 = 0;
7865             is_ip_any = 0;
7866           }
7867         else if (unformat (i, "laddr_start %U", unformat_ip6_address, &laddr6_start))
7868           {
7869             is_ipv6 = 1;
7870             is_ip_any = 0;
7871           }
7872         else if (unformat (i, "laddr_stop %U", unformat_ip6_address, &laddr6_stop))
7873           {
7874             is_ipv6 = 1;
7875             is_ip_any = 0;
7876           }
7877         else if (unformat (i, "raddr_start %U", unformat_ip6_address, &raddr6_start))
7878           {
7879             is_ipv6 = 1;
7880             is_ip_any = 0;
7881           }
7882         else if (unformat (i, "raddr_stop %U", unformat_ip6_address, &raddr6_stop))
7883           {
7884             is_ipv6 = 1;
7885             is_ip_any = 0;
7886           }
7887         else if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
7888           {
7889             if (policy == IPSEC_POLICY_ACTION_RESOLVE) {
7890                 clib_warning ("unsupported action: 'resolve'");
7891                 return -99;
7892             }
7893           }
7894         else {
7895             clib_warning ("parse error '%U'", format_unformat_error, i);
7896             return -99;
7897         }
7898
7899     }
7900
7901     M(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry);
7902
7903     mp->spd_id = ntohl(spd_id);
7904     mp->priority = ntohl(priority);
7905     mp->is_outbound = is_outbound;
7906
7907     mp->is_ipv6 = is_ipv6;
7908     if (is_ipv6 || is_ip_any) {
7909         memcpy (mp->remote_address_start, &raddr6_start, sizeof(ip6_address_t));
7910         memcpy (mp->remote_address_stop, &raddr6_stop, sizeof(ip6_address_t));
7911         memcpy (mp->local_address_start, &laddr6_start, sizeof(ip6_address_t));
7912         memcpy (mp->local_address_stop, &laddr6_stop, sizeof(ip6_address_t));
7913     } else {
7914         memcpy (mp->remote_address_start, &raddr4_start, sizeof(ip4_address_t));
7915         memcpy (mp->remote_address_stop, &raddr4_stop, sizeof(ip4_address_t));
7916         memcpy (mp->local_address_start, &laddr4_start, sizeof(ip4_address_t));
7917         memcpy (mp->local_address_stop, &laddr4_stop, sizeof(ip4_address_t));
7918     }
7919     mp->protocol = (u8) protocol;
7920     mp->local_port_start = ntohs((u16) lport_start);
7921     mp->local_port_stop = ntohs((u16) lport_stop);
7922     mp->remote_port_start = ntohs((u16) rport_start);
7923     mp->remote_port_stop = ntohs((u16) rport_stop);
7924     mp->policy = (u8) policy;
7925     mp->sa_id = ntohl(sa_id);
7926     mp->is_add = is_add;
7927     mp->is_ip_any = is_ip_any;
7928     S; W;
7929     /* NOTREACHED */
7930     return 0;
7931 }
7932
7933 static int
7934 api_ipsec_sad_add_del_entry (vat_main_t * vam)
7935 {
7936     unformat_input_t * i = vam->input;
7937     vl_api_ipsec_sad_add_del_entry_t *mp;
7938     f64 timeout;
7939     u32 sad_id, spi;
7940     u8 * ck, * ik;
7941     u8 is_add = 1;
7942
7943     u8 protocol = IPSEC_PROTOCOL_AH;
7944     u8 is_tunnel = 0, is_tunnel_ipv6 = 0;
7945     u32 crypto_alg = 0, integ_alg = 0;
7946     ip4_address_t tun_src4;
7947     ip4_address_t tun_dst4;
7948     ip6_address_t tun_src6;
7949     ip6_address_t tun_dst6;
7950
7951     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7952         if (unformat (i, "del"))
7953             is_add = 0;
7954         else if (unformat (i, "sad_id %d", &sad_id))
7955             ;
7956         else if (unformat (i, "spi %d", &spi))
7957             ;
7958         else if (unformat (i, "esp"))
7959             protocol = IPSEC_PROTOCOL_ESP;
7960         else if (unformat (i, "tunnel_src %U", unformat_ip4_address, &tun_src4)) {
7961             is_tunnel = 1;
7962             is_tunnel_ipv6 = 0;
7963         }
7964         else if (unformat (i, "tunnel_dst %U", unformat_ip4_address, &tun_dst4)) {
7965             is_tunnel = 1;
7966             is_tunnel_ipv6 = 0;
7967         }
7968         else if (unformat (i, "tunnel_src %U", unformat_ip6_address, &tun_src6)) {
7969             is_tunnel = 1;
7970             is_tunnel_ipv6 = 1;
7971         }
7972         else if (unformat (i, "tunnel_dst %U", unformat_ip6_address, &tun_dst6)) {
7973             is_tunnel = 1;
7974             is_tunnel_ipv6 = 1;
7975         }
7976         else if (unformat (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg)) {
7977             if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
7978                 crypto_alg > IPSEC_INTEG_ALG_SHA_512_256) {
7979                 clib_warning ("unsupported crypto-alg: '%U'",
7980                               format_ipsec_crypto_alg, crypto_alg);
7981                 return -99;
7982             }
7983         }
7984         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
7985             ;
7986         else if (unformat (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) {
7987             if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
7988                 integ_alg > IPSEC_INTEG_ALG_SHA_512_256) {
7989                 clib_warning ("unsupported integ-alg: '%U'",
7990                               format_ipsec_integ_alg, integ_alg);
7991                 return -99;
7992             }
7993         }
7994         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
7995             ;
7996         else {
7997             clib_warning ("parse error '%U'", format_unformat_error, i);
7998             return -99;
7999         }
8000
8001     }
8002
8003     M(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry);
8004
8005     mp->sad_id = ntohl(sad_id);
8006     mp->is_add = is_add;
8007     mp->protocol = protocol;
8008     mp->spi = ntohl(spi);
8009     mp->is_tunnel = is_tunnel;
8010     mp->is_tunnel_ipv6 = is_tunnel_ipv6;
8011     mp->crypto_algorithm = crypto_alg;
8012     mp->integrity_algorithm = integ_alg;
8013     mp->crypto_key_length = vec_len(ck);
8014     mp->integrity_key_length = vec_len(ik);
8015
8016     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8017       mp->crypto_key_length = sizeof(mp->crypto_key);
8018
8019     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8020       mp->integrity_key_length = sizeof(mp->integrity_key);
8021
8022     memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8023     memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8024
8025     if (is_tunnel) {
8026       if (is_tunnel_ipv6) {
8027         memcpy (mp->tunnel_src_address, &tun_src6, sizeof(ip6_address_t));
8028         memcpy (mp->tunnel_dst_address, &tun_dst6, sizeof(ip6_address_t));
8029       } else {
8030         memcpy (mp->tunnel_src_address, &tun_src4, sizeof(ip4_address_t));
8031         memcpy (mp->tunnel_dst_address, &tun_dst4, sizeof(ip4_address_t));
8032       }
8033     }
8034
8035     S; W;
8036     /* NOTREACHED */
8037     return 0;
8038 }
8039
8040 static int
8041 api_ipsec_sa_set_key (vat_main_t * vam)
8042 {
8043     unformat_input_t * i = vam->input;
8044     vl_api_ipsec_sa_set_key_t *mp;
8045     f64 timeout;
8046     u32 sa_id;
8047     u8 * ck, * ik;
8048
8049     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8050         if (unformat (i, "sa_id %d", &sa_id))
8051             ;
8052         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8053             ;
8054         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8055             ;
8056         else {
8057             clib_warning ("parse error '%U'", format_unformat_error, i);
8058             return -99;
8059         }
8060     }
8061
8062     M(IPSEC_SA_SET_KEY, ipsec_set_sa_key);
8063
8064     mp->sa_id = ntohl(sa_id);
8065     mp->crypto_key_length = vec_len(ck);
8066     mp->integrity_key_length = vec_len(ik);
8067
8068     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8069       mp->crypto_key_length = sizeof(mp->crypto_key);
8070
8071     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8072       mp->integrity_key_length = sizeof(mp->integrity_key);
8073
8074     memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8075     memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8076
8077     S; W;
8078     /* NOTREACHED */
8079     return 0;
8080 }
8081
8082 /*
8083  * MAP
8084  */
8085 static int api_map_add_domain (vat_main_t * vam)
8086 {
8087   unformat_input_t *i = vam->input;
8088   vl_api_map_add_domain_t *mp;
8089   f64 timeout;
8090
8091   ip4_address_t ip4_prefix;
8092   ip6_address_t ip6_prefix;
8093   ip6_address_t ip6_src;
8094   u32 num_m_args = 0;
8095   u32 ip6_prefix_len, ip4_prefix_len, ea_bits_len, psid_offset,
8096     psid_length;
8097   u8 is_translation = 0;
8098   u32 mtu = 0;
8099   u8 ip6_src_len = 128;
8100
8101   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8102     if (unformat (i, "ip4-pfx %U/%d", unformat_ip4_address,
8103                   &ip4_prefix, &ip4_prefix_len))
8104       num_m_args++;
8105     else if (unformat (i, "ip6-pfx %U/%d", unformat_ip6_address,
8106                        &ip6_prefix, &ip6_prefix_len))
8107       num_m_args++;
8108     else if (unformat (i, "ip6-src %U/%d", unformat_ip6_address, &ip6_src, &ip6_src_len))
8109       num_m_args++;
8110     else if (unformat (i, "ip6-src %U", unformat_ip6_address, &ip6_src))
8111       num_m_args++;
8112     else if (unformat (i, "ea-bits-len %d", &ea_bits_len))
8113       num_m_args++;
8114     else if (unformat (i, "psid-offset %d", &psid_offset))
8115       num_m_args++;
8116     else if (unformat (i, "psid-len %d", &psid_length))
8117       num_m_args++;
8118     else if (unformat (i, "mtu %d", &mtu))
8119       num_m_args++;
8120     else if (unformat (i, "map-t"))
8121       is_translation = 1;
8122     else {
8123       clib_warning ("parse error '%U'", format_unformat_error, i);
8124       return -99;
8125     }
8126   }
8127
8128   if (num_m_args != 6) {
8129     errmsg("mandatory argument(s) missing\n");
8130     return -99;
8131   }
8132
8133   /* Construct the API message */
8134   M(MAP_ADD_DOMAIN, map_add_domain);
8135
8136   memcpy(mp->ip4_prefix, &ip4_prefix, sizeof(ip4_prefix));
8137   mp->ip4_prefix_len = ip4_prefix_len;
8138
8139   memcpy(mp->ip6_prefix, &ip6_prefix, sizeof(ip6_prefix));
8140   mp->ip6_prefix_len = ip6_prefix_len;
8141
8142   memcpy(mp->ip6_src, &ip6_src, sizeof(ip6_src));
8143   mp->ip6_src_prefix_len = ip6_src_len;
8144
8145   mp->ea_bits_len = ea_bits_len;
8146   mp->psid_offset = psid_offset;
8147   mp->psid_length = psid_length;
8148   mp->is_translation = is_translation;
8149   mp->mtu = htons(mtu);
8150
8151   /* send it... */
8152   S;
8153
8154   /* Wait for a reply, return good/bad news  */
8155   W;
8156 }
8157
8158 static int api_map_del_domain (vat_main_t * vam)
8159 {
8160   unformat_input_t *i = vam->input;
8161   vl_api_map_del_domain_t *mp;
8162   f64 timeout;
8163
8164   u32 num_m_args = 0;
8165   u32 index;
8166
8167   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8168     if (unformat (i, "index %d", &index))
8169       num_m_args++;
8170     else {
8171       clib_warning ("parse error '%U'", format_unformat_error, i);
8172       return -99;
8173     }
8174   }
8175
8176   if (num_m_args != 1) {
8177     errmsg("mandatory argument(s) missing\n");
8178     return -99;
8179   }
8180
8181   /* Construct the API message */
8182   M(MAP_DEL_DOMAIN, map_del_domain);
8183
8184   mp->index = ntohl(index);
8185
8186   /* send it... */
8187   S;
8188
8189   /* Wait for a reply, return good/bad news  */
8190   W;
8191 }
8192
8193 static int api_map_add_del_rule (vat_main_t * vam)
8194 {
8195   unformat_input_t *i = vam->input;
8196   vl_api_map_add_del_rule_t *mp;
8197   f64 timeout;
8198   u8 is_add = 1;
8199   ip6_address_t ip6_dst;
8200   u32 num_m_args = 0, index, psid;
8201
8202   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8203     if (unformat (i, "index %d", &index))
8204       num_m_args++;
8205     else if (unformat (i, "psid %d", &psid))
8206       num_m_args++;
8207     else if (unformat (i, "dst %U", unformat_ip6_address, &ip6_dst))
8208       num_m_args++;
8209     else if (unformat (i, "del")) {
8210       is_add = 0;
8211     } else {
8212       clib_warning ("parse error '%U'", format_unformat_error, i);
8213       return -99;
8214     }
8215   }
8216
8217   /* Construct the API message */
8218   M(MAP_ADD_DEL_RULE, map_add_del_rule);
8219
8220   mp->index = ntohl(index);
8221   mp->is_add = is_add;
8222   memcpy(mp->ip6_dst, &ip6_dst, sizeof(ip6_dst));
8223   mp->psid = ntohs(psid);
8224
8225   /* send it... */
8226   S;
8227
8228   /* Wait for a reply, return good/bad news  */
8229   W;
8230 }
8231
8232 static int api_map_domain_dump (vat_main_t * vam)
8233 {
8234     vl_api_map_domain_dump_t *mp;
8235     f64 timeout;
8236
8237     /* Construct the API message */
8238     M(MAP_DOMAIN_DUMP, map_domain_dump);
8239
8240     /* send it... */
8241     S;
8242
8243     /* Use a control ping for synchronization */
8244     {
8245         vl_api_control_ping_t * mp;
8246         M(CONTROL_PING, control_ping);
8247         S;
8248     }
8249     W;
8250 }
8251
8252 static int api_map_rule_dump (vat_main_t * vam)
8253 {
8254     unformat_input_t *i = vam->input;
8255     vl_api_map_rule_dump_t *mp;
8256     f64 timeout;
8257     u32 domain_index = ~0;
8258
8259     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8260         if (unformat (i, "index %u", &domain_index))
8261             ;
8262         else
8263             break;
8264     }
8265
8266     if (domain_index == ~0) {
8267         clib_warning("parse error: domain index expected");
8268         return -99;
8269     }
8270
8271     /* Construct the API message */
8272     M(MAP_RULE_DUMP, map_rule_dump);
8273
8274     mp->domain_index = htonl(domain_index);
8275
8276     /* send it... */
8277     S;
8278
8279     /* Use a control ping for synchronization */
8280     {
8281         vl_api_control_ping_t * mp;
8282         M(CONTROL_PING, control_ping);
8283         S;
8284     }
8285     W;
8286 }
8287
8288 static void vl_api_map_add_domain_reply_t_handler
8289 (vl_api_map_add_domain_reply_t * mp)
8290 {
8291   vat_main_t * vam = &vat_main;
8292   i32 retval = ntohl(mp->retval);
8293
8294   if (vam->async_mode) {
8295       vam->async_errors += (retval < 0);
8296   } else {
8297       vam->retval = retval;
8298       vam->result_ready = 1;
8299   }
8300 }
8301
8302 static void vl_api_map_add_domain_reply_t_handler_json
8303 (vl_api_map_add_domain_reply_t * mp)
8304 {
8305   vat_main_t * vam = &vat_main;
8306   vat_json_node_t node;
8307
8308   vat_json_init_object(&node);
8309   vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
8310   vat_json_object_add_uint(&node, "index", ntohl(mp->index));
8311
8312   vat_json_print(vam->ofp, &node);
8313   vat_json_free(&node);
8314
8315   vam->retval = ntohl(mp->retval);
8316   vam->result_ready = 1;
8317 }
8318
8319 static int
8320 api_get_first_msg_id (vat_main_t * vam)
8321 {
8322     vl_api_get_first_msg_id_t * mp;
8323     f64 timeout;
8324     unformat_input_t * i = vam->input;
8325     u8 * name;
8326     u8 name_set = 0;
8327     
8328     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8329         if (unformat (i, "client %s", &name))
8330             name_set = 1;
8331         else 
8332             break;
8333     }
8334
8335     if (name_set == 0) {
8336         errmsg ("missing client name\n");
8337         return -99;
8338     }
8339     vec_add1 (name, 0);
8340
8341     if (vec_len (name) > 63) {
8342         errmsg ("client name too long\n");
8343         return -99;
8344     }
8345
8346     M(GET_FIRST_MSG_ID, get_first_msg_id);
8347     memcpy (mp->name, name, vec_len(name));
8348     S; W;
8349     /* NOTREACHED */
8350     return 0;
8351 }
8352
8353 static int q_or_quit (vat_main_t * vam)
8354 {
8355     longjmp (vam->jump_buf, 1);
8356     return 0; /* not so much */
8357 }
8358 static int q (vat_main_t * vam) {return q_or_quit (vam);}
8359 static int quit (vat_main_t * vam) {return q_or_quit (vam);}
8360
8361 static int comment (vat_main_t * vam)
8362 {
8363     return 0;
8364 }
8365
8366 static int cmd_cmp (void * a1, void * a2)
8367 {
8368   u8 ** c1 = a1;
8369   u8 ** c2 = a2;
8370
8371   return strcmp ((char *)(c1[0]), (char *)(c2[0]));
8372 }
8373
8374 static int help (vat_main_t * vam)
8375 {
8376     u8 ** cmds = 0;
8377     u8 * name = 0;
8378     hash_pair_t * p;
8379     unformat_input_t * i = vam->input;
8380     int j;
8381
8382     if (unformat (i, "%s", &name)) {
8383         uword *hs;
8384
8385         vec_add1(name, 0);
8386
8387         hs = hash_get_mem (vam->help_by_name, name);
8388         if (hs)
8389             fformat (vam->ofp, "usage: %s %s\n", name, hs[0]);
8390         else
8391             fformat (vam->ofp, "No such msg / command '%s'\n", name);
8392         vec_free(name);
8393         return 0;
8394     }
8395
8396     fformat(vam->ofp, "Help is available for the following:\n");
8397
8398     hash_foreach_pair (p, vam->function_by_name, 
8399     ({
8400         vec_add1 (cmds, (u8 *)(p->key));
8401     }));
8402
8403     vec_sort_with_function (cmds, cmd_cmp);
8404
8405     for (j = 0; j < vec_len(cmds); j++)
8406         fformat (vam->ofp, "%s\n", cmds[j]);
8407
8408     vec_free (cmds);
8409     return 0;
8410 }
8411
8412 static int set (vat_main_t * vam)
8413 {
8414     u8 * name = 0, * value = 0;
8415     unformat_input_t * i = vam->input;
8416
8417     if (unformat (i, "%s", &name)) {
8418         /* The input buffer is a vector, not a string. */
8419         value = vec_dup (i->buffer);
8420         vec_delete (value, i->index, 0);
8421         /* Almost certainly has a trailing newline */
8422         if (value[vec_len(value)-1] == '\n')
8423             value[vec_len(value)-1] = 0;
8424         /* Make sure it's a proper string, one way or the other */
8425         vec_add1 (value, 0);
8426         (void) clib_macro_set_value (&vam->macro_main, 
8427                                      (char *)name, (char *)value);
8428     }
8429     else
8430         errmsg ("usage: set <name> <value>\n");
8431
8432     vec_free (name);
8433     vec_free (value);
8434     return 0;
8435 }
8436
8437 static int unset (vat_main_t * vam)
8438 {
8439     u8 * name = 0;
8440
8441     if (unformat (vam->input, "%s", &name))
8442         if (clib_macro_unset (&vam->macro_main, (char *)name) == 1)
8443             errmsg ("unset: %s wasn't set\n", name);
8444     vec_free (name);
8445     return 0;
8446 }
8447
8448 typedef struct {
8449     u8 * name;
8450     u8 * value;
8451 } macro_sort_t;
8452
8453
8454 static int macro_sort_cmp (void * a1, void * a2)
8455 {
8456   macro_sort_t * s1 = a1;
8457   macro_sort_t * s2 = a2;
8458
8459   return strcmp ((char *)(s1->name), (char *)(s2->name));
8460 }
8461
8462 static int dump_macro_table (vat_main_t * vam)
8463 {
8464     macro_sort_t * sort_me = 0, * sm;    
8465     int i;
8466     hash_pair_t * p;
8467
8468     hash_foreach_pair (p, vam->macro_main.the_value_table_hash, 
8469     ({
8470         vec_add2 (sort_me, sm, 1);
8471         sm->name = (u8 *)(p->key);
8472         sm->value = (u8 *) (p->value[0]);
8473     }));
8474     
8475     vec_sort_with_function (sort_me, macro_sort_cmp);
8476
8477     if (vec_len(sort_me))
8478         fformat (vam->ofp, "%-15s%s\n", "Name", "Value");
8479     else
8480         fformat (vam->ofp, "The macro table is empty...\n");
8481
8482     for (i = 0; i < vec_len (sort_me); i++)
8483         fformat (vam->ofp, "%-15s%s\n", sort_me[i].name,
8484                  sort_me[i].value);
8485     return 0;
8486 }
8487
8488 static int script (vat_main_t * vam)
8489 {
8490     u8 * s = 0;
8491     char * save_current_file;
8492     unformat_input_t save_input;
8493     jmp_buf save_jump_buf;
8494     u32 save_line_number;
8495
8496     FILE * new_fp, * save_ifp;
8497
8498     if (unformat (vam->input, "%s", &s)) {
8499         new_fp = fopen ((char *)s, "r");
8500         if (new_fp == 0) {
8501             errmsg ("Couldn't open script file %s\n", s);
8502             vec_free (s);
8503             return -99;
8504         }
8505     } else {
8506         errmsg ("Missing script name\n");
8507         return -99;
8508     }
8509
8510     memcpy (&save_input, &vam->input, sizeof (save_input));
8511     memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
8512     save_ifp = vam->ifp;
8513     save_line_number = vam->input_line_number;
8514     save_current_file = (char *) vam->current_file;
8515
8516     vam->input_line_number = 0;
8517     vam->ifp = new_fp;
8518     vam->current_file = s;
8519     do_one_file (vam);
8520
8521     memcpy (&vam->input, &save_input, sizeof (vam->input));
8522     memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
8523     vam->ifp = save_ifp;
8524     vam->input_line_number = save_line_number;
8525     vam->current_file = (u8 *) save_current_file;
8526     vec_free (s);
8527
8528     return 0;
8529 }
8530
8531 static int echo (vat_main_t * vam)
8532 {
8533     fformat (vam->ofp, "%v", vam->input->buffer);
8534     return 0;
8535 }
8536
8537 /* List of API message constructors, CLI names map to api_xxx */
8538 #define foreach_vpe_api_msg                                             \
8539 _(create_loopback,"[mac <mac-addr>]")                                   \
8540 _(sw_interface_dump,"")                                                 \
8541 _(sw_interface_set_flags,                                               \
8542   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
8543 _(sw_interface_add_del_address,                                         \
8544   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
8545 _(sw_interface_set_table,                                               \
8546   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
8547 _(sw_interface_set_vpath,                                               \
8548   "<intfc> | sw_if_index <id> enable | disable")                        \
8549 _(sw_interface_set_l2_xconnect,                                         \
8550   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8551   "enable | disable")                                                   \
8552 _(sw_interface_set_l2_bridge,                                           \
8553   "rx <intfc> | rx_sw_if_index <id> bd_id <bridge-domain-id>\n"         \
8554   "[shg <split-horizon-group>] [bvi]\n"                                 \
8555   "enable | disable")                                                   \
8556 _(bridge_domain_add_del,                                                \
8557   "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [del]\n")\
8558 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")     \
8559 _(l2fib_add_del,                                                        \
8560   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi]\n") \
8561 _(l2_flags,                                                             \
8562   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood]\n")       \
8563 _(bridge_flags,                                                         \
8564   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
8565 _(tap_connect,                                                          \
8566   "tapname <name> mac <mac-addr> | random-mac")                         \
8567 _(tap_modify,                                                           \
8568   "<vpp-if-name> | sw_if_index <id> tapname <name> mac <mac-addr> | random-mac") \
8569 _(tap_delete,                                                           \
8570   "<vpp-if-name> | sw_if_index <id>")                                   \
8571 _(sw_interface_tap_dump, "")                                            \
8572 _(ip_add_del_route,                                                     \
8573   "<addr>/<mask> via <addr> [vrf <n>]\n"                                \
8574   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
8575   "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
8576   "[multipath] [count <n>]")                                            \
8577 _(proxy_arp_add_del,                                                    \
8578   "<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]")                      \
8579 _(proxy_arp_intfc_enable_disable,                                       \
8580   "<intfc> | sw_if_index <id> enable | disable")                        \
8581 _(mpls_add_del_encap,                                                   \
8582   "label <n> dst <ip4-addr> [vrf <n>] [del]")                           \
8583 _(mpls_add_del_decap,                                                   \
8584   "label <n> [rx_vrf_id <n>] [tx_vrf_id] [s-bit-clear][del]")           \
8585 _(mpls_gre_add_del_tunnel,                                              \
8586   "inner_vrf_id <n> outer_vrf_id <n> src <ip4-address> dst <ip4-address>\n" \
8587   "adj <ip4-address>/<mask-width> [del]")                               \
8588 _(sw_interface_set_unnumbered,                                          \
8589   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
8590 _(ip_neighbor_add_del,                                                  \
8591   "<intfc> | sw_if_index <id> dst <ip46-address> mac <mac-addr>")       \
8592 _(reset_vrf, "vrf <id> [ipv6]")                                         \
8593 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
8594 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
8595   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
8596   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
8597   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
8598 _(oam_add_del, "src <ip4-address> dst <ip4-address> [vrf <n>] [del]")   \
8599 _(reset_fib, "vrf <n> [ipv6]")                                          \
8600 _(dhcp_proxy_config,                                                    \
8601   "svr <v46-address> src <v46-address>\n"                               \
8602    "insert-cid <n> [del]")                                              \
8603 _(dhcp_proxy_config_2,                                                  \
8604   "svr <v46-address> src <v46-address>\n"                               \
8605    "rx_vrf_id <nn> server_vrf_id <nn> insert-cid <n> [del]")            \
8606 _(dhcp_proxy_set_vss,                                                   \
8607   "tbl_id <n> fib_id <n> oui <n> [ipv6] [del]")                         \
8608 _(dhcp_client_config,                                                   \
8609   "<intfc> | sw_if_index <id> [hostname <name>] [disable_event] [del]") \
8610 _(set_ip_flow_hash,                                                     \
8611   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
8612 _(sw_interface_ip6_enable_disable,                                      \
8613   "<intfc> | sw_if_index <id> enable | disable")                        \
8614 _(sw_interface_ip6_set_link_local_address,                              \
8615   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>")              \
8616 _(sw_interface_ip6nd_ra_prefix,                                         \
8617   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>\n"             \
8618   "val_life <n> pref_life <n> [def] [noadv] [offl] [noauto]\n"          \
8619   "[nolink] [isno]")                                                    \
8620 _(sw_interface_ip6nd_ra_config,                                         \
8621   "<intfc> | sw_if_index <id> [maxint <n>] [minint <n>]\n"              \
8622   "[life <n>] [count <n>] [interval <n>] [surpress]\n"                  \
8623   "[managed] [other] [ll] [send] [cease] [isno] [def]")                 \
8624 _(set_arp_neighbor_limit, "arp_nbr_limit <n> [ipv6]")                   \
8625 _(l2_patch_add_del,                                                     \
8626   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8627   "enable | disable")                                                   \
8628 _(mpls_ethernet_add_del_tunnel,                                         \
8629   "tx <intfc> | tx_sw_if_index <n> dst <mac-addr>\n"                    \
8630   "adj <ip4-addr>/<mw> dst <mac-addr> [del]")                           \
8631 _(mpls_ethernet_add_del_tunnel_2,                                       \
8632   "inner_vrf_id <n> outer_vrf_id <n> next-hop <ip4-addr>\n"             \
8633   "resolve-attempts <n> resolve-if-needed 0 | 1 [del]")                 \
8634 _(sr_tunnel_add_del,                                                    \
8635   "src <ip6-addr> dst <ip6-addr>/<mw> (next <ip6-addr>)+\n"             \
8636   " [tag <ip6-addr>]* [clean] [reroute]")                               \
8637 _(classify_add_del_table,                                               \
8638   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
8639   "[del] mask <mask-value>\n"                                           \
8640   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>")              \
8641 _(classify_add_del_session,                                             \
8642   "[hit-next|l2-hit-next|acl-hit-next] <name|nn> table-index <nn>\n"    \
8643   "skip_n <nn> match_n <nn> match [hex] [l2] [l3 [ip4|ip6]]")           \
8644 _(classify_set_interface_ip_table,                                      \
8645   "<intfc> | sw_if_index <nn> table <nn>")                              \
8646 _(classify_set_interface_l2_tables,                                     \
8647   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
8648   "  [other-table <nn>]")                                               \
8649 _(get_node_index, "node <node-name")                                    \
8650 _(add_node_next, "node <node-name> next <next-node-name>")              \
8651 _(l2tpv3_create_tunnel,                                                 \
8652   "client_address <ip6-addr> our_address <ip6-addr>\n"                  \
8653   "[local_session_id <nn>][remote_session_id <nn>][local_cookie <nn>]\n"\
8654   "[remote_cookie <nn>]\n[l2-sublayer-preset]\n")                       \
8655 _(l2tpv3_set_tunnel_cookies,                                            \
8656   "<intfc> | sw_if_index <nn> [new_local_cookie <nn>]\n"                \
8657   "[new_remote_cookie <nn>]\n")                                         \
8658 _(l2tpv3_interface_enable_disable,                                      \
8659   "<intfc> | sw_if_index <nn> enable | disable")                        \
8660 _(l2tpv3_set_lookup_key,                                                \
8661   "lookup_v6_src | lookup_v6_dst | lookup_session_id")                  \
8662 _(sw_if_l2tpv3_tunnel_dump, "")                                         \
8663 _(vxlan_add_del_tunnel,                                                 \
8664   "src <ip4-addr> dst <ip4-addr> vni [encap-vrf-id <nn>]\n"             \
8665   " [decap-next l2|ip4|ip6] [del]")                                     \
8666 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
8667 _(l2_fib_clear_table, "")                                               \
8668 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
8669 _(l2_interface_vlan_tag_rewrite,                                        \
8670   "<intfc> | sw_if_index <nn> \n"                                       \
8671   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
8672   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
8673 _(create_vhost_user_if,                                                 \
8674         "socket <filename> [server] [renumber <dev_instance>]")         \
8675 _(modify_vhost_user_if,                                                 \
8676         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
8677         "[server] [renumber <dev_instance>]")                           \
8678 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
8679 _(sw_interface_vhost_user_dump, "")                                     \
8680 _(show_version, "")                                                     \
8681 _(nsh_gre_add_del_tunnel,                                               \
8682   "src <ip4-addr> dst <ip4-addr>"                                       \
8683   "c1 <nn> c2 <nn> c3 <nn> c4 <nn> spi <nn> si <nn>\n"                  \
8684   "[encap-fib-id <nn>] [decap-fib-id <nn>] [o-bit <1|0>]\n"             \
8685   "[c-bit <1|0>] [md-type <nn>][next-ip4][next-ip6][next-ethernet]\n"   \
8686   "[tlv <xx>][del]")                                                    \
8687 _(nsh_vxlan_gpe_add_del_tunnel,                                         \
8688   "src <ip4-addr> dst <ip4-addr> vni <nn>\n"                            \
8689   "c1 <nn> c2 <nn> c3 <nn> c4 <nn> spi <nn> si <nn>\n"                  \
8690   "[encap-vrf-id <nn>] [decap-vrf-id <nn>] [o-bit <1|0>]\n"             \
8691   "[c-bit <1|0>] [md-type <nn>][next-ip4][next-ip6][next-ethernet]\n"   \
8692   "[tlv <xx>][del]")                                                    \
8693 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
8694 _(lisp_gpe_add_del_tunnel,                                              \
8695   "src <ip4-addr> dst <ip4-addr> iid <nn>|iidx <0xnn>\n"                \
8696   "[encap-vrf-id <nn>] [decap-vrf-id <nn>]\n"                           \
8697   "[n-bit][l-bit][e-bit][v-bit][i-bit][p-bit][not-p-bit][o-bit]\n"      \
8698   "[next-ip4][next-ip6][next-ethernet][next-nsh]\n"                     \
8699   "[decap-next [ip4|ip6|ethernet|nsh-encap|<nn>]][del]")                \
8700 _(interface_name_renumber,                                              \
8701   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
8702 _(input_acl_set_interface,                                              \
8703   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
8704   "  [l2-table <nn>] [del]")                                            \
8705 _(want_ip4_arp_events, "address <ip4-address> [del]")                   \
8706 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
8707 _(ip_dump, "ipv4 | ipv6")                                               \
8708 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
8709 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
8710   "  spid_id <n> ")                                                     \
8711 _(ipsec_sad_add_del_entry, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
8712   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
8713   "  integ_alg <alg> integ_key <hex>")                                  \
8714 _(ipsec_spd_add_del_entry, "spd_id <n> priority <n> action <action>\n"  \
8715   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
8716   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
8717   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" )\
8718 _(ipsec_sa_set_key, "sa_id <n> crypto_key <hex> integ_key <hex>")       \
8719 _(delete_loopback,"sw_if_index <nn>")                                   \
8720 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
8721 _(map_add_domain,                                                       \
8722   "ip4-pfx <ip4pfx> ip6-pfx <ip6pfx> "                                  \
8723   "ip6-src <ip6addr> "                                                  \
8724   "ea-bits-len <n> psid-offset <n> psid-len <n>")                       \
8725 _(map_del_domain, "index <n>")                                          \
8726 _(map_add_del_rule,                                                     \
8727   "index <n> psid <n> dst <ip6addr> [del]")                             \
8728 _(map_domain_dump, "")                                                  \
8729 _(map_rule_dump, "index <map-domain>")                                  \
8730 _(want_interface_events,  "enable|disable")                             \
8731 _(want_stats,"enable|disable")                                          \
8732 _(get_first_msg_id, "client <name>")
8733
8734 /* List of command functions, CLI names map directly to functions */
8735 #define foreach_cli_function                                    \
8736 _(comment, "usage: comment <ignore-rest-of-line>")              \
8737 _(dump_interface_table, "usage: dump_interface_table")          \
8738 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
8739 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
8740 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
8741 _(dump_stats_table, "usage: dump_stats_table")                  \
8742 _(dump_macro_table, "usage: dump_macro_table ")                 \
8743 _(echo, "usage: echo <message>")                                \
8744 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
8745 _(help, "usage: help")                                          \
8746 _(q, "usage: quit")                                             \
8747 _(quit, "usage: quit")                                          \
8748 _(set, "usage: set <variable-name> <value>")                    \
8749 _(script, "usage: script <file-name>")                          \
8750 _(unset, "usage: unset <variable-name>")
8751
8752 #define _(N,n)                                  \
8753     static void vl_api_##n##_t_handler_uni      \
8754     (vl_api_##n##_t * mp)                       \
8755     {                                           \
8756         vat_main_t * vam = &vat_main;           \
8757         if (vam->json_output) {                 \
8758             vl_api_##n##_t_handler_json(mp);    \
8759         } else {                                \
8760             vl_api_##n##_t_handler(mp);         \
8761         }                                       \
8762     }
8763 foreach_vpe_api_reply_msg;
8764 #undef _
8765
8766 void vat_api_hookup (vat_main_t *vam)
8767 {
8768 #define _(N,n)                                                  \
8769     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
8770                            vl_api_##n##_t_handler_uni,          \
8771                            vl_noop_handler,                     \
8772                            vl_api_##n##_t_endian,               \
8773                            vl_api_##n##_t_print,                \
8774                            sizeof(vl_api_##n##_t), 1); 
8775     foreach_vpe_api_reply_msg;
8776 #undef _
8777
8778     vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
8779
8780     vam->sw_if_index_by_interface_name = 
8781         hash_create_string (0, sizeof (uword));
8782
8783     vam->function_by_name = 
8784         hash_create_string (0, sizeof(uword));
8785
8786     vam->help_by_name = 
8787         hash_create_string (0, sizeof(uword));
8788
8789     /* API messages we can send */
8790 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
8791     foreach_vpe_api_msg;
8792 #undef _
8793
8794     /* Help strings */
8795 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
8796     foreach_vpe_api_msg;
8797 #undef _
8798
8799     /* CLI functions */
8800 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
8801     foreach_cli_function;
8802 #undef _
8803
8804     /* Help strings */
8805 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
8806     foreach_cli_function;
8807 #undef _
8808 }
8809
8810 #undef vl_api_version
8811 #define vl_api_version(n,v) static u32 vpe_api_version = v;
8812 #include <api/vpe.api.h>
8813 #undef vl_api_version
8814
8815 void vl_client_add_api_signatures (vl_api_memclnt_create_t *mp) 
8816 {
8817     /* 
8818      * Send the main API signature in slot 0. This bit of code must
8819      * match the checks in ../vpe/api/api.c: vl_msg_api_version_check().
8820      */
8821     mp->api_versions[0] = clib_host_to_net_u32 (vpe_api_version);
8822 }