Add custom mac address option to vhost interfaces.
[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     u8 hwaddr[6];
6897     u8 use_custom_mac = 0;
6898
6899     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6900       if (unformat (i, "socket %s", &file_name)) {
6901         file_name_set = 1;
6902       }
6903       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
6904         ;
6905       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
6906         use_custom_mac = 1;
6907       else if (unformat (i, "server"))
6908         is_server = 1;
6909       else
6910         break;
6911     }
6912
6913     if (file_name_set == 0) {
6914       errmsg ("missing socket file name\n");
6915       return -99;
6916     }
6917
6918     if (vec_len (file_name) > 255) {
6919       errmsg ("socket file name too long\n");
6920       return -99;
6921     }
6922     vec_add1 (file_name, 0);
6923
6924     M(CREATE_VHOST_USER_IF, create_vhost_user_if);
6925
6926     mp->is_server = is_server;
6927     memcpy(mp->sock_filename, file_name, vec_len(file_name));
6928     vec_free(file_name);
6929     if (custom_dev_instance != ~0) {
6930         mp->renumber = 1;
6931         mp->custom_dev_instance = ntohl(custom_dev_instance);
6932     }
6933     mp->use_custom_mac = use_custom_mac;
6934     memcpy(mp->mac_address, hwaddr, 6);
6935
6936     S; W;
6937     /* NOTREACHED */
6938     return 0;
6939 }
6940
6941 static int api_modify_vhost_user_if (vat_main_t * vam)
6942 {
6943     unformat_input_t * i = vam->input;
6944     vl_api_modify_vhost_user_if_t *mp;
6945     f64 timeout;
6946     u8 * file_name;
6947     u8 is_server = 0;
6948     u8 file_name_set = 0;
6949     u32 custom_dev_instance = ~0;
6950     u8 sw_if_index_set = 0;
6951     u32 sw_if_index = (u32)~0;
6952
6953     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6954       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6955           sw_if_index_set = 1;
6956       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6957           sw_if_index_set = 1;
6958       else if (unformat (i, "socket %s", &file_name)) {
6959         file_name_set = 1;
6960       }
6961       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
6962         ;
6963       else if (unformat (i, "server"))
6964         is_server = 1;
6965       else
6966         break;
6967     }
6968
6969     if (sw_if_index_set == 0) {
6970        errmsg ("missing sw_if_index or interface name\n");
6971        return -99;
6972     }
6973
6974     if (file_name_set == 0) {
6975       errmsg ("missing socket file name\n");
6976       return -99;
6977     }
6978
6979     if (vec_len (file_name) > 255) {
6980       errmsg ("socket file name too long\n");
6981       return -99;
6982     }
6983     vec_add1 (file_name, 0);
6984
6985     M(MODIFY_VHOST_USER_IF, modify_vhost_user_if);
6986
6987     mp->sw_if_index = ntohl(sw_if_index);
6988     mp->is_server = is_server;
6989     memcpy(mp->sock_filename, file_name, vec_len(file_name));
6990     vec_free(file_name);
6991     if (custom_dev_instance != ~0) {
6992         mp->renumber = 1;
6993         mp->custom_dev_instance = ntohl(custom_dev_instance);
6994     }
6995
6996     S; W;
6997     /* NOTREACHED */
6998     return 0;
6999 }
7000
7001 static int api_delete_vhost_user_if (vat_main_t * vam)
7002 {
7003     unformat_input_t * i = vam->input;
7004     vl_api_delete_vhost_user_if_t *mp;
7005     f64 timeout;
7006     u32 sw_if_index = ~0;
7007     u8 sw_if_index_set = 0;
7008
7009     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7010       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7011           sw_if_index_set = 1;
7012       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7013           sw_if_index_set = 1;
7014       else
7015         break;
7016     }
7017
7018     if (sw_if_index_set == 0) {
7019        errmsg ("missing sw_if_index or interface name\n");
7020        return -99;
7021     }
7022
7023
7024     M(DELETE_VHOST_USER_IF, delete_vhost_user_if);
7025
7026     mp->sw_if_index = ntohl(sw_if_index);
7027
7028     S; W;
7029     /* NOTREACHED */
7030     return 0;
7031 }
7032
7033 static void vl_api_sw_interface_vhost_user_details_t_handler
7034 (vl_api_sw_interface_vhost_user_details_t * mp)
7035 {
7036     vat_main_t * vam = &vat_main;
7037
7038     fformat(vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s\n",
7039             (char *)mp->interface_name,
7040             ntohl(mp->sw_if_index), ntohl(mp->virtio_net_hdr_sz),
7041             clib_net_to_host_u64(mp->features), mp->is_server,
7042             ntohl(mp->num_regions), (char *)mp->sock_filename);
7043     fformat(vam->ofp, "    Status: '%s'\n", strerror(ntohl(mp->sock_errno)));
7044 }
7045
7046 static void vl_api_sw_interface_vhost_user_details_t_handler_json
7047 (vl_api_sw_interface_vhost_user_details_t * mp)
7048 {
7049     vat_main_t * vam = &vat_main;
7050     vat_json_node_t *node = NULL;
7051
7052     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7053         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7054         vat_json_init_array(&vam->json_tree);
7055     }
7056     node = vat_json_array_add(&vam->json_tree);
7057
7058     vat_json_init_object(node);
7059     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7060     vat_json_object_add_string_copy(node, "interface_name", mp->interface_name);
7061     vat_json_object_add_uint(node, "virtio_net_hdr_sz", ntohl(mp->virtio_net_hdr_sz));
7062     vat_json_object_add_uint(node, "features", clib_net_to_host_u64(mp->features));
7063     vat_json_object_add_uint(node, "is_server", mp->is_server);
7064     vat_json_object_add_string_copy(node, "sock_filename", mp->sock_filename);
7065     vat_json_object_add_uint(node, "num_regions", ntohl(mp->num_regions));
7066     vat_json_object_add_uint(node, "sock_errno", ntohl(mp->sock_errno));
7067 }
7068
7069 static int api_sw_interface_vhost_user_dump (vat_main_t * vam)
7070 {
7071     vl_api_sw_interface_vhost_user_dump_t *mp;
7072     f64 timeout;
7073     fformat(vam->ofp, "Interface name           idx hdr_sz features server regions filename\n");
7074
7075     /* Get list of vhost-user interfaces */
7076     M(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump);
7077     S;
7078
7079     /* Use a control ping for synchronization */
7080     {
7081         vl_api_control_ping_t * mp;
7082         M(CONTROL_PING, control_ping);
7083         S;
7084     }
7085     W;
7086 }
7087
7088 static int api_show_version (vat_main_t * vam)
7089 {
7090     vl_api_show_version_t *mp;
7091     f64 timeout;
7092
7093     M(SHOW_VERSION, show_version);
7094
7095     S; W;
7096     /* NOTREACHED */
7097     return 0;
7098 }
7099
7100 static uword unformat_nsh_gre_decap_next 
7101 (unformat_input_t * input, va_list * args)
7102 {
7103   u32 * result = va_arg (*args, u32 *);
7104   u32 tmp;
7105   
7106   if (unformat (input, "drop"))
7107     *result = NSH_INPUT_NEXT_DROP;
7108   else if (unformat (input, "ip4"))
7109     *result = NSH_INPUT_NEXT_IP4_INPUT;
7110   else if (unformat (input, "ip6"))
7111     *result = NSH_INPUT_NEXT_IP6_INPUT;
7112   else if (unformat (input, "ethernet"))
7113     *result = NSH_INPUT_NEXT_ETHERNET_INPUT;
7114   else if (unformat (input, "%d", &tmp))
7115     *result = tmp;
7116   else
7117     return 0;
7118   return 1;
7119 }
7120
7121 static int api_nsh_gre_add_del_tunnel (vat_main_t * vam)
7122 {
7123     unformat_input_t * line_input = vam->input;
7124     vl_api_nsh_gre_add_del_tunnel_t *mp;
7125     f64 timeout;
7126     ip4_address_t src, dst;
7127     u8 is_add = 1;
7128     u8 src_set = 0;
7129     u8 dst_set = 0;
7130     u32 encap_vrf_id = 0;
7131     u32 decap_vrf_id = 0;
7132     u8 ver_o_c = 0;
7133     u8 md_type = 0;
7134     u8 next_protocol = 1; /* ip4 */
7135     u32 spi;
7136     u8 spi_set = 0;
7137     u32 si;
7138     u8 si_set = 0;
7139     u32 spi_si;
7140     u32 c1 = 0;
7141     u32 c2 = 0;
7142     u32 c3 = 0;
7143     u32 c4 = 0;
7144     u32 *tlvs = 0;
7145     u32 decap_next_index = NSH_INPUT_NEXT_IP4_INPUT;
7146     u32 tmp;
7147     int i;
7148
7149     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7150         if (unformat (line_input, "del"))
7151             is_add = 0;
7152         else if (unformat (line_input, "src %U", 
7153                            unformat_ip4_address, &src))
7154             src_set = 1;
7155         else if (unformat (line_input, "dst %U",
7156                            unformat_ip4_address, &dst))
7157             dst_set = 1;
7158         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7159             ;
7160         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7161             ;
7162         else if (unformat (line_input, "decap-next %U", 
7163                            unformat_nsh_gre_decap_next, &decap_next_index))
7164             ;
7165         else if (unformat (line_input, "version %d", &tmp))
7166             ver_o_c |= (tmp & 3) << 6;
7167         else if (unformat (line_input, "o-bit %d", &tmp))
7168             ver_o_c |= (tmp & 1) << 5;
7169         else if (unformat (line_input, "c-bit %d", &tmp))
7170             ver_o_c |= (tmp & 1) << 4;
7171         else if (unformat (line_input, "md-type %d", &tmp))
7172             md_type = tmp;
7173         else if (unformat(line_input, "next-ip4"))
7174             next_protocol = 1;
7175         else if (unformat(line_input, "next-ip6"))
7176             next_protocol = 2;
7177         else if (unformat(line_input, "next-ethernet"))
7178             next_protocol = 3;
7179         else if (unformat (line_input, "c1 %d", &c1))
7180             ;
7181         else if (unformat (line_input, "c2 %d", &c2))
7182             ;
7183         else if (unformat (line_input, "c3 %d", &c3))
7184             ;
7185         else if (unformat (line_input, "c4 %d", &c4))
7186             ;
7187         else if (unformat (line_input, "spi %d", &spi))
7188             spi_set = 1;
7189         else if (unformat (line_input, "si %d", &si))
7190             si_set = 1;
7191         else if (unformat (line_input, "tlv %x"))
7192             vec_add1 (tlvs, tmp);
7193         else {
7194             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7195             return -99;
7196         }
7197     }
7198
7199     if (src_set == 0) {
7200         errmsg ("tunnel src address not specified\n");
7201         return -99;
7202     }
7203     if (dst_set == 0) {
7204         errmsg ("tunnel dst address not specified\n");
7205         return -99;
7206     }
7207
7208     if (spi_set == 0) {
7209         errmsg ("spi not specified\n");
7210         return -99;
7211     }
7212
7213     if (si_set == 0) {
7214         errmsg ("si not specified\n");
7215         return -99;
7216     }
7217
7218     M2 (NSH_GRE_ADD_DEL_TUNNEL, nsh_gre_add_del_tunnel,
7219         sizeof(u32) * vec_len (tlvs));
7220     
7221     spi_si = (spi<<8) | si;
7222
7223     mp->src = src.as_u32;
7224     mp->dst = dst.as_u32;
7225     mp->encap_vrf_id = ntohl(encap_vrf_id);
7226     mp->decap_vrf_id = ntohl(decap_vrf_id);
7227     mp->decap_next_index = ntohl(decap_next_index);
7228     mp->tlv_len_in_words = vec_len (tlvs);
7229     mp->is_add = is_add;
7230     mp->ver_o_c = ver_o_c;
7231     mp->length = 6 + vec_len(tlvs);
7232     mp->md_type = md_type;
7233     mp->next_protocol = next_protocol;
7234     mp->spi_si = ntohl(spi_si);
7235     mp->c1 = ntohl(c1);
7236     mp->c2 = ntohl(c2);
7237     mp->c3 = ntohl(c3);
7238     mp->c4 = ntohl(c4);
7239     
7240     for (i = 0; i < vec_len(tlvs); i++)
7241         mp->tlvs[i] = ntohl(tlvs[i]);
7242
7243     vec_free (tlvs);
7244
7245     S; W;
7246     /* NOTREACHED */
7247     return 0;
7248 }
7249
7250 static uword unformat_nsh_vxlan_gpe_decap_next 
7251 (unformat_input_t * input, va_list * args)
7252 {
7253   u32 * result = va_arg (*args, u32 *);
7254   u32 tmp;
7255   
7256   if (unformat (input, "drop"))
7257     *result = NSH_VXLAN_GPE_INPUT_NEXT_DROP;
7258   else if (unformat (input, "ip4"))
7259     *result = NSH_VXLAN_GPE_INPUT_NEXT_IP4_INPUT;
7260   else if (unformat (input, "ip6"))
7261     *result = NSH_VXLAN_GPE_INPUT_NEXT_IP6_INPUT;
7262   else if (unformat (input, "ethernet"))
7263     *result = NSH_VXLAN_GPE_INPUT_NEXT_ETHERNET_INPUT;
7264   else if (unformat (input, "nsh-vxlan-gpe"))
7265       *result = NSH_VXLAN_GPE_INPUT_NEXT_ETHERNET_INPUT;
7266   else if (unformat (input, "%d", &tmp))
7267     *result = tmp;
7268   else
7269     return 0;
7270   return 1;
7271 }
7272
7273 static int api_nsh_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
7274 {
7275     unformat_input_t * line_input = vam->input;
7276     vl_api_nsh_vxlan_gpe_add_del_tunnel_t *mp;
7277     f64 timeout;
7278     ip4_address_t src, dst;
7279     u8 is_add = 1;
7280     u8 src_set = 0;
7281     u8 dst_set = 0;
7282     u32 encap_vrf_id = 0;
7283     u32 decap_vrf_id = 0;
7284     u8 ver_o_c = 0;
7285     u8 md_type = 0;
7286     u8 next_protocol = 1; /* ip4 */
7287     u32 spi;
7288     u8 spi_set = 0;
7289     u32 si;
7290     u8 si_set = 0;
7291     u32 spi_si;
7292     u32 c1 = 0;
7293     u32 c2 = 0;
7294     u32 c3 = 0;
7295     u32 c4 = 0;
7296     u32 *tlvs = 0;
7297     u32 decap_next_index = NSH_INPUT_NEXT_IP4_INPUT;
7298     u32 vni;
7299     u8 vni_set = 0;
7300     u32 tmp;
7301     int i;
7302
7303     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7304         if (unformat (line_input, "del"))
7305             is_add = 0;
7306         else if (unformat (line_input, "src %U", 
7307                            unformat_ip4_address, &src))
7308             src_set = 1;
7309         else if (unformat (line_input, "dst %U",
7310                            unformat_ip4_address, &dst))
7311             dst_set = 1;
7312         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7313             ;
7314         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7315             ;
7316         else if (unformat (line_input, "decap-next %U", 
7317                            unformat_nsh_vxlan_gpe_decap_next, 
7318                            &decap_next_index))
7319             ;
7320         else if (unformat (line_input, "vni %d", &vni))
7321             vni_set = 1;
7322         else if (unformat (line_input, "version %d", &tmp))
7323             ver_o_c |= (tmp & 3) << 6;
7324         else if (unformat (line_input, "o-bit %d", &tmp))
7325             ver_o_c |= (tmp & 1) << 5;
7326         else if (unformat (line_input, "c-bit %d", &tmp))
7327             ver_o_c |= (tmp & 1) << 4;
7328         else if (unformat (line_input, "md-type %d", &tmp))
7329             md_type = tmp;
7330         else if (unformat(line_input, "next-ip4"))
7331             next_protocol = 1;
7332         else if (unformat(line_input, "next-ip6"))
7333             next_protocol = 2;
7334         else if (unformat(line_input, "next-ethernet"))
7335             next_protocol = 3;
7336         else if (unformat (line_input, "c1 %d", &c1))
7337             ;
7338         else if (unformat (line_input, "c2 %d", &c2))
7339             ;
7340         else if (unformat (line_input, "c3 %d", &c3))
7341             ;
7342         else if (unformat (line_input, "c4 %d", &c4))
7343             ;
7344         else if (unformat (line_input, "spi %d", &spi))
7345             spi_set = 1;
7346         else if (unformat (line_input, "si %d", &si))
7347             si_set = 1;
7348         else if (unformat (line_input, "tlv %x"))
7349             vec_add1 (tlvs, tmp);
7350         else {
7351             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7352             return -99;
7353         }
7354     }
7355
7356     if (src_set == 0) {
7357         errmsg ("tunnel src address not specified\n");
7358         return -99;
7359     }
7360     if (dst_set == 0) {
7361         errmsg ("tunnel dst address not specified\n");
7362         return -99;
7363     }
7364
7365     if (spi_set == 0) {
7366         errmsg ("spi not specified\n");
7367         return -99;
7368     }
7369
7370     if (si_set == 0) {
7371         errmsg ("si not specified\n");
7372         return -99;
7373     }
7374     if (vni_set == 0) {
7375         errmsg ("vni not specified\n");
7376         return -99;
7377     }
7378
7379     M2 (NSH_VXLAN_GPE_ADD_DEL_TUNNEL, nsh_vxlan_gpe_add_del_tunnel,
7380         sizeof(u32) * vec_len (tlvs));
7381     
7382     spi_si = (spi<<8) | si;
7383
7384     mp->src = src.as_u32;
7385     mp->dst = dst.as_u32;
7386     mp->encap_vrf_id = ntohl(encap_vrf_id);
7387     mp->decap_vrf_id = ntohl(decap_vrf_id);
7388     mp->decap_next_index = ntohl(decap_next_index);
7389     mp->tlv_len_in_words = vec_len (tlvs);
7390     mp->vni = ntohl(vni);
7391     mp->is_add = is_add;
7392     mp->ver_o_c = ver_o_c;
7393     mp->length = 6 + vec_len(tlvs);
7394     mp->md_type = md_type;
7395     mp->next_protocol = next_protocol;
7396     mp->spi_si = ntohl(spi_si);
7397     mp->c1 = ntohl(c1);
7398     mp->c2 = ntohl(c2);
7399     mp->c3 = ntohl(c3);
7400     mp->c4 = ntohl(c4);
7401     
7402     for (i = 0; i < vec_len(tlvs); i++)
7403         mp->tlvs[i] = ntohl(tlvs[i]);
7404
7405     vec_free (tlvs);
7406
7407     S; W;
7408     /* NOTREACHED */
7409     return 0;
7410 }
7411
7412 static uword unformat_lisp_gpe_decap_next (unformat_input_t * input, 
7413                                                va_list * args)
7414 {
7415     u32 * result = va_arg (*args, u32 *);
7416     u32 tmp;
7417   
7418     if (unformat (input, "drop"))
7419         *result = LISP_GPE_INPUT_NEXT_DROP;
7420     else if (unformat (input, "ip4"))
7421         *result = LISP_GPE_INPUT_NEXT_IP4_INPUT;
7422     else if (unformat (input, "ip6"))
7423         *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
7424     else if (unformat (input, "ethernet"))
7425         *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
7426     else if (unformat (input, "lisp-gpe"))
7427         *result = LISP_GPE_INPUT_NEXT_LISP_GPE_ENCAP;
7428     else if (unformat (input, "%d", &tmp))
7429         *result = tmp;
7430     else
7431         return 0;
7432     return 1;
7433 }
7434
7435 static int
7436 api_lisp_gpe_add_del_tunnel (vat_main_t * vam)
7437 {
7438     unformat_input_t * line_input = vam->input;
7439     vl_api_lisp_gpe_add_del_tunnel_t *mp;
7440     f64 timeout;
7441     ip4_address_t src, dst;
7442     u8 is_add = 1;
7443     u8 src_set = 0;
7444     u8 dst_set = 0;
7445     u32 encap_vrf_id = 0;
7446     u32 decap_vrf_id = 0;
7447     u8 next_protocol = LISP_GPE_NEXT_PROTOCOL_IP4;
7448     u32 decap_next_index = LISP_GPE_INPUT_NEXT_IP4_INPUT;
7449     u8 flags = LISP_GPE_FLAGS_P;
7450     u8 ver_res = 0;
7451     u8 res = 0;
7452     u32 iid = 0;
7453     u8 iid_set = 0;
7454     u32 tmp;
7455   
7456     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7457         if (unformat (line_input, "del"))
7458             is_add = 0;
7459         else if (unformat (line_input, "src %U", 
7460                            unformat_ip4_address, &src))
7461             src_set = 1;
7462         else if (unformat (line_input, "dst %U",
7463                            unformat_ip4_address, &dst))
7464             dst_set = 1;
7465         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7466             ;
7467         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7468             ;
7469         else if (unformat (line_input, "decap-next %U", 
7470                            unformat_lisp_gpe_decap_next, 
7471                            &decap_next_index))
7472             ;
7473         else if (unformat(line_input, "next-ip4"))
7474             next_protocol = 1;
7475         else if (unformat(line_input, "next-ip6"))
7476             next_protocol = 2;
7477         else if (unformat(line_input, "next-ethernet"))
7478             next_protocol = 3;
7479         else if (unformat(line_input, "next-nsh"))
7480             next_protocol = 4;
7481         /* Allow the user to specify anything they want in the LISP hdr */
7482         else if (unformat (line_input, "ver_res %x", &tmp))
7483             ver_res = tmp;
7484         else if (unformat (line_input, "res %x", &tmp))
7485             res = tmp;
7486         else if (unformat (line_input, "flags %x", &tmp))
7487             flags = tmp;
7488         else if (unformat (line_input, "n-bit"))
7489             flags |= LISP_GPE_FLAGS_N;
7490         else if (unformat (line_input, "l-bit"))
7491             flags |= LISP_GPE_FLAGS_L;
7492         else if (unformat (line_input, "e-bit"))
7493             flags |= LISP_GPE_FLAGS_E;
7494         else if (unformat (line_input, "v-bit"))
7495             flags |= LISP_GPE_FLAGS_V;
7496         else if (unformat (line_input, "i-bit"))
7497             flags |= LISP_GPE_FLAGS_V;
7498         else if (unformat (line_input, "not-p-bit"))
7499             flags &= !LISP_GPE_FLAGS_P;
7500         else if (unformat (line_input, "p-bit"))
7501             flags |= LISP_GPE_FLAGS_P;
7502         else if (unformat (line_input, "o-bit"))
7503             flags |= LISP_GPE_FLAGS_O;
7504         else if (unformat (line_input, "iidx %x", &iid))
7505             iid_set = 1;
7506         else if (unformat (line_input, "iid %d", &iid))
7507             iid_set = 1;
7508         else {
7509             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7510             return -99;
7511         }
7512     }
7513
7514     if (src_set == 0) {
7515         errmsg ("tunnel src address not specified\n");
7516         return -99;
7517     }
7518     if (dst_set == 0) {
7519         errmsg ("tunnel dst address not specified\n");
7520         return -99;
7521     }
7522     if (iid_set == 0) {
7523         errmsg ("iid not specified\n");
7524         return -99;
7525     }
7526
7527     M(LISP_GPE_ADD_DEL_TUNNEL, lisp_gpe_add_del_tunnel);
7528
7529     mp->src = src.as_u32;
7530     mp->dst = dst.as_u32;
7531     mp->encap_vrf_id = ntohl(encap_vrf_id);
7532     mp->decap_vrf_id = ntohl(decap_vrf_id);
7533     mp->decap_next_index = ntohl(decap_next_index);
7534     mp->is_add = is_add;
7535     mp->flags = flags;
7536     mp->ver_res = ver_res;
7537     mp->res = res;
7538     mp->next_protocol = next_protocol;
7539     mp->iid = ntohl(iid);
7540
7541     S; W; 
7542
7543     /* NOTREACHED */
7544     return 0;
7545 }
7546
7547
7548 u8 * format_l2_fib_mac_address (u8 * s, va_list * args)
7549 {
7550   u8 * a = va_arg (*args, u8 *);
7551
7552   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
7553                  a[2], a[3], a[4], a[5], a[6], a[7]);
7554 }
7555
7556 static void vl_api_l2_fib_table_entry_t_handler
7557 (vl_api_l2_fib_table_entry_t * mp)
7558 {
7559     vat_main_t * vam = &vat_main;
7560
7561     fformat(vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
7562             "       %d       %d     %d\n",
7563             ntohl(mp->bd_id), format_l2_fib_mac_address, &mp->mac,
7564             ntohl(mp->sw_if_index), mp->static_mac, mp->filter_mac,
7565             mp->bvi_mac);
7566 }
7567
7568 static void vl_api_l2_fib_table_entry_t_handler_json
7569 (vl_api_l2_fib_table_entry_t * mp)
7570 {
7571     vat_main_t * vam = &vat_main;
7572     vat_json_node_t *node = NULL;
7573
7574     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7575         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7576         vat_json_init_array(&vam->json_tree);
7577     }
7578     node = vat_json_array_add(&vam->json_tree);
7579
7580     vat_json_init_object(node);
7581     vat_json_object_add_uint(node, "bd_id", ntohl(mp->bd_id));
7582     vat_json_object_add_uint(node, "mac", clib_net_to_host_u64(mp->mac));
7583     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7584     vat_json_object_add_uint(node, "static_mac", mp->static_mac);
7585     vat_json_object_add_uint(node, "filter_mac", mp->filter_mac);
7586     vat_json_object_add_uint(node, "bvi_mac", mp->bvi_mac);
7587 }
7588
7589 static int api_l2_fib_table_dump (vat_main_t * vam)
7590 {
7591     unformat_input_t * i = vam->input;
7592     vl_api_l2_fib_table_dump_t *mp;
7593     f64 timeout;
7594     u32 bd_id;
7595     u8 bd_id_set = 0;
7596
7597     /* Parse args required to build the message */
7598     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7599         if (unformat (i, "bd_id %d", &bd_id))
7600             bd_id_set = 1;
7601         else
7602             break;
7603     }
7604
7605     if (bd_id_set == 0) {
7606         errmsg ("missing bridge domain\n");
7607         return -99;
7608     }
7609
7610     fformat(vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI\n");
7611
7612     /* Get list of l2 fib entries */
7613     M(L2_FIB_TABLE_DUMP, l2_fib_table_dump);
7614
7615     mp->bd_id = ntohl(bd_id);
7616     S;
7617
7618     /* Use a control ping for synchronization */
7619     {
7620         vl_api_control_ping_t * mp;
7621         M(CONTROL_PING, control_ping);
7622         S;
7623     }
7624     W;
7625 }
7626
7627
7628 static int
7629 api_interface_name_renumber (vat_main_t * vam)
7630 {
7631     unformat_input_t * line_input = vam->input;
7632     vl_api_interface_name_renumber_t *mp;
7633     u32 sw_if_index = ~0;
7634     f64 timeout;
7635     u32 new_show_dev_instance = ~0;
7636
7637     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7638         if (unformat (line_input, "%U", unformat_sw_if_index, vam, 
7639                       &sw_if_index))
7640             ;
7641         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
7642             ;
7643         else if (unformat (line_input, "new_show_dev_instance %d", 
7644                            &new_show_dev_instance))
7645             ;
7646         else
7647             break;
7648     }
7649
7650     if (sw_if_index == ~0) {
7651         errmsg ("missing interface name or sw_if_index\n");
7652         return -99;
7653     }
7654
7655     if (new_show_dev_instance == ~0) {
7656         errmsg ("missing new_show_dev_instance\n");
7657         return -99;
7658     }
7659
7660     M(INTERFACE_NAME_RENUMBER, interface_name_renumber);
7661
7662     mp->sw_if_index = ntohl (sw_if_index);
7663     mp->new_show_dev_instance = ntohl (new_show_dev_instance);
7664
7665     S; W;
7666 }
7667
7668 static int
7669 api_want_ip4_arp_events (vat_main_t * vam)
7670 {
7671     unformat_input_t * line_input = vam->input;
7672     vl_api_want_ip4_arp_events_t * mp;
7673     f64 timeout;
7674     ip4_address_t address;
7675     int address_set = 0;
7676     u32 enable_disable = 1;
7677
7678     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7679         if (unformat (line_input, "address %U", 
7680                       unformat_ip4_address, &address))
7681             address_set = 1;
7682         else if (unformat (line_input, "del"))
7683             enable_disable = 0;
7684         else
7685             break;
7686     }
7687     
7688     if (address_set == 0) {
7689         errmsg ("missing addresses\n");
7690         return -99;
7691     }
7692         
7693     M(WANT_IP4_ARP_EVENTS, want_ip4_arp_events);
7694     mp->enable_disable = enable_disable;
7695     mp->pid = getpid();
7696     mp->address = address.as_u32;
7697
7698     S; W; 
7699 }
7700
7701 static int api_input_acl_set_interface (vat_main_t * vam)
7702 {
7703     unformat_input_t * i = vam->input;
7704     vl_api_input_acl_set_interface_t *mp;
7705     f64 timeout;
7706     u32 sw_if_index;
7707     int sw_if_index_set;
7708     u32 ip4_table_index = ~0;
7709     u32 ip6_table_index = ~0;
7710     u32 l2_table_index = ~0;
7711     u8 is_add = 1;
7712
7713     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7714         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7715             sw_if_index_set = 1;
7716         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7717             sw_if_index_set = 1;
7718         else if (unformat (i, "del"))
7719             is_add = 0;
7720         else if (unformat (i, "ip4-table %d", &ip4_table_index))
7721             ;
7722         else if (unformat (i, "ip6-table %d", &ip6_table_index))
7723             ;
7724         else if (unformat (i, "l2-table %d", &l2_table_index))
7725             ;
7726         else {
7727             clib_warning ("parse error '%U'", format_unformat_error, i);
7728             return -99;
7729         }
7730     }
7731
7732     if (sw_if_index_set == 0) {
7733         errmsg ("missing interface name or sw_if_index\n");
7734         return -99;
7735     }
7736
7737     M(INPUT_ACL_SET_INTERFACE, input_acl_set_interface);
7738
7739     mp->sw_if_index = ntohl(sw_if_index);
7740     mp->ip4_table_index = ntohl(ip4_table_index);
7741     mp->ip6_table_index = ntohl(ip6_table_index);
7742     mp->l2_table_index = ntohl(l2_table_index);
7743     mp->is_add = is_add;
7744
7745     S; W;
7746     /* NOTREACHED */
7747     return 0;
7748 }
7749
7750 static int
7751 api_ip_address_dump (vat_main_t * vam)
7752 {
7753     unformat_input_t * i = vam->input;
7754     vl_api_ip_address_dump_t * mp;
7755     u32 sw_if_index = ~0;
7756     u8 sw_if_index_set = 0;
7757     u8 ipv4_set = 0;
7758     u8 ipv6_set = 0;
7759     f64 timeout;
7760
7761     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7762         if (unformat (i, "sw_if_index %d", &sw_if_index))
7763             sw_if_index_set = 1;
7764         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7765             sw_if_index_set = 1;
7766         else if (unformat (i, "ipv4"))
7767             ipv4_set = 1;
7768         else if (unformat (i, "ipv6"))
7769             ipv6_set = 1;
7770         else
7771             break;
7772     }
7773
7774     if (ipv4_set && ipv6_set) {
7775         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
7776         return -99;
7777     }
7778
7779     if ((!ipv4_set) && (!ipv6_set)) {
7780         errmsg ("no ipv4 nor ipv6 flag set\n");
7781         return -99;
7782     }
7783
7784     if (sw_if_index_set == 0) {
7785         errmsg ("missing interface name or sw_if_index\n");
7786         return -99;
7787     }
7788
7789     vam->current_sw_if_index = sw_if_index;
7790     vam->is_ipv6 = ipv6_set;
7791
7792     M(IP_ADDRESS_DUMP, ip_address_dump);
7793     mp->sw_if_index = ntohl(sw_if_index);
7794     mp->is_ipv6 = ipv6_set;
7795     S;
7796
7797     /* Use a control ping for synchronization */
7798     {
7799         vl_api_control_ping_t * mp;
7800         M(CONTROL_PING, control_ping);
7801         S;
7802     }
7803     W;
7804 }
7805
7806 static int
7807 api_ip_dump (vat_main_t * vam)
7808 {
7809     vl_api_ip_dump_t * mp;
7810     unformat_input_t * in = vam->input;
7811     int ipv4_set = 0;
7812     int ipv6_set = 0;
7813     int is_ipv6;
7814     f64 timeout;
7815     int i;
7816
7817     while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT) {
7818         if (unformat (in, "ipv4"))
7819             ipv4_set = 1;
7820         else if (unformat (in, "ipv6"))
7821             ipv6_set = 1;
7822         else
7823             break;
7824     }
7825
7826     if (ipv4_set && ipv6_set) {
7827         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
7828         return -99;
7829     }
7830
7831     if ((!ipv4_set) && (!ipv6_set)) {
7832         errmsg ("no ipv4 nor ipv6 flag set\n");
7833         return -99;
7834     }
7835
7836     is_ipv6 = ipv6_set;
7837     vam->is_ipv6 = is_ipv6;
7838
7839     /* free old data */
7840     for (i = 0; i < vec_len(vam->ip_details_by_sw_if_index[is_ipv6]); i++) {
7841         vec_free(vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
7842     }
7843     vec_free(vam->ip_details_by_sw_if_index[is_ipv6]);
7844
7845     M(IP_DUMP, ip_dump);
7846     mp->is_ipv6 = ipv6_set;
7847     S;
7848
7849     /* Use a control ping for synchronization */
7850     {
7851         vl_api_control_ping_t * mp;
7852         M(CONTROL_PING, control_ping);
7853         S;
7854     }
7855     W;
7856 }
7857
7858 static int
7859 api_ipsec_spd_add_del (vat_main_t * vam)
7860 {
7861 #if DPDK > 0
7862     unformat_input_t * i = vam->input;
7863     vl_api_ipsec_spd_add_del_t *mp;
7864     f64 timeout;
7865     u32 spd_id = ~0;
7866     u8 is_add = 1;
7867
7868     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7869         if (unformat (i, "spd_id %d", &spd_id))
7870             ;
7871         else if (unformat (i, "del"))
7872             is_add = 0;
7873         else {
7874             clib_warning ("parse error '%U'", format_unformat_error, i);
7875             return -99;
7876         }
7877     }
7878     if (spd_id == ~0) {
7879         errmsg ("spd_id must be set\n");
7880         return -99;
7881     }
7882
7883     M(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del);
7884
7885     mp->spd_id = ntohl(spd_id);
7886     mp->is_add = is_add;
7887
7888     S; W;
7889     /* NOTREACHED */
7890     return 0;
7891 #else
7892     clib_warning ("unsupported (no dpdk)");
7893     return -99;
7894 #endif
7895 }
7896
7897 static int
7898 api_ipsec_interface_add_del_spd (vat_main_t * vam)
7899 {
7900 #if DPDK > 0
7901     unformat_input_t * i = vam->input;
7902     vl_api_ipsec_interface_add_del_spd_t *mp;
7903     f64 timeout;
7904     u32 sw_if_index;
7905     u8 sw_if_index_set = 0;
7906     u32 spd_id = (u32) ~0;
7907     u8 is_add = 1;
7908
7909     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7910         if (unformat (i, "del"))
7911             is_add = 0;
7912         else if (unformat (i, "spd_id %d", &spd_id))
7913             ;
7914         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7915             sw_if_index_set = 1;
7916         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7917             sw_if_index_set = 1;
7918         else {
7919             clib_warning ("parse error '%U'", format_unformat_error, i);
7920             return -99;
7921         }
7922
7923     }
7924
7925     if (spd_id == (u32) ~0) {
7926         errmsg ("spd_id must be set\n");
7927         return -99;
7928     }
7929
7930     if (sw_if_index_set == 0) {
7931         errmsg ("missing interface name or sw_if_index\n");
7932         return -99;
7933     }
7934
7935     M(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd);
7936
7937     mp->spd_id = ntohl(spd_id);
7938     mp->sw_if_index = ntohl (sw_if_index);
7939     mp->is_add = is_add;
7940
7941     S; W;
7942     /* NOTREACHED */
7943     return 0;
7944 #else
7945     clib_warning ("unsupported (no dpdk)");
7946     return -99;
7947 #endif
7948 }
7949
7950 static int
7951 api_ipsec_spd_add_del_entry (vat_main_t * vam)
7952 {
7953 #if DPDK > 0
7954     unformat_input_t * i = vam->input;
7955     vl_api_ipsec_spd_add_del_entry_t *mp;
7956     f64 timeout;
7957     u8 is_add = 1, is_outbound = 0, is_ipv6 = 0, is_ip_any = 1;
7958     u32 spd_id, sa_id, protocol = 0, policy = 0;
7959     i32 priority;
7960     u32 rport_start = 0, rport_stop = (u32) ~0;
7961     u32 lport_start = 0, lport_stop = (u32) ~0;
7962     ip4_address_t laddr4_start, laddr4_stop, raddr4_start, raddr4_stop;
7963     ip6_address_t laddr6_start, laddr6_stop, raddr6_start, raddr6_stop;
7964
7965     laddr4_start.as_u32 = raddr4_start.as_u32 = 0;
7966     laddr4_stop.as_u32 = raddr4_stop.as_u32 = (u32) ~0;
7967     laddr6_start.as_u64[0] = raddr6_start.as_u64[0] = 0;
7968     laddr6_start.as_u64[1] = raddr6_start.as_u64[1] = 0;
7969     laddr6_stop.as_u64[0] = raddr6_stop.as_u64[0] = (u64) ~0;
7970     laddr6_stop.as_u64[1] = raddr6_stop.as_u64[1] = (u64) ~0;
7971
7972     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7973         if (unformat (i, "del"))
7974             is_add = 0;
7975         if (unformat (i, "outbound"))
7976             is_outbound = 1;
7977         if (unformat (i, "inbound"))
7978             is_outbound = 0;
7979         else if (unformat (i, "spd_id %d", &spd_id))
7980             ;
7981         else if (unformat (i, "sa_id %d", &sa_id))
7982             ;
7983         else if (unformat (i, "priority %d", &priority))
7984             ;
7985         else if (unformat (i, "protocol %d", &protocol))
7986             ;
7987         else if (unformat (i, "lport_start %d", &lport_start))
7988             ;
7989         else if (unformat (i, "lport_stop %d", &lport_stop))
7990             ;
7991         else if (unformat (i, "rport_start %d", &rport_start))
7992             ;
7993         else if (unformat (i, "rport_stop %d", &rport_stop))
7994             ;
7995         else if (unformat (i, "laddr_start %U", unformat_ip4_address, &laddr4_start))
7996           {
7997             is_ipv6 = 0;
7998             is_ip_any =0;
7999           }
8000         else if (unformat (i, "laddr_stop %U", unformat_ip4_address, &laddr4_stop))
8001           {
8002             is_ipv6 = 0;
8003             is_ip_any = 0;
8004           }
8005         else if (unformat (i, "raddr_start %U", unformat_ip4_address, &raddr4_start))
8006           {
8007             is_ipv6 = 0;
8008             is_ip_any = 0;
8009           }
8010         else if (unformat (i, "raddr_stop %U", unformat_ip4_address, &raddr4_stop))
8011           {
8012             is_ipv6 = 0;
8013             is_ip_any = 0;
8014           }
8015         else if (unformat (i, "laddr_start %U", unformat_ip6_address, &laddr6_start))
8016           {
8017             is_ipv6 = 1;
8018             is_ip_any = 0;
8019           }
8020         else if (unformat (i, "laddr_stop %U", unformat_ip6_address, &laddr6_stop))
8021           {
8022             is_ipv6 = 1;
8023             is_ip_any = 0;
8024           }
8025         else if (unformat (i, "raddr_start %U", unformat_ip6_address, &raddr6_start))
8026           {
8027             is_ipv6 = 1;
8028             is_ip_any = 0;
8029           }
8030         else if (unformat (i, "raddr_stop %U", unformat_ip6_address, &raddr6_stop))
8031           {
8032             is_ipv6 = 1;
8033             is_ip_any = 0;
8034           }
8035         else if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
8036           {
8037             if (policy == IPSEC_POLICY_ACTION_RESOLVE) {
8038                 clib_warning ("unsupported action: 'resolve'");
8039                 return -99;
8040             }
8041           }
8042         else {
8043             clib_warning ("parse error '%U'", format_unformat_error, i);
8044             return -99;
8045         }
8046
8047     }
8048
8049     M(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry);
8050
8051     mp->spd_id = ntohl(spd_id);
8052     mp->priority = ntohl(priority);
8053     mp->is_outbound = is_outbound;
8054
8055     mp->is_ipv6 = is_ipv6;
8056     if (is_ipv6 || is_ip_any) {
8057         memcpy (mp->remote_address_start, &raddr6_start, sizeof(ip6_address_t));
8058         memcpy (mp->remote_address_stop, &raddr6_stop, sizeof(ip6_address_t));
8059         memcpy (mp->local_address_start, &laddr6_start, sizeof(ip6_address_t));
8060         memcpy (mp->local_address_stop, &laddr6_stop, sizeof(ip6_address_t));
8061     } else {
8062         memcpy (mp->remote_address_start, &raddr4_start, sizeof(ip4_address_t));
8063         memcpy (mp->remote_address_stop, &raddr4_stop, sizeof(ip4_address_t));
8064         memcpy (mp->local_address_start, &laddr4_start, sizeof(ip4_address_t));
8065         memcpy (mp->local_address_stop, &laddr4_stop, sizeof(ip4_address_t));
8066     }
8067     mp->protocol = (u8) protocol;
8068     mp->local_port_start = ntohs((u16) lport_start);
8069     mp->local_port_stop = ntohs((u16) lport_stop);
8070     mp->remote_port_start = ntohs((u16) rport_start);
8071     mp->remote_port_stop = ntohs((u16) rport_stop);
8072     mp->policy = (u8) policy;
8073     mp->sa_id = ntohl(sa_id);
8074     mp->is_add = is_add;
8075     mp->is_ip_any = is_ip_any;
8076     S; W;
8077     /* NOTREACHED */
8078     return 0;
8079 #else
8080     clib_warning ("unsupported (no dpdk)");
8081     return -99;
8082 #endif
8083 }
8084
8085 static int
8086 api_ipsec_sad_add_del_entry (vat_main_t * vam)
8087 {
8088 #if DPDK > 0
8089     unformat_input_t * i = vam->input;
8090     vl_api_ipsec_sad_add_del_entry_t *mp;
8091     f64 timeout;
8092     u32 sad_id, spi;
8093     u8 * ck, * ik;
8094     u8 is_add = 1;
8095
8096     u8 protocol = IPSEC_PROTOCOL_AH;
8097     u8 is_tunnel = 0, is_tunnel_ipv6 = 0;
8098     u32 crypto_alg = 0, integ_alg = 0;
8099     ip4_address_t tun_src4;
8100     ip4_address_t tun_dst4;
8101     ip6_address_t tun_src6;
8102     ip6_address_t tun_dst6;
8103
8104     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8105         if (unformat (i, "del"))
8106             is_add = 0;
8107         else if (unformat (i, "sad_id %d", &sad_id))
8108             ;
8109         else if (unformat (i, "spi %d", &spi))
8110             ;
8111         else if (unformat (i, "esp"))
8112             protocol = IPSEC_PROTOCOL_ESP;
8113         else if (unformat (i, "tunnel_src %U", unformat_ip4_address, &tun_src4)) {
8114             is_tunnel = 1;
8115             is_tunnel_ipv6 = 0;
8116         }
8117         else if (unformat (i, "tunnel_dst %U", unformat_ip4_address, &tun_dst4)) {
8118             is_tunnel = 1;
8119             is_tunnel_ipv6 = 0;
8120         }
8121         else if (unformat (i, "tunnel_src %U", unformat_ip6_address, &tun_src6)) {
8122             is_tunnel = 1;
8123             is_tunnel_ipv6 = 1;
8124         }
8125         else if (unformat (i, "tunnel_dst %U", unformat_ip6_address, &tun_dst6)) {
8126             is_tunnel = 1;
8127             is_tunnel_ipv6 = 1;
8128         }
8129         else if (unformat (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg)) {
8130             if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
8131                 crypto_alg > IPSEC_INTEG_ALG_SHA_512_256) {
8132                 clib_warning ("unsupported crypto-alg: '%U'",
8133                               format_ipsec_crypto_alg, crypto_alg);
8134                 return -99;
8135             }
8136         }
8137         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8138             ;
8139         else if (unformat (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) {
8140             if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
8141                 integ_alg > IPSEC_INTEG_ALG_SHA_512_256) {
8142                 clib_warning ("unsupported integ-alg: '%U'",
8143                               format_ipsec_integ_alg, integ_alg);
8144                 return -99;
8145             }
8146         }
8147         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8148             ;
8149         else {
8150             clib_warning ("parse error '%U'", format_unformat_error, i);
8151             return -99;
8152         }
8153
8154     }
8155
8156     M(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry);
8157
8158     mp->sad_id = ntohl(sad_id);
8159     mp->is_add = is_add;
8160     mp->protocol = protocol;
8161     mp->spi = ntohl(spi);
8162     mp->is_tunnel = is_tunnel;
8163     mp->is_tunnel_ipv6 = is_tunnel_ipv6;
8164     mp->crypto_algorithm = crypto_alg;
8165     mp->integrity_algorithm = integ_alg;
8166     mp->crypto_key_length = vec_len(ck);
8167     mp->integrity_key_length = vec_len(ik);
8168
8169     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8170       mp->crypto_key_length = sizeof(mp->crypto_key);
8171
8172     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8173       mp->integrity_key_length = sizeof(mp->integrity_key);
8174
8175     memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8176     memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8177
8178     if (is_tunnel) {
8179       if (is_tunnel_ipv6) {
8180         memcpy (mp->tunnel_src_address, &tun_src6, sizeof(ip6_address_t));
8181         memcpy (mp->tunnel_dst_address, &tun_dst6, sizeof(ip6_address_t));
8182       } else {
8183         memcpy (mp->tunnel_src_address, &tun_src4, sizeof(ip4_address_t));
8184         memcpy (mp->tunnel_dst_address, &tun_dst4, sizeof(ip4_address_t));
8185       }
8186     }
8187
8188     S; W;
8189     /* NOTREACHED */
8190     return 0;
8191 #else
8192     clib_warning ("unsupported (no dpdk)");
8193     return -99;
8194 #endif
8195 }
8196
8197 static int
8198 api_ipsec_sa_set_key (vat_main_t * vam)
8199 {
8200 #if DPDK > 0
8201     unformat_input_t * i = vam->input;
8202     vl_api_ipsec_sa_set_key_t *mp;
8203     f64 timeout;
8204     u32 sa_id;
8205     u8 * ck, * ik;
8206
8207     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8208         if (unformat (i, "sa_id %d", &sa_id))
8209             ;
8210         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8211             ;
8212         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8213             ;
8214         else {
8215             clib_warning ("parse error '%U'", format_unformat_error, i);
8216             return -99;
8217         }
8218     }
8219
8220     M(IPSEC_SA_SET_KEY, ipsec_set_sa_key);
8221
8222     mp->sa_id = ntohl(sa_id);
8223     mp->crypto_key_length = vec_len(ck);
8224     mp->integrity_key_length = vec_len(ik);
8225
8226     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8227       mp->crypto_key_length = sizeof(mp->crypto_key);
8228
8229     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8230       mp->integrity_key_length = sizeof(mp->integrity_key);
8231
8232     memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8233     memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8234
8235     S; W;
8236     /* NOTREACHED */
8237     return 0;
8238 #else
8239     clib_warning ("unsupported (no dpdk)");
8240     return -99;
8241 #endif
8242 }
8243
8244 /*
8245  * MAP
8246  */
8247 static int api_map_add_domain (vat_main_t * vam)
8248 {
8249   unformat_input_t *i = vam->input;
8250   vl_api_map_add_domain_t *mp;
8251   f64 timeout;
8252
8253   ip4_address_t ip4_prefix;
8254   ip6_address_t ip6_prefix;
8255   ip6_address_t ip6_src;
8256   u32 num_m_args = 0;
8257   u32 ip6_prefix_len, ip4_prefix_len, ea_bits_len, psid_offset,
8258     psid_length;
8259   u8 is_translation = 0;
8260   u32 mtu = 0;
8261   u8 ip6_src_len = 128;
8262
8263   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8264     if (unformat (i, "ip4-pfx %U/%d", unformat_ip4_address,
8265                   &ip4_prefix, &ip4_prefix_len))
8266       num_m_args++;
8267     else if (unformat (i, "ip6-pfx %U/%d", unformat_ip6_address,
8268                        &ip6_prefix, &ip6_prefix_len))
8269       num_m_args++;
8270     else if (unformat (i, "ip6-src %U/%d", unformat_ip6_address, &ip6_src, &ip6_src_len))
8271       num_m_args++;
8272     else if (unformat (i, "ip6-src %U", unformat_ip6_address, &ip6_src))
8273       num_m_args++;
8274     else if (unformat (i, "ea-bits-len %d", &ea_bits_len))
8275       num_m_args++;
8276     else if (unformat (i, "psid-offset %d", &psid_offset))
8277       num_m_args++;
8278     else if (unformat (i, "psid-len %d", &psid_length))
8279       num_m_args++;
8280     else if (unformat (i, "mtu %d", &mtu))
8281       num_m_args++;
8282     else if (unformat (i, "map-t"))
8283       is_translation = 1;
8284     else {
8285       clib_warning ("parse error '%U'", format_unformat_error, i);
8286       return -99;
8287     }
8288   }
8289
8290   if (num_m_args != 6) {
8291     errmsg("mandatory argument(s) missing\n");
8292     return -99;
8293   }
8294
8295   /* Construct the API message */
8296   M(MAP_ADD_DOMAIN, map_add_domain);
8297
8298   memcpy(mp->ip4_prefix, &ip4_prefix, sizeof(ip4_prefix));
8299   mp->ip4_prefix_len = ip4_prefix_len;
8300
8301   memcpy(mp->ip6_prefix, &ip6_prefix, sizeof(ip6_prefix));
8302   mp->ip6_prefix_len = ip6_prefix_len;
8303
8304   memcpy(mp->ip6_src, &ip6_src, sizeof(ip6_src));
8305   mp->ip6_src_prefix_len = ip6_src_len;
8306
8307   mp->ea_bits_len = ea_bits_len;
8308   mp->psid_offset = psid_offset;
8309   mp->psid_length = psid_length;
8310   mp->is_translation = is_translation;
8311   mp->mtu = htons(mtu);
8312
8313   /* send it... */
8314   S;
8315
8316   /* Wait for a reply, return good/bad news  */
8317   W;
8318 }
8319
8320 static int api_map_del_domain (vat_main_t * vam)
8321 {
8322   unformat_input_t *i = vam->input;
8323   vl_api_map_del_domain_t *mp;
8324   f64 timeout;
8325
8326   u32 num_m_args = 0;
8327   u32 index;
8328
8329   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8330     if (unformat (i, "index %d", &index))
8331       num_m_args++;
8332     else {
8333       clib_warning ("parse error '%U'", format_unformat_error, i);
8334       return -99;
8335     }
8336   }
8337
8338   if (num_m_args != 1) {
8339     errmsg("mandatory argument(s) missing\n");
8340     return -99;
8341   }
8342
8343   /* Construct the API message */
8344   M(MAP_DEL_DOMAIN, map_del_domain);
8345
8346   mp->index = ntohl(index);
8347
8348   /* send it... */
8349   S;
8350
8351   /* Wait for a reply, return good/bad news  */
8352   W;
8353 }
8354
8355 static int api_map_add_del_rule (vat_main_t * vam)
8356 {
8357   unformat_input_t *i = vam->input;
8358   vl_api_map_add_del_rule_t *mp;
8359   f64 timeout;
8360   u8 is_add = 1;
8361   ip6_address_t ip6_dst;
8362   u32 num_m_args = 0, index, psid;
8363
8364   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8365     if (unformat (i, "index %d", &index))
8366       num_m_args++;
8367     else if (unformat (i, "psid %d", &psid))
8368       num_m_args++;
8369     else if (unformat (i, "dst %U", unformat_ip6_address, &ip6_dst))
8370       num_m_args++;
8371     else if (unformat (i, "del")) {
8372       is_add = 0;
8373     } else {
8374       clib_warning ("parse error '%U'", format_unformat_error, i);
8375       return -99;
8376     }
8377   }
8378
8379   /* Construct the API message */
8380   M(MAP_ADD_DEL_RULE, map_add_del_rule);
8381
8382   mp->index = ntohl(index);
8383   mp->is_add = is_add;
8384   memcpy(mp->ip6_dst, &ip6_dst, sizeof(ip6_dst));
8385   mp->psid = ntohs(psid);
8386
8387   /* send it... */
8388   S;
8389
8390   /* Wait for a reply, return good/bad news  */
8391   W;
8392 }
8393
8394 static int api_map_domain_dump (vat_main_t * vam)
8395 {
8396     vl_api_map_domain_dump_t *mp;
8397     f64 timeout;
8398
8399     /* Construct the API message */
8400     M(MAP_DOMAIN_DUMP, map_domain_dump);
8401
8402     /* send it... */
8403     S;
8404
8405     /* Use a control ping for synchronization */
8406     {
8407         vl_api_control_ping_t * mp;
8408         M(CONTROL_PING, control_ping);
8409         S;
8410     }
8411     W;
8412 }
8413
8414 static int api_map_rule_dump (vat_main_t * vam)
8415 {
8416     unformat_input_t *i = vam->input;
8417     vl_api_map_rule_dump_t *mp;
8418     f64 timeout;
8419     u32 domain_index = ~0;
8420
8421     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8422         if (unformat (i, "index %u", &domain_index))
8423             ;
8424         else
8425             break;
8426     }
8427
8428     if (domain_index == ~0) {
8429         clib_warning("parse error: domain index expected");
8430         return -99;
8431     }
8432
8433     /* Construct the API message */
8434     M(MAP_RULE_DUMP, map_rule_dump);
8435
8436     mp->domain_index = htonl(domain_index);
8437
8438     /* send it... */
8439     S;
8440
8441     /* Use a control ping for synchronization */
8442     {
8443         vl_api_control_ping_t * mp;
8444         M(CONTROL_PING, control_ping);
8445         S;
8446     }
8447     W;
8448 }
8449
8450 static void vl_api_map_add_domain_reply_t_handler
8451 (vl_api_map_add_domain_reply_t * mp)
8452 {
8453   vat_main_t * vam = &vat_main;
8454   i32 retval = ntohl(mp->retval);
8455
8456   if (vam->async_mode) {
8457       vam->async_errors += (retval < 0);
8458   } else {
8459       vam->retval = retval;
8460       vam->result_ready = 1;
8461   }
8462 }
8463
8464 static void vl_api_map_add_domain_reply_t_handler_json
8465 (vl_api_map_add_domain_reply_t * mp)
8466 {
8467   vat_main_t * vam = &vat_main;
8468   vat_json_node_t node;
8469
8470   vat_json_init_object(&node);
8471   vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
8472   vat_json_object_add_uint(&node, "index", ntohl(mp->index));
8473
8474   vat_json_print(vam->ofp, &node);
8475   vat_json_free(&node);
8476
8477   vam->retval = ntohl(mp->retval);
8478   vam->result_ready = 1;
8479 }
8480
8481 static int
8482 api_get_first_msg_id (vat_main_t * vam)
8483 {
8484     vl_api_get_first_msg_id_t * mp;
8485     f64 timeout;
8486     unformat_input_t * i = vam->input;
8487     u8 * name;
8488     u8 name_set = 0;
8489     
8490     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8491         if (unformat (i, "client %s", &name))
8492             name_set = 1;
8493         else 
8494             break;
8495     }
8496
8497     if (name_set == 0) {
8498         errmsg ("missing client name\n");
8499         return -99;
8500     }
8501     vec_add1 (name, 0);
8502
8503     if (vec_len (name) > 63) {
8504         errmsg ("client name too long\n");
8505         return -99;
8506     }
8507
8508     M(GET_FIRST_MSG_ID, get_first_msg_id);
8509     memcpy (mp->name, name, vec_len(name));
8510     S; W;
8511     /* NOTREACHED */
8512     return 0;
8513 }
8514
8515 static int api_cop_interface_enable_disable (vat_main_t * vam)
8516 {
8517     unformat_input_t * line_input = vam->input;
8518     vl_api_cop_interface_enable_disable_t * mp;
8519     f64 timeout;
8520     u32 sw_if_index = ~0;
8521     u8 enable_disable = 1;
8522
8523     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8524         if (unformat (line_input, "disable"))
8525             enable_disable = 0;
8526         if (unformat (line_input, "enable"))
8527             enable_disable = 1;
8528         else if (unformat (line_input, "%U", unformat_sw_if_index,
8529                            vam, &sw_if_index))
8530             ;
8531         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8532             ;
8533         else
8534             break;
8535     }
8536         
8537     if (sw_if_index == ~0) {
8538         errmsg ("missing interface name or sw_if_index\n");
8539         return -99;
8540     }
8541
8542     /* Construct the API message */
8543     M(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable);
8544     mp->sw_if_index = ntohl(sw_if_index);
8545     mp->enable_disable = enable_disable;
8546
8547     /* send it... */
8548     S;
8549     /* Wait for the reply */
8550     W;
8551 }
8552
8553 static int api_cop_whitelist_enable_disable (vat_main_t * vam)
8554 {
8555     unformat_input_t * line_input = vam->input;
8556     vl_api_cop_whitelist_enable_disable_t * mp;
8557     f64 timeout;
8558     u32 sw_if_index = ~0;
8559     u8 ip4=0, ip6=0, default_cop=0;
8560     u32 fib_id;
8561
8562     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8563         if (unformat (line_input, "ip4"))
8564             ip4 = 1;
8565         else if (unformat (line_input, "ip6"))
8566             ip6 = 1;
8567         else if (unformat (line_input, "default"))
8568             default_cop = 1;
8569         else if (unformat (line_input, "%U", unformat_sw_if_index,
8570                            vam, &sw_if_index))
8571             ;
8572         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8573             ;
8574         else if (unformat (line_input, "fib-id %d", &fib_id))
8575             ;
8576         else
8577             break;
8578     }
8579         
8580     if (sw_if_index == ~0) {
8581         errmsg ("missing interface name or sw_if_index\n");
8582         return -99;
8583     }
8584
8585     /* Construct the API message */
8586     M(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable);
8587     mp->sw_if_index = ntohl(sw_if_index);
8588     mp->fib_id = ntohl(fib_id);
8589     mp->ip4 = ip4;
8590     mp->ip6 = ip6;
8591     mp->default_cop = default_cop;
8592
8593     /* send it... */
8594     S;
8595     /* Wait for the reply */
8596     W;
8597 }
8598
8599 static int api_get_node_graph (vat_main_t * vam)
8600 {
8601     vl_api_get_node_graph_t * mp;
8602     f64 timeout;
8603
8604     M(GET_NODE_GRAPH, get_node_graph);
8605
8606     /* send it... */
8607     S;
8608     /* Wait for the reply */
8609     W;
8610 }
8611
8612 static int q_or_quit (vat_main_t * vam)
8613 {
8614     longjmp (vam->jump_buf, 1);
8615     return 0; /* not so much */
8616 }
8617 static int q (vat_main_t * vam) {return q_or_quit (vam);}
8618 static int quit (vat_main_t * vam) {return q_or_quit (vam);}
8619
8620 static int comment (vat_main_t * vam)
8621 {
8622     return 0;
8623 }
8624
8625 static int cmd_cmp (void * a1, void * a2)
8626 {
8627   u8 ** c1 = a1;
8628   u8 ** c2 = a2;
8629
8630   return strcmp ((char *)(c1[0]), (char *)(c2[0]));
8631 }
8632
8633 static int help (vat_main_t * vam)
8634 {
8635     u8 ** cmds = 0;
8636     u8 * name = 0;
8637     hash_pair_t * p;
8638     unformat_input_t * i = vam->input;
8639     int j;
8640
8641     if (unformat (i, "%s", &name)) {
8642         uword *hs;
8643
8644         vec_add1(name, 0);
8645
8646         hs = hash_get_mem (vam->help_by_name, name);
8647         if (hs)
8648             fformat (vam->ofp, "usage: %s %s\n", name, hs[0]);
8649         else
8650             fformat (vam->ofp, "No such msg / command '%s'\n", name);
8651         vec_free(name);
8652         return 0;
8653     }
8654
8655     fformat(vam->ofp, "Help is available for the following:\n");
8656
8657     hash_foreach_pair (p, vam->function_by_name, 
8658     ({
8659         vec_add1 (cmds, (u8 *)(p->key));
8660     }));
8661
8662     vec_sort_with_function (cmds, cmd_cmp);
8663
8664     for (j = 0; j < vec_len(cmds); j++)
8665         fformat (vam->ofp, "%s\n", cmds[j]);
8666
8667     vec_free (cmds);
8668     return 0;
8669 }
8670
8671 static int set (vat_main_t * vam)
8672 {
8673     u8 * name = 0, * value = 0;
8674     unformat_input_t * i = vam->input;
8675
8676     if (unformat (i, "%s", &name)) {
8677         /* The input buffer is a vector, not a string. */
8678         value = vec_dup (i->buffer);
8679         vec_delete (value, i->index, 0);
8680         /* Almost certainly has a trailing newline */
8681         if (value[vec_len(value)-1] == '\n')
8682             value[vec_len(value)-1] = 0;
8683         /* Make sure it's a proper string, one way or the other */
8684         vec_add1 (value, 0);
8685         (void) clib_macro_set_value (&vam->macro_main, 
8686                                      (char *)name, (char *)value);
8687     }
8688     else
8689         errmsg ("usage: set <name> <value>\n");
8690
8691     vec_free (name);
8692     vec_free (value);
8693     return 0;
8694 }
8695
8696 static int unset (vat_main_t * vam)
8697 {
8698     u8 * name = 0;
8699
8700     if (unformat (vam->input, "%s", &name))
8701         if (clib_macro_unset (&vam->macro_main, (char *)name) == 1)
8702             errmsg ("unset: %s wasn't set\n", name);
8703     vec_free (name);
8704     return 0;
8705 }
8706
8707 typedef struct {
8708     u8 * name;
8709     u8 * value;
8710 } macro_sort_t;
8711
8712
8713 static int macro_sort_cmp (void * a1, void * a2)
8714 {
8715   macro_sort_t * s1 = a1;
8716   macro_sort_t * s2 = a2;
8717
8718   return strcmp ((char *)(s1->name), (char *)(s2->name));
8719 }
8720
8721 static int dump_macro_table (vat_main_t * vam)
8722 {
8723     macro_sort_t * sort_me = 0, * sm;    
8724     int i;
8725     hash_pair_t * p;
8726
8727     hash_foreach_pair (p, vam->macro_main.the_value_table_hash, 
8728     ({
8729         vec_add2 (sort_me, sm, 1);
8730         sm->name = (u8 *)(p->key);
8731         sm->value = (u8 *) (p->value[0]);
8732     }));
8733     
8734     vec_sort_with_function (sort_me, macro_sort_cmp);
8735
8736     if (vec_len(sort_me))
8737         fformat (vam->ofp, "%-15s%s\n", "Name", "Value");
8738     else
8739         fformat (vam->ofp, "The macro table is empty...\n");
8740
8741     for (i = 0; i < vec_len (sort_me); i++)
8742         fformat (vam->ofp, "%-15s%s\n", sort_me[i].name,
8743                  sort_me[i].value);
8744     return 0;
8745 }
8746
8747 static int dump_node_table (vat_main_t * vam)
8748 {
8749     int i, j;
8750     vlib_node_t * node, * next_node;
8751
8752     if (vec_len (vam->graph_nodes) == 0) {
8753         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
8754         return 0;
8755     }
8756
8757     for (i = 0; i < vec_len (vam->graph_nodes); i++) {
8758         node = vam->graph_nodes[i];
8759         fformat (vam->ofp, "[%d] %s\n", i, node->name);
8760         for (j = 0; j < vec_len (node->next_nodes); j++) {
8761             if (node->next_nodes[j] != ~0) {
8762                 next_node = vam->graph_nodes[node->next_nodes[j]];
8763                 fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
8764             }
8765         }
8766     }
8767     return 0;
8768 }
8769
8770 static int search_node_table (vat_main_t * vam)
8771 {
8772     unformat_input_t * line_input = vam->input;
8773     u8 * node_to_find;
8774     int j;
8775     vlib_node_t * node, * next_node;
8776     uword * p;
8777
8778     if (vam->graph_node_index_by_name == 0) {
8779         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
8780         return 0;
8781     }
8782
8783     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8784         if (unformat (line_input, "%s", &node_to_find)) {
8785             vec_add1 (node_to_find, 0);
8786             p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
8787             if (p == 0) {
8788                 fformat (vam->ofp, "%s not found...\n", node_to_find);
8789                 goto out;
8790             }
8791             node = vam->graph_nodes[p[0]];
8792             fformat (vam->ofp, "[%d] %s\n", p[0], node->name);
8793             for (j = 0; j < vec_len (node->next_nodes); j++) {
8794                 if (node->next_nodes[j] != ~0) {
8795                     next_node = vam->graph_nodes[node->next_nodes[j]];
8796                     fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
8797                 }
8798             }
8799         }
8800             
8801         else {
8802             clib_warning ("parse error '%U'", format_unformat_error, 
8803                           line_input);
8804             return -99;
8805         }
8806
8807     out:
8808         vec_free(node_to_find);
8809         
8810     }
8811
8812     return 0;        
8813 }
8814
8815
8816 static int script (vat_main_t * vam)
8817 {
8818     u8 * s = 0;
8819     char * save_current_file;
8820     unformat_input_t save_input;
8821     jmp_buf save_jump_buf;
8822     u32 save_line_number;
8823
8824     FILE * new_fp, * save_ifp;
8825
8826     if (unformat (vam->input, "%s", &s)) {
8827         new_fp = fopen ((char *)s, "r");
8828         if (new_fp == 0) {
8829             errmsg ("Couldn't open script file %s\n", s);
8830             vec_free (s);
8831             return -99;
8832         }
8833     } else {
8834         errmsg ("Missing script name\n");
8835         return -99;
8836     }
8837
8838     memcpy (&save_input, &vam->input, sizeof (save_input));
8839     memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
8840     save_ifp = vam->ifp;
8841     save_line_number = vam->input_line_number;
8842     save_current_file = (char *) vam->current_file;
8843
8844     vam->input_line_number = 0;
8845     vam->ifp = new_fp;
8846     vam->current_file = s;
8847     do_one_file (vam);
8848
8849     memcpy (&vam->input, &save_input, sizeof (vam->input));
8850     memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
8851     vam->ifp = save_ifp;
8852     vam->input_line_number = save_line_number;
8853     vam->current_file = (u8 *) save_current_file;
8854     vec_free (s);
8855
8856     return 0;
8857 }
8858
8859 static int echo (vat_main_t * vam)
8860 {
8861     fformat (vam->ofp, "%v", vam->input->buffer);
8862     return 0;
8863 }
8864
8865 /* List of API message constructors, CLI names map to api_xxx */
8866 #define foreach_vpe_api_msg                                             \
8867 _(create_loopback,"[mac <mac-addr>]")                                   \
8868 _(sw_interface_dump,"")                                                 \
8869 _(sw_interface_set_flags,                                               \
8870   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
8871 _(sw_interface_add_del_address,                                         \
8872   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
8873 _(sw_interface_set_table,                                               \
8874   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
8875 _(sw_interface_set_vpath,                                               \
8876   "<intfc> | sw_if_index <id> enable | disable")                        \
8877 _(sw_interface_set_l2_xconnect,                                         \
8878   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8879   "enable | disable")                                                   \
8880 _(sw_interface_set_l2_bridge,                                           \
8881   "rx <intfc> | rx_sw_if_index <id> bd_id <bridge-domain-id>\n"         \
8882   "[shg <split-horizon-group>] [bvi]\n"                                 \
8883   "enable | disable")                                                   \
8884 _(bridge_domain_add_del,                                                \
8885   "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [del]\n")\
8886 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")     \
8887 _(l2fib_add_del,                                                        \
8888   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi]\n") \
8889 _(l2_flags,                                                             \
8890   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood]\n")       \
8891 _(bridge_flags,                                                         \
8892   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
8893 _(tap_connect,                                                          \
8894   "tapname <name> mac <mac-addr> | random-mac")                         \
8895 _(tap_modify,                                                           \
8896   "<vpp-if-name> | sw_if_index <id> tapname <name> mac <mac-addr> | random-mac") \
8897 _(tap_delete,                                                           \
8898   "<vpp-if-name> | sw_if_index <id>")                                   \
8899 _(sw_interface_tap_dump, "")                                            \
8900 _(ip_add_del_route,                                                     \
8901   "<addr>/<mask> via <addr> [vrf <n>]\n"                                \
8902   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
8903   "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
8904   "[multipath] [count <n>]")                                            \
8905 _(proxy_arp_add_del,                                                    \
8906   "<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]")                      \
8907 _(proxy_arp_intfc_enable_disable,                                       \
8908   "<intfc> | sw_if_index <id> enable | disable")                        \
8909 _(mpls_add_del_encap,                                                   \
8910   "label <n> dst <ip4-addr> [vrf <n>] [del]")                           \
8911 _(mpls_add_del_decap,                                                   \
8912   "label <n> [rx_vrf_id <n>] [tx_vrf_id] [s-bit-clear][del]")           \
8913 _(mpls_gre_add_del_tunnel,                                              \
8914   "inner_vrf_id <n> outer_vrf_id <n> src <ip4-address> dst <ip4-address>\n" \
8915   "adj <ip4-address>/<mask-width> [del]")                               \
8916 _(sw_interface_set_unnumbered,                                          \
8917   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
8918 _(ip_neighbor_add_del,                                                  \
8919   "<intfc> | sw_if_index <id> dst <ip46-address> mac <mac-addr>")       \
8920 _(reset_vrf, "vrf <id> [ipv6]")                                         \
8921 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
8922 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
8923   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
8924   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
8925   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
8926 _(oam_add_del, "src <ip4-address> dst <ip4-address> [vrf <n>] [del]")   \
8927 _(reset_fib, "vrf <n> [ipv6]")                                          \
8928 _(dhcp_proxy_config,                                                    \
8929   "svr <v46-address> src <v46-address>\n"                               \
8930    "insert-cid <n> [del]")                                              \
8931 _(dhcp_proxy_config_2,                                                  \
8932   "svr <v46-address> src <v46-address>\n"                               \
8933    "rx_vrf_id <nn> server_vrf_id <nn> insert-cid <n> [del]")            \
8934 _(dhcp_proxy_set_vss,                                                   \
8935   "tbl_id <n> fib_id <n> oui <n> [ipv6] [del]")                         \
8936 _(dhcp_client_config,                                                   \
8937   "<intfc> | sw_if_index <id> [hostname <name>] [disable_event] [del]") \
8938 _(set_ip_flow_hash,                                                     \
8939   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
8940 _(sw_interface_ip6_enable_disable,                                      \
8941   "<intfc> | sw_if_index <id> enable | disable")                        \
8942 _(sw_interface_ip6_set_link_local_address,                              \
8943   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>")              \
8944 _(sw_interface_ip6nd_ra_prefix,                                         \
8945   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>\n"             \
8946   "val_life <n> pref_life <n> [def] [noadv] [offl] [noauto]\n"          \
8947   "[nolink] [isno]")                                                    \
8948 _(sw_interface_ip6nd_ra_config,                                         \
8949   "<intfc> | sw_if_index <id> [maxint <n>] [minint <n>]\n"              \
8950   "[life <n>] [count <n>] [interval <n>] [surpress]\n"                  \
8951   "[managed] [other] [ll] [send] [cease] [isno] [def]")                 \
8952 _(set_arp_neighbor_limit, "arp_nbr_limit <n> [ipv6]")                   \
8953 _(l2_patch_add_del,                                                     \
8954   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8955   "enable | disable")                                                   \
8956 _(mpls_ethernet_add_del_tunnel,                                         \
8957   "tx <intfc> | tx_sw_if_index <n> dst <mac-addr>\n"                    \
8958   "adj <ip4-addr>/<mw> dst <mac-addr> [del]")                           \
8959 _(mpls_ethernet_add_del_tunnel_2,                                       \
8960   "inner_vrf_id <n> outer_vrf_id <n> next-hop <ip4-addr>\n"             \
8961   "resolve-attempts <n> resolve-if-needed 0 | 1 [del]")                 \
8962 _(sr_tunnel_add_del,                                                    \
8963   "src <ip6-addr> dst <ip6-addr>/<mw> (next <ip6-addr>)+\n"             \
8964   " [tag <ip6-addr>]* [clean] [reroute]")                               \
8965 _(classify_add_del_table,                                               \
8966   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
8967   "[del] mask <mask-value>\n"                                           \
8968   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>")              \
8969 _(classify_add_del_session,                                             \
8970   "[hit-next|l2-hit-next|acl-hit-next] <name|nn> table-index <nn>\n"    \
8971   "skip_n <nn> match_n <nn> match [hex] [l2] [l3 [ip4|ip6]]")           \
8972 _(classify_set_interface_ip_table,                                      \
8973   "<intfc> | sw_if_index <nn> table <nn>")                              \
8974 _(classify_set_interface_l2_tables,                                     \
8975   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
8976   "  [other-table <nn>]")                                               \
8977 _(get_node_index, "node <node-name")                                    \
8978 _(add_node_next, "node <node-name> next <next-node-name>")              \
8979 _(l2tpv3_create_tunnel,                                                 \
8980   "client_address <ip6-addr> our_address <ip6-addr>\n"                  \
8981   "[local_session_id <nn>][remote_session_id <nn>][local_cookie <nn>]\n"\
8982   "[remote_cookie <nn>]\n[l2-sublayer-preset]\n")                       \
8983 _(l2tpv3_set_tunnel_cookies,                                            \
8984   "<intfc> | sw_if_index <nn> [new_local_cookie <nn>]\n"                \
8985   "[new_remote_cookie <nn>]\n")                                         \
8986 _(l2tpv3_interface_enable_disable,                                      \
8987   "<intfc> | sw_if_index <nn> enable | disable")                        \
8988 _(l2tpv3_set_lookup_key,                                                \
8989   "lookup_v6_src | lookup_v6_dst | lookup_session_id")                  \
8990 _(sw_if_l2tpv3_tunnel_dump, "")                                         \
8991 _(vxlan_add_del_tunnel,                                                 \
8992   "src <ip4-addr> dst <ip4-addr> vni [encap-vrf-id <nn>]\n"             \
8993   " [decap-next l2|ip4|ip6] [del]")                                     \
8994 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
8995 _(l2_fib_clear_table, "")                                               \
8996 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
8997 _(l2_interface_vlan_tag_rewrite,                                        \
8998   "<intfc> | sw_if_index <nn> \n"                                       \
8999   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
9000   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
9001 _(create_vhost_user_if,                                                 \
9002         "socket <filename> [server] [renumber <dev_instance>] "         \
9003         "[mac <mac_address>]")                                          \
9004 _(modify_vhost_user_if,                                                 \
9005         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
9006         "[server] [renumber <dev_instance>]")                           \
9007 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
9008 _(sw_interface_vhost_user_dump, "")                                     \
9009 _(show_version, "")                                                     \
9010 _(nsh_gre_add_del_tunnel,                                               \
9011   "src <ip4-addr> dst <ip4-addr>"                                       \
9012   "c1 <nn> c2 <nn> c3 <nn> c4 <nn> spi <nn> si <nn>\n"                  \
9013   "[encap-fib-id <nn>] [decap-fib-id <nn>] [o-bit <1|0>]\n"             \
9014   "[c-bit <1|0>] [md-type <nn>][next-ip4][next-ip6][next-ethernet]\n"   \
9015   "[tlv <xx>][del]")                                                    \
9016 _(nsh_vxlan_gpe_add_del_tunnel,                                         \
9017   "src <ip4-addr> dst <ip4-addr> vni <nn>\n"                            \
9018   "c1 <nn> c2 <nn> c3 <nn> c4 <nn> spi <nn> si <nn>\n"                  \
9019   "[encap-vrf-id <nn>] [decap-vrf-id <nn>] [o-bit <1|0>]\n"             \
9020   "[c-bit <1|0>] [md-type <nn>][next-ip4][next-ip6][next-ethernet]\n"   \
9021   "[tlv <xx>][del]")                                                    \
9022 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
9023 _(lisp_gpe_add_del_tunnel,                                              \
9024   "src <ip4-addr> dst <ip4-addr> iid <nn>|iidx <0xnn>\n"                \
9025   "[encap-vrf-id <nn>] [decap-vrf-id <nn>]\n"                           \
9026   "[n-bit][l-bit][e-bit][v-bit][i-bit][p-bit][not-p-bit][o-bit]\n"      \
9027   "[next-ip4][next-ip6][next-ethernet][next-nsh]\n"                     \
9028   "[decap-next [ip4|ip6|ethernet|nsh-encap|<nn>]][del]")                \
9029 _(interface_name_renumber,                                              \
9030   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
9031 _(input_acl_set_interface,                                              \
9032   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
9033   "  [l2-table <nn>] [del]")                                            \
9034 _(want_ip4_arp_events, "address <ip4-address> [del]")                   \
9035 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
9036 _(ip_dump, "ipv4 | ipv6")                                               \
9037 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
9038 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
9039   "  spid_id <n> ")                                                     \
9040 _(ipsec_sad_add_del_entry, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
9041   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
9042   "  integ_alg <alg> integ_key <hex>")                                  \
9043 _(ipsec_spd_add_del_entry, "spd_id <n> priority <n> action <action>\n"  \
9044   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
9045   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
9046   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" )\
9047 _(ipsec_sa_set_key, "sa_id <n> crypto_key <hex> integ_key <hex>")       \
9048 _(delete_loopback,"sw_if_index <nn>")                                   \
9049 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
9050 _(map_add_domain,                                                       \
9051   "ip4-pfx <ip4pfx> ip6-pfx <ip6pfx> "                                  \
9052   "ip6-src <ip6addr> "                                                  \
9053   "ea-bits-len <n> psid-offset <n> psid-len <n>")                       \
9054 _(map_del_domain, "index <n>")                                          \
9055 _(map_add_del_rule,                                                     \
9056   "index <n> psid <n> dst <ip6addr> [del]")                             \
9057 _(map_domain_dump, "")                                                  \
9058 _(map_rule_dump, "index <map-domain>")                                  \
9059 _(want_interface_events,  "enable|disable")                             \
9060 _(want_stats,"enable|disable")                                          \
9061 _(get_first_msg_id, "client <name>")                                    \
9062 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
9063 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
9064   "fib-id <nn> [ip4][ip6][default]")                                    \
9065 _(get_node_graph, " ")
9066
9067 /* List of command functions, CLI names map directly to functions */
9068 #define foreach_cli_function                                    \
9069 _(comment, "usage: comment <ignore-rest-of-line>")              \
9070 _(dump_interface_table, "usage: dump_interface_table")          \
9071 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
9072 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
9073 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
9074 _(dump_stats_table, "usage: dump_stats_table")                  \
9075 _(dump_macro_table, "usage: dump_macro_table ")                 \
9076 _(dump_node_table, "usage: dump_node_table")                    \
9077 _(echo, "usage: echo <message>")                                \
9078 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
9079 _(help, "usage: help")                                          \
9080 _(q, "usage: quit")                                             \
9081 _(quit, "usage: quit")                                          \
9082 _(search_node_table, "usage: search_node_table <name>...")      \
9083 _(set, "usage: set <variable-name> <value>")                    \
9084 _(script, "usage: script <file-name>")                          \
9085 _(unset, "usage: unset <variable-name>")
9086
9087 #define _(N,n)                                  \
9088     static void vl_api_##n##_t_handler_uni      \
9089     (vl_api_##n##_t * mp)                       \
9090     {                                           \
9091         vat_main_t * vam = &vat_main;           \
9092         if (vam->json_output) {                 \
9093             vl_api_##n##_t_handler_json(mp);    \
9094         } else {                                \
9095             vl_api_##n##_t_handler(mp);         \
9096         }                                       \
9097     }
9098 foreach_vpe_api_reply_msg;
9099 #undef _
9100
9101 void vat_api_hookup (vat_main_t *vam)
9102 {
9103 #define _(N,n)                                                  \
9104     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
9105                            vl_api_##n##_t_handler_uni,          \
9106                            vl_noop_handler,                     \
9107                            vl_api_##n##_t_endian,               \
9108                            vl_api_##n##_t_print,                \
9109                            sizeof(vl_api_##n##_t), 1); 
9110     foreach_vpe_api_reply_msg;
9111 #undef _
9112
9113     vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
9114
9115     vam->sw_if_index_by_interface_name = 
9116         hash_create_string (0, sizeof (uword));
9117
9118     vam->function_by_name = 
9119         hash_create_string (0, sizeof(uword));
9120
9121     vam->help_by_name = 
9122         hash_create_string (0, sizeof(uword));
9123
9124     /* API messages we can send */
9125 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
9126     foreach_vpe_api_msg;
9127 #undef _
9128
9129     /* Help strings */
9130 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
9131     foreach_vpe_api_msg;
9132 #undef _
9133
9134     /* CLI functions */
9135 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
9136     foreach_cli_function;
9137 #undef _
9138
9139     /* Help strings */
9140 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
9141     foreach_cli_function;
9142 #undef _
9143 }
9144
9145 #undef vl_api_version
9146 #define vl_api_version(n,v) static u32 vpe_api_version = v;
9147 #include <api/vpe.api.h>
9148 #undef vl_api_version
9149
9150 void vl_client_add_api_signatures (vl_api_memclnt_create_t *mp) 
9151 {
9152     /* 
9153      * Send the main API signature in slot 0. This bit of code must
9154      * match the checks in ../vpe/api/api.c: vl_msg_api_version_check().
9155      */
9156     mp->api_versions[0] = clib_host_to_net_u32 (vpe_api_version);
9157 }