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