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