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