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