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