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