0c0a65e0dd3a94fb499c630f7144af695f0543bb
[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             fformat (vam->ofp, "%s", vam->shmem_result);
2432             pthread_mutex_lock (&am->vlib_rp->mutex);
2433             oldheap = svm_push_data_heap (am->vlib_rp);
2434             
2435             free_me = (u8 *)vam->shmem_result;
2436             vec_free (free_me);
2437
2438             svm_pop_heap (oldheap);
2439             pthread_mutex_unlock (&am->vlib_rp->mutex);
2440             return 0;
2441         }
2442     }
2443     return -99;
2444 }
2445
2446 static int api_create_loopback (vat_main_t * vam)
2447 {
2448     unformat_input_t * i = vam->input;
2449     vl_api_create_loopback_t *mp;
2450     f64 timeout;
2451     u8 mac_address[6];
2452     u8 mac_set = 0;
2453
2454     memset (mac_address, 0, sizeof (mac_address));
2455
2456     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2457       {
2458         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
2459             mac_set = 1;
2460         else
2461           break;
2462       }
2463
2464     /* Construct the API message */
2465     M(CREATE_LOOPBACK, create_loopback);
2466     if (mac_set)
2467         memcpy (mp->mac_address, mac_address, sizeof (mac_address));
2468
2469     S; W;
2470 }
2471
2472 static int api_delete_loopback (vat_main_t * vam)
2473 {
2474     unformat_input_t * i = vam->input;
2475     vl_api_delete_loopback_t *mp;
2476     f64 timeout;
2477     u32 sw_if_index = ~0;
2478
2479     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2480       {
2481         if (unformat (i, "sw_if_index %d", &sw_if_index))
2482           ;
2483         else
2484           break;
2485       }
2486
2487     if (sw_if_index == ~0)
2488       {
2489         errmsg ("missing sw_if_index\n");
2490         return -99;
2491       }
2492
2493     /* Construct the API message */
2494     M(DELETE_LOOPBACK, delete_loopback);
2495     mp->sw_if_index = ntohl (sw_if_index);
2496
2497     S; W;
2498 }
2499
2500 static int api_want_stats (vat_main_t * vam)
2501 {
2502     unformat_input_t * i = vam->input;
2503     vl_api_want_stats_t * mp;
2504     f64 timeout;
2505     int enable = -1;
2506
2507     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2508       {
2509         if (unformat (i, "enable"))
2510           enable = 1;
2511         else if (unformat (i, "disable"))
2512           enable = 0;
2513         else
2514           break;
2515       }
2516
2517     if (enable == -1)
2518       {
2519         errmsg ("missing enable|disable\n");
2520         return -99;
2521       }
2522
2523     M(WANT_STATS, want_stats);
2524     mp->enable_disable = enable;
2525
2526     S; W;
2527 }
2528
2529 static int api_want_interface_events (vat_main_t * vam)
2530 {
2531     unformat_input_t * i = vam->input;
2532     vl_api_want_interface_events_t * mp;
2533     f64 timeout;
2534     int enable = -1;
2535
2536     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2537       {
2538         if (unformat (i, "enable"))
2539           enable = 1;
2540         else if (unformat (i, "disable"))
2541           enable = 0;
2542         else
2543           break;
2544       }
2545
2546     if (enable == -1)
2547       {
2548         errmsg ("missing enable|disable\n");
2549         return -99;
2550       }
2551
2552     M(WANT_INTERFACE_EVENTS, want_interface_events);
2553     mp->enable_disable = enable;
2554
2555     vam->interface_event_display = enable;
2556
2557     S; W;
2558 }
2559
2560
2561 /* Note: non-static, called once to set up the initial intfc table */
2562 int api_sw_interface_dump (vat_main_t * vam)
2563 {
2564     vl_api_sw_interface_dump_t *mp;
2565     f64 timeout;
2566     hash_pair_t * p;
2567     name_sort_t * nses = 0, * ns;
2568     sw_interface_subif_t * sub = NULL;
2569
2570     /* Toss the old name table */
2571     hash_foreach_pair (p, vam->sw_if_index_by_interface_name, 
2572     ({
2573         vec_add2 (nses, ns, 1);
2574         ns->name = (u8 *)(p->key);
2575         ns->value = (u32) p->value[0];
2576     }));
2577
2578     hash_free (vam->sw_if_index_by_interface_name);
2579
2580     vec_foreach (ns, nses)
2581         vec_free (ns->name);
2582
2583     vec_free (nses);
2584
2585     vec_foreach (sub, vam->sw_if_subif_table) {
2586         vec_free (sub->interface_name);
2587     }
2588     vec_free (vam->sw_if_subif_table);
2589
2590     /* recreate the interface name hash table */
2591     vam->sw_if_index_by_interface_name 
2592         = hash_create_string (0, sizeof(uword));
2593
2594     /* Get list of ethernets */
2595     M(SW_INTERFACE_DUMP, sw_interface_dump);
2596     mp->name_filter_valid = 1;
2597     strncpy ((char *) mp->name_filter, "Ether", sizeof(mp->name_filter-1)); 
2598     S;
2599
2600     /* and local / loopback interfaces */
2601     M(SW_INTERFACE_DUMP, sw_interface_dump);
2602     mp->name_filter_valid = 1;
2603     strncpy ((char *) mp->name_filter, "lo", sizeof(mp->name_filter-1)); 
2604     S;
2605
2606     /* and vxlan tunnel interfaces */
2607     M(SW_INTERFACE_DUMP, sw_interface_dump);
2608     mp->name_filter_valid = 1;
2609     strncpy ((char *) mp->name_filter, "vxlan", sizeof(mp->name_filter-1)); 
2610     S;
2611
2612     /* and l2tpv3 tunnel interfaces */
2613     M(SW_INTERFACE_DUMP, sw_interface_dump);
2614     mp->name_filter_valid = 1;
2615     strncpy ((char *) mp->name_filter, "l2tpv3_tunnel", sizeof(mp->name_filter-1));
2616     S;
2617
2618     /* Use a control ping for synchronization */
2619     {
2620         vl_api_control_ping_t * mp;
2621         M(CONTROL_PING, control_ping);
2622         S;
2623     }
2624     W;
2625 }
2626
2627 static int api_sw_interface_set_flags (vat_main_t * vam)
2628 {
2629     unformat_input_t * i = vam->input;
2630     vl_api_sw_interface_set_flags_t *mp;
2631     f64 timeout;
2632     u32 sw_if_index;
2633     u8 sw_if_index_set = 0;
2634     u8 admin_up = 0, link_up = 0;
2635     
2636     /* Parse args required to build the message */
2637     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2638         if (unformat (i, "admin-up"))
2639             admin_up = 1;
2640         else if (unformat (i, "admin-down"))
2641             admin_up = 0;
2642         else if (unformat (i, "link-up"))
2643             link_up = 1;
2644         else if (unformat (i, "link-down"))
2645             link_up = 0;
2646         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2647             sw_if_index_set = 1;
2648         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2649             sw_if_index_set = 1;
2650         else
2651             break;
2652     }
2653
2654     if (sw_if_index_set == 0) {
2655         errmsg ("missing interface name or sw_if_index\n");
2656         return -99;
2657     }
2658
2659     /* Construct the API message */
2660     M(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags);
2661     mp->sw_if_index = ntohl (sw_if_index);
2662     mp->admin_up_down = admin_up;
2663     mp->link_up_down = link_up;
2664
2665     /* send it... */
2666     S;
2667
2668     /* Wait for a reply, return the good/bad news... */
2669     W;
2670 }
2671
2672 static int api_sw_interface_add_del_address (vat_main_t * vam)
2673 {
2674     unformat_input_t * i = vam->input;
2675     vl_api_sw_interface_add_del_address_t *mp;
2676     f64 timeout;
2677     u32 sw_if_index;
2678     u8 sw_if_index_set = 0;
2679     u8 is_add = 1, del_all = 0;
2680     u32 address_length = 0;
2681     u8 v4_address_set = 0;
2682     u8 v6_address_set = 0;
2683     ip4_address_t v4address;
2684     ip6_address_t v6address;
2685     
2686     /* Parse args required to build the message */
2687     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2688         if (unformat (i, "del-all"))
2689             del_all = 1;
2690         else if (unformat (i, "del"))
2691             is_add = 0;
2692         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2693             sw_if_index_set = 1;
2694         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2695             sw_if_index_set = 1;
2696         else if (unformat (i, "%U/%d", 
2697                            unformat_ip4_address, &v4address, 
2698                            &address_length))
2699             v4_address_set = 1;
2700         else if (unformat (i, "%U/%d", 
2701                            unformat_ip6_address, &v6address, 
2702                            &address_length))
2703             v6_address_set = 1;
2704         else
2705             break;
2706     }
2707
2708     if (sw_if_index_set == 0) {
2709         errmsg ("missing interface name or sw_if_index\n");
2710         return -99;
2711     }
2712     if (v4_address_set && v6_address_set) {
2713         errmsg ("both v4 and v6 addresses set\n");
2714         return -99;
2715     }
2716     if (!v4_address_set && !v6_address_set && !del_all) {
2717         errmsg ("no addresses set\n");
2718         return -99;
2719     }
2720
2721     /* Construct the API message */
2722     M(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address);
2723
2724     mp->sw_if_index = ntohl (sw_if_index);
2725     mp->is_add = is_add;
2726     mp->del_all = del_all;
2727     if (v6_address_set) {
2728         mp->is_ipv6 = 1;
2729         memcpy (mp->address, &v6address, sizeof (v6address));
2730     } else {
2731         memcpy (mp->address, &v4address, sizeof (v4address));
2732     }
2733     mp->address_length = address_length;
2734
2735     /* send it... */
2736     S;
2737
2738     /* Wait for a reply, return good/bad news  */
2739     W;
2740 }
2741
2742 static int api_sw_interface_set_table (vat_main_t * vam)
2743 {
2744     unformat_input_t * i = vam->input;
2745     vl_api_sw_interface_set_table_t *mp;
2746     f64 timeout;
2747     u32 sw_if_index, vrf_id = 0;
2748     u8 sw_if_index_set = 0;
2749     u8 is_ipv6 = 0;
2750     
2751     /* Parse args required to build the message */
2752     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2753         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2754             sw_if_index_set = 1;
2755         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2756             sw_if_index_set = 1;
2757         else if (unformat (i, "vrf %d", &vrf_id))
2758             ;
2759         else if (unformat (i, "ipv6"))
2760             is_ipv6 = 1;
2761         else
2762             break;
2763     }
2764
2765     if (sw_if_index_set == 0) {
2766         errmsg ("missing interface name or sw_if_index\n");
2767         return -99;
2768     }
2769
2770     /* Construct the API message */
2771     M(SW_INTERFACE_SET_TABLE, sw_interface_set_table);
2772
2773     mp->sw_if_index = ntohl (sw_if_index);
2774     mp->is_ipv6 = is_ipv6;
2775     mp->vrf_id = ntohl (vrf_id);
2776
2777     /* send it... */
2778     S;
2779
2780     /* Wait for a reply... */
2781     W;
2782 }
2783
2784 static int api_sw_interface_set_vpath (vat_main_t * vam)
2785 {
2786     unformat_input_t * i = vam->input;
2787     vl_api_sw_interface_set_vpath_t *mp;
2788     f64 timeout;
2789     u32 sw_if_index = 0;
2790     u8 sw_if_index_set = 0;
2791     u8 is_enable = 0;
2792     
2793     /* Parse args required to build the message */
2794     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2795         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
2796             sw_if_index_set = 1;
2797         else if (unformat (i, "sw_if_index %d", &sw_if_index))
2798             sw_if_index_set = 1;
2799         else if (unformat (i, "enable"))
2800             is_enable = 1;
2801         else if (unformat (i, "disable"))
2802             is_enable = 0;
2803         else
2804             break;
2805     }
2806
2807     if (sw_if_index_set == 0) {
2808         errmsg ("missing interface name or sw_if_index\n");
2809         return -99;
2810     }
2811
2812     /* Construct the API message */
2813     M(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath);
2814
2815     mp->sw_if_index = ntohl (sw_if_index);
2816     mp->enable = is_enable;
2817
2818     /* send it... */
2819     S;
2820
2821     /* Wait for a reply... */
2822     W;
2823 }
2824
2825 static int api_sw_interface_set_l2_xconnect (vat_main_t * vam)
2826 {
2827     unformat_input_t * i = vam->input;
2828     vl_api_sw_interface_set_l2_xconnect_t *mp;
2829     f64 timeout;
2830     u32 rx_sw_if_index;
2831     u8 rx_sw_if_index_set = 0;
2832     u32 tx_sw_if_index;
2833     u8 tx_sw_if_index_set = 0;
2834     u8 enable = 1;
2835     
2836     /* Parse args required to build the message */
2837     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2838         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
2839             rx_sw_if_index_set = 1;     
2840         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
2841             tx_sw_if_index_set = 1;
2842         else if (unformat (i, "rx")) {
2843             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2844                 if (unformat (i, "%U", unformat_sw_if_index, vam,
2845                               &rx_sw_if_index))
2846                     rx_sw_if_index_set = 1;
2847             } else
2848                 break;
2849         } else if (unformat (i, "tx")) {
2850             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2851                 if (unformat (i, "%U", unformat_sw_if_index, vam,
2852                               &tx_sw_if_index))
2853                     tx_sw_if_index_set = 1;
2854             } else
2855                 break;
2856         } else if (unformat (i, "enable"))
2857             enable = 1;
2858         else if (unformat (i, "disable")) 
2859             enable = 0;
2860         else
2861             break;
2862     }
2863
2864     if (rx_sw_if_index_set == 0) {
2865         errmsg ("missing rx interface name or rx_sw_if_index\n");
2866         return -99;
2867     }
2868
2869     if (enable && (tx_sw_if_index_set == 0)) {
2870         errmsg ("missing tx interface name or tx_sw_if_index\n");
2871         return -99;
2872     }
2873     
2874     M(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect);
2875
2876     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
2877     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
2878     mp->enable = enable;
2879
2880     S; W;
2881     /* NOTREACHED */
2882     return 0;
2883 }
2884
2885 static int api_sw_interface_set_l2_bridge (vat_main_t * vam)
2886 {
2887     unformat_input_t * i = vam->input;
2888     vl_api_sw_interface_set_l2_bridge_t *mp;
2889     f64 timeout;
2890     u32 rx_sw_if_index;
2891     u8 rx_sw_if_index_set = 0;
2892     u32 bd_id;
2893     u8 bd_id_set = 0;
2894     u8 bvi = 0;
2895     u32 shg = 0;
2896     u8 enable = 1;
2897     
2898     /* Parse args required to build the message */
2899     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2900         if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
2901             rx_sw_if_index_set = 1;     
2902         else if (unformat (i, "bd_id %d", &bd_id))
2903             bd_id_set = 1;
2904         else if (unformat (i, "%U", unformat_sw_if_index, vam,
2905                            &rx_sw_if_index))
2906             rx_sw_if_index_set = 1;
2907         else if (unformat (i, "shg %d", &shg)) 
2908             ;
2909         else if (unformat (i, "bvi"))
2910             bvi = 1;
2911         else if (unformat (i, "enable"))
2912             enable = 1;
2913         else if (unformat (i, "disable")) 
2914             enable = 0;
2915         else
2916             break;
2917     }
2918
2919     if (rx_sw_if_index_set == 0) {
2920         errmsg ("missing rx interface name or sw_if_index\n");
2921         return -99;
2922     }
2923
2924     if (enable && (bd_id_set == 0)) {
2925         errmsg ("missing bridge domain\n");
2926         return -99;
2927     }
2928     
2929     M(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge);
2930
2931     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
2932     mp->bd_id = ntohl(bd_id);
2933     mp->shg = (u8)shg;
2934     mp->bvi = bvi;
2935     mp->enable = enable;
2936
2937     S; W;
2938     /* NOTREACHED */
2939     return 0;
2940 }
2941
2942 static int api_bridge_domain_dump (vat_main_t * vam)
2943 {
2944     unformat_input_t * i = vam->input;
2945     vl_api_bridge_domain_dump_t *mp;
2946     f64 timeout;
2947     u32 bd_id = ~0;
2948
2949     /* Parse args required to build the message */
2950     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2951         if (unformat (i, "bd_id %d", &bd_id))
2952             ;
2953         else
2954             break;
2955     }
2956
2957     M(BRIDGE_DOMAIN_DUMP, bridge_domain_dump);
2958     mp->bd_id = ntohl(bd_id);
2959     S;
2960
2961     /* Use a control ping for synchronization */
2962     {
2963         vl_api_control_ping_t * mp;
2964         M(CONTROL_PING, control_ping);
2965         S;
2966     }
2967
2968     W;
2969     /* NOTREACHED */
2970     return 0;
2971 }
2972
2973 static int api_bridge_domain_add_del (vat_main_t * vam)
2974 {
2975     unformat_input_t * i = vam->input;
2976     vl_api_bridge_domain_add_del_t *mp;
2977     f64 timeout;
2978     u32 bd_id = ~0;
2979     u8 is_add = 1;
2980     u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
2981
2982     /* Parse args required to build the message */
2983     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
2984         if (unformat (i, "bd_id %d", &bd_id))
2985             ;
2986         else if (unformat (i, "flood %d", &flood))
2987              ;
2988         else if (unformat (i, "uu-flood %d", &uu_flood))
2989              ;
2990         else if (unformat (i, "forward %d", &forward))
2991              ;
2992         else if (unformat (i, "learn %d", &learn))
2993              ;
2994         else if (unformat (i, "arp-term %d", &arp_term))
2995              ;
2996         else if (unformat (i, "del")) {
2997              is_add = 0;
2998              flood = uu_flood = forward = learn = 0;
2999         }
3000         else
3001             break;
3002     }
3003
3004     if (bd_id == ~0) {
3005         errmsg ("missing bridge domain\n");
3006         return -99;
3007     }
3008
3009     M(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del);
3010
3011     mp->bd_id = ntohl(bd_id);
3012     mp->flood = flood;
3013     mp->uu_flood = uu_flood;
3014     mp->forward = forward;
3015     mp->learn = learn;
3016     mp->arp_term = arp_term;
3017     mp->is_add = is_add;
3018
3019     S; W;
3020     /* NOTREACHED */
3021     return 0;
3022 }
3023
3024 static int api_l2fib_add_del (vat_main_t * vam)
3025 {
3026     unformat_input_t * i = vam->input;
3027     vl_api_l2fib_add_del_t *mp;
3028     f64 timeout;
3029     u64 mac = 0;
3030     u8 mac_set = 0;
3031     u32 bd_id;
3032     u8 bd_id_set = 0;
3033     u32 sw_if_index;
3034     u8 sw_if_index_set = 0;
3035     u8 is_add = 1;
3036     u8 static_mac = 0;
3037     u8 filter_mac = 0;
3038
3039     /* Parse args required to build the message */
3040     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3041         if (unformat (i, "mac %U", unformat_ethernet_address, &mac))
3042             mac_set = 1;
3043         else if (unformat (i, "bd_id %d", &bd_id))
3044             bd_id_set = 1;
3045         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3046             sw_if_index_set = 1;        
3047         else if (unformat (i, "sw_if")) {
3048             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3049                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3050                     sw_if_index_set = 1;
3051             } else
3052                 break;
3053         } else if (unformat (i, "static"))
3054                 static_mac = 1;
3055         else if (unformat (i, "filter")) {
3056                 filter_mac = 1;
3057                 static_mac = 1;
3058         } else if (unformat (i, "del"))
3059                 is_add = 0;
3060         else
3061             break;
3062     }
3063
3064     if (mac_set == 0) {
3065         errmsg ("missing mac address\n");
3066         return -99;
3067     }
3068
3069     if (bd_id_set == 0) {
3070         errmsg ("missing bridge domain\n");
3071         return -99;
3072     }
3073
3074     if (is_add && (sw_if_index_set == 0)) {
3075         errmsg ("missing interface name or sw_if_index\n");
3076         return -99;
3077     }
3078
3079     M(L2FIB_ADD_DEL, l2fib_add_del);
3080
3081     mp->mac = mac;
3082     mp->bd_id = ntohl(bd_id);
3083     mp->is_add = is_add;
3084
3085     if (is_add) {
3086         mp->sw_if_index = ntohl(sw_if_index);
3087         mp->static_mac = static_mac;
3088         mp->filter_mac = filter_mac;
3089     }
3090     
3091     S; W;
3092     /* NOTREACHED */
3093     return 0;
3094 }
3095
3096 static int api_l2_flags (vat_main_t * vam)
3097 {
3098     unformat_input_t * i = vam->input;
3099     vl_api_l2_flags_t *mp;
3100     f64 timeout;
3101     u32 sw_if_index;
3102     u32 feature_bitmap = 0;
3103     u8 sw_if_index_set = 0;
3104
3105     /* Parse args required to build the message */
3106     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3107         if (unformat (i, "sw_if_index %d", &sw_if_index))
3108             sw_if_index_set = 1;        
3109         else if (unformat (i, "sw_if")) {
3110             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3111                 if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3112                     sw_if_index_set = 1;
3113             } else
3114                 break;
3115         } else if (unformat (i, "learn"))
3116             feature_bitmap |= L2INPUT_FEAT_LEARN;
3117         else if (unformat (i, "forward"))
3118             feature_bitmap |= L2INPUT_FEAT_FWD;
3119         else if (unformat (i, "flood"))
3120             feature_bitmap |= L2INPUT_FEAT_FLOOD;
3121         else if (unformat (i, "uu-flood"))
3122             feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
3123         else
3124             break;
3125     }
3126
3127     if (sw_if_index_set == 0) {
3128         errmsg ("missing interface name or sw_if_index\n");
3129         return -99;
3130     }
3131
3132     M(L2_FLAGS, l2_flags);
3133
3134     mp->sw_if_index = ntohl(sw_if_index);
3135     mp->feature_bitmap = ntohl(feature_bitmap);
3136
3137     S; W;
3138     /* NOTREACHED */
3139     return 0;
3140 }
3141
3142 static int api_bridge_flags (vat_main_t * vam)
3143 {
3144     unformat_input_t * i = vam->input;
3145     vl_api_bridge_flags_t *mp;
3146     f64 timeout;
3147     u32 bd_id;
3148     u8 bd_id_set = 0;
3149     u8 is_set = 1;
3150     u32 flags = 0;
3151
3152     /* Parse args required to build the message */
3153     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3154         if (unformat (i, "bd_id %d", &bd_id))
3155             bd_id_set = 1;
3156         else if (unformat (i, "learn"))
3157             flags |= L2_LEARN;
3158         else if (unformat (i, "forward"))
3159             flags |= L2_FWD;
3160         else if (unformat (i, "flood"))
3161             flags |= L2_FLOOD;
3162         else if (unformat (i, "uu-flood"))
3163             flags |= L2_UU_FLOOD;
3164         else if (unformat (i, "arp-term"))
3165             flags |= L2_ARP_TERM;
3166         else if (unformat (i, "off"))
3167             is_set = 0;
3168         else if (unformat (i, "disable"))
3169             is_set = 0;
3170         else
3171             break;
3172     }
3173
3174     if (bd_id_set == 0) {
3175         errmsg ("missing bridge domain\n");
3176         return -99;
3177     }
3178
3179     M(BRIDGE_FLAGS, bridge_flags);
3180
3181     mp->bd_id = ntohl(bd_id);
3182     mp->feature_bitmap = ntohl(flags);
3183     mp->is_set = is_set;
3184
3185     S; W;
3186     /* NOTREACHED */
3187     return 0;
3188 }
3189
3190 static int api_bd_ip_mac_add_del (vat_main_t * vam)
3191 {
3192     unformat_input_t * i = vam->input;
3193     vl_api_bd_ip_mac_add_del_t *mp;
3194     f64 timeout;
3195     u32 bd_id;
3196     u8 is_ipv6 = 0;
3197     u8 is_add = 1;
3198     u8 bd_id_set = 0;
3199     u8 ip_set = 0;
3200     u8 mac_set = 0;
3201     ip4_address_t v4addr;
3202     ip6_address_t v6addr;
3203     u8 macaddr[6];
3204     
3205
3206     /* Parse args required to build the message */
3207     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3208         if (unformat (i, "bd_id %d", &bd_id)) {
3209             bd_id_set++;
3210         } else if (unformat (i, "%U", unformat_ip4_address, &v4addr)) {
3211             ip_set++;
3212         } else if (unformat (i, "%U", unformat_ip6_address, &v6addr)) {
3213             ip_set++;
3214             is_ipv6++;
3215         } else if (unformat (i, "%U", unformat_ethernet_address, macaddr)) {
3216             mac_set++;
3217         } else if (unformat (i, "del"))
3218             is_add = 0;
3219         else
3220             break;
3221     }
3222
3223     if (bd_id_set == 0) {
3224         errmsg ("missing bridge domain\n");
3225         return -99;
3226     } else if (ip_set == 0) {
3227         errmsg ("missing IP address\n");
3228         return -99;
3229     } else if (mac_set == 0) {
3230         errmsg ("missing MAC address\n");
3231         return -99;
3232     }
3233
3234     M(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del);
3235
3236     mp->bd_id = ntohl(bd_id);
3237     mp->is_ipv6 = is_ipv6;
3238     mp->is_add = is_add;
3239     if (is_ipv6)
3240          memcpy (mp->ip_address, &v6addr, sizeof (v6addr));
3241     else memcpy (mp->ip_address, &v4addr, sizeof (v4addr));
3242     memcpy (mp->mac_address, macaddr, 6);
3243     S; W;
3244     /* NOTREACHED */
3245     return 0;
3246 }
3247
3248 static int api_tap_connect (vat_main_t * vam)
3249 {
3250     unformat_input_t * i = vam->input;
3251     vl_api_tap_connect_t *mp;
3252     f64 timeout;
3253     u8 mac_address[6];
3254     u8 random_mac = 1;
3255     u8 name_set = 0;
3256     u8 * tap_name;
3257
3258     memset (mac_address, 0, sizeof (mac_address));
3259     
3260     /* Parse args required to build the message */
3261     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3262         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
3263             random_mac = 0;
3264         }
3265         else if (unformat (i, "random-mac"))
3266             random_mac = 1;
3267         else if (unformat (i, "tapname %s", &tap_name))
3268             name_set = 1;
3269         else
3270             break;
3271     }
3272
3273     if (name_set == 0) {
3274         errmsg ("missing tap name\n");
3275         return -99;
3276     }
3277     if (vec_len (tap_name) > 63) {
3278         errmsg ("tap name too long\n");
3279     }
3280     vec_add1 (tap_name, 0);
3281         
3282     /* Construct the API message */
3283     M(TAP_CONNECT, tap_connect);
3284
3285     mp->use_random_mac = random_mac;
3286     memcpy (mp->mac_address, mac_address, 6);
3287     memcpy (mp->tap_name, tap_name, vec_len (tap_name));
3288     vec_free (tap_name);
3289
3290     /* send it... */
3291     S;
3292
3293     /* Wait for a reply... */
3294     W;
3295 }
3296
3297 static int api_tap_modify (vat_main_t * vam)
3298 {
3299     unformat_input_t * i = vam->input;
3300     vl_api_tap_modify_t *mp;
3301     f64 timeout;
3302     u8 mac_address[6];
3303     u8 random_mac = 1;
3304     u8 name_set = 0;
3305     u8 * tap_name;
3306     u32 sw_if_index = ~0;
3307     u8 sw_if_index_set = 0;
3308
3309     memset (mac_address, 0, sizeof (mac_address));
3310     
3311     /* Parse args required to build the message */
3312     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3313         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3314             sw_if_index_set = 1;
3315         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3316             sw_if_index_set = 1;
3317         else if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
3318             random_mac = 0;
3319         }
3320         else if (unformat (i, "random-mac"))
3321             random_mac = 1;
3322         else if (unformat (i, "tapname %s", &tap_name))
3323             name_set = 1;
3324         else
3325             break;
3326     }
3327
3328     if (sw_if_index_set == 0) {
3329         errmsg ("missing vpp interface name");
3330         return -99;
3331     }
3332     if (name_set == 0) {
3333         errmsg ("missing tap name\n");
3334         return -99;
3335     }
3336     if (vec_len (tap_name) > 63) {
3337         errmsg ("tap name too long\n");
3338     }
3339     vec_add1 (tap_name, 0);
3340         
3341     /* Construct the API message */
3342     M(TAP_MODIFY, tap_modify);
3343
3344     mp->use_random_mac = random_mac;
3345     mp->sw_if_index = ntohl(sw_if_index);
3346     memcpy (mp->mac_address, mac_address, 6);
3347     memcpy (mp->tap_name, tap_name, vec_len (tap_name));
3348     vec_free (tap_name);
3349
3350     /* send it... */
3351     S;
3352
3353     /* Wait for a reply... */
3354     W;
3355 }
3356
3357 static int api_tap_delete (vat_main_t * vam)
3358 {
3359     unformat_input_t * i = vam->input;
3360     vl_api_tap_delete_t *mp;
3361     f64 timeout;
3362     u32 sw_if_index = ~0;
3363     u8 sw_if_index_set = 0;
3364
3365     /* Parse args required to build the message */
3366     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3367         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3368             sw_if_index_set = 1;
3369         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3370             sw_if_index_set = 1;
3371         else
3372             break;
3373     }
3374
3375     if (sw_if_index_set == 0) {
3376         errmsg ("missing vpp interface name");
3377         return -99;
3378     }
3379         
3380     /* Construct the API message */
3381     M(TAP_DELETE, tap_delete);
3382
3383     mp->sw_if_index = ntohl(sw_if_index);
3384
3385     /* send it... */
3386     S;
3387
3388     /* Wait for a reply... */
3389     W;
3390 }
3391
3392 static int api_ip_add_del_route (vat_main_t * vam)
3393 {
3394     unformat_input_t * i = vam->input;
3395     vl_api_ip_add_del_route_t *mp;
3396     f64 timeout;
3397     u32 sw_if_index = 0, vrf_id = 0;
3398     u8 sw_if_index_set = 0;
3399     u8 is_ipv6 = 0;
3400     u8 is_local = 0, is_drop = 0;
3401     u8 create_vrf_if_needed = 0;
3402     u8 is_add = 1;
3403     u8 next_hop_weight = 1;
3404     u8 not_last = 0;
3405     u8 is_multipath = 0;
3406     u8 address_set = 0;
3407     u8 address_length_set = 0;
3408     u32 lookup_in_vrf = 0;
3409     u32 resolve_attempts = 0;
3410     u32 dst_address_length = 0;
3411     u8 next_hop_set = 0;
3412     ip4_address_t v4_dst_address, v4_next_hop_address;
3413     ip6_address_t v6_dst_address, v6_next_hop_address;
3414     int count = 1;
3415     int j;
3416     f64 before = 0;
3417     u32 random_add_del = 0;
3418     u32 * random_vector = 0;
3419     uword * random_hash;
3420     u32 random_seed = 0xdeaddabe;
3421     u32 classify_table_index = ~0;
3422     u8 is_classify = 0;
3423     
3424     /* Parse args required to build the message */
3425     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3426         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3427             sw_if_index_set = 1;
3428         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3429             sw_if_index_set = 1;
3430         else if (unformat (i, "%U", unformat_ip4_address,
3431                            &v4_dst_address)) {
3432             address_set = 1;
3433             is_ipv6 = 0;
3434         }
3435         else if (unformat (i, "%U", unformat_ip6_address, &v6_dst_address)) {
3436             address_set = 1;
3437             is_ipv6 = 1;
3438         }
3439         else if (unformat (i, "/%d", &dst_address_length)) {
3440             address_length_set = 1;
3441         }
3442         
3443         else if (is_ipv6 == 0 && unformat (i, "via %U", unformat_ip4_address, 
3444                                            &v4_next_hop_address)) {
3445             next_hop_set = 1;
3446         }
3447         else if (is_ipv6 == 1 && unformat (i, "via %U", unformat_ip6_address, 
3448                                            &v6_next_hop_address)) {
3449             next_hop_set = 1;
3450         }
3451         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
3452             ;
3453         else if (unformat (i, "weight %d", &next_hop_weight))
3454             ;
3455         else if (unformat (i, "drop")) {
3456             is_drop = 1;
3457         } else if (unformat (i, "local")) {
3458             is_local = 1;
3459         } else if (unformat (i, "classify %d", &classify_table_index)) {
3460             is_classify = 1;
3461         } else if (unformat (i, "del"))
3462             is_add = 0;
3463         else if (unformat (i, "add"))
3464             is_add = 1;
3465         else if (unformat (i, "not-last"))
3466             not_last = 1;
3467         else if (unformat (i, "multipath"))
3468             is_multipath = 1;
3469         else if (unformat (i, "vrf %d", &vrf_id))
3470             ;
3471         else if (unformat (i, "create-vrf"))
3472             create_vrf_if_needed = 1;
3473         else if (unformat (i, "count %d", &count))
3474             ;
3475         else if (unformat (i, "lookup-in-vrf %d", &lookup_in_vrf))
3476             ;
3477         else if (unformat (i, "random"))
3478             random_add_del = 1;
3479         else if (unformat (i, "seed %d", &random_seed))
3480             ;
3481         else {
3482             clib_warning ("parse error '%U'", format_unformat_error, i);
3483             return -99;
3484         }
3485     }
3486
3487     if (resolve_attempts > 0 && sw_if_index_set == 0) {
3488         errmsg ("ARP resolution needs explicit interface or sw_if_index\n");
3489         return -99;
3490     }
3491     
3492     if (!next_hop_set && !is_drop && !is_local && !is_classify) {
3493         errmsg ("next hop / local / drop / classify not set\n");
3494         return -99;
3495     }
3496
3497     if (address_set == 0) {
3498         errmsg ("missing addresses\n");
3499         return -99;
3500     }
3501
3502     if (address_length_set == 0) {
3503         errmsg ("missing address length\n");
3504         return -99;
3505     }
3506     
3507     /* Generate a pile of unique, random routes */
3508     if (random_add_del) {
3509         u32 this_random_address;
3510         random_hash = hash_create (count, sizeof(uword));
3511
3512         hash_set (random_hash, v4_next_hop_address.as_u32, 1);
3513         for (j = 0; j <= count; j++) {
3514             do {
3515                 this_random_address = random_u32 (&random_seed);
3516                 this_random_address = 
3517                     clib_host_to_net_u32 (this_random_address);
3518             } while (hash_get (random_hash, this_random_address));
3519             vec_add1 (random_vector, this_random_address);
3520             hash_set (random_hash, this_random_address, 1);
3521         }
3522         hash_free (random_hash);
3523         v4_dst_address.as_u32 = random_vector[0];
3524     }
3525
3526     if (count > 1) {
3527         /* Turn on async mode */
3528         vam->async_mode = 1;
3529         vam->async_errors = 0;
3530         before = vat_time_now(vam);
3531     }
3532
3533     for (j = 0; j < count; j++) {
3534         /* Construct the API message */
3535         M(IP_ADD_DEL_ROUTE, ip_add_del_route);
3536     
3537         mp->next_hop_sw_if_index = ntohl (sw_if_index);
3538         mp->vrf_id = ntohl (vrf_id);
3539         if (resolve_attempts > 0) {
3540             mp->resolve_attempts = ntohl (resolve_attempts);
3541             mp->resolve_if_needed = 1;
3542         }
3543         mp->create_vrf_if_needed = create_vrf_if_needed;
3544     
3545         mp->is_add = is_add;
3546         mp->is_drop = is_drop;
3547         mp->is_ipv6 = is_ipv6;
3548         mp->is_local = is_local;
3549         mp->is_classify = is_classify;
3550         mp->is_multipath = is_multipath;
3551         mp->not_last = not_last;
3552         mp->next_hop_weight = next_hop_weight;
3553         mp->dst_address_length = dst_address_length;
3554         mp->lookup_in_vrf = ntohl(lookup_in_vrf);
3555         mp->classify_table_index = ntohl(classify_table_index);
3556
3557         if (is_ipv6){
3558             memcpy (mp->dst_address, &v6_dst_address, sizeof (v6_dst_address));
3559             if (next_hop_set)
3560                 memcpy (mp->next_hop_address, &v6_next_hop_address, 
3561                         sizeof (v6_next_hop_address));
3562             increment_v6_address (&v6_dst_address);
3563         } else {
3564             memcpy (mp->dst_address, &v4_dst_address, sizeof (v4_dst_address));
3565             if (next_hop_set)
3566                 memcpy (mp->next_hop_address, &v4_next_hop_address, 
3567                         sizeof (v4_next_hop_address));
3568             if (random_add_del)
3569                 v4_dst_address.as_u32 = random_vector[j+1];
3570             else
3571                 increment_v4_address (&v4_dst_address);
3572         }
3573         /* send it... */
3574         S;
3575     }
3576
3577     /* When testing multiple add/del ops, use a control-ping to sync */
3578     if (count > 1) {
3579         vl_api_control_ping_t * mp;
3580         f64 after;
3581
3582         /* Shut off async mode */
3583         vam->async_mode = 0;
3584
3585         M(CONTROL_PING, control_ping);
3586         S;
3587
3588         timeout = vat_time_now(vam) + 1.0;
3589         while (vat_time_now (vam) < timeout)
3590             if (vam->result_ready == 1)
3591                 goto out;
3592         vam->retval = -99;
3593
3594     out:
3595         if (vam->retval == -99)
3596             errmsg ("timeout\n");
3597
3598         if (vam->async_errors > 0) {
3599             errmsg ("%d asynchronous errors\n", vam->async_errors);
3600             vam->retval = -98;
3601         }
3602         vam->async_errors = 0;
3603         after = vat_time_now(vam);
3604
3605         fformat(vam->ofp, "%d routes in %.6f secs, %.2f routes/sec\n",
3606                 count, after - before, count / (after - before));
3607     } else {
3608         /* Wait for a reply... */
3609         W;
3610     }
3611
3612     /* Return the good/bad news */
3613     return (vam->retval);
3614 }
3615
3616 static int api_proxy_arp_add_del (vat_main_t * vam)
3617 {
3618     unformat_input_t * i = vam->input;
3619     vl_api_proxy_arp_add_del_t *mp;
3620     f64 timeout;
3621     u32 vrf_id = 0;
3622     u8 is_add = 1;
3623     ip4_address_t lo, hi;
3624     u8 range_set = 0;
3625
3626     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3627         if (unformat (i, "vrf %d", &vrf_id))
3628             ;
3629         else if (unformat (i, "%U - %U", unformat_ip4_address, &lo, 
3630                            unformat_ip4_address, &hi))
3631             range_set = 1;
3632         else if (unformat (i, "del"))
3633             is_add = 0;
3634         else {
3635             clib_warning ("parse error '%U'", format_unformat_error, i);
3636             return -99;
3637         }
3638     }
3639     
3640     if (range_set == 0) {
3641         errmsg ("address range not set\n");
3642         return -99;
3643     }
3644
3645     M(PROXY_ARP_ADD_DEL, proxy_arp_add_del);
3646
3647     mp->vrf_id = ntohl(vrf_id);
3648     mp->is_add = is_add;
3649     memcpy(mp->low_address, &lo, sizeof (mp->low_address));
3650     memcpy(mp->hi_address, &hi, sizeof (mp->hi_address));
3651
3652     S; W;
3653     /* NOTREACHED */
3654     return 0;
3655 }
3656
3657 static int api_proxy_arp_intfc_enable_disable (vat_main_t * vam)
3658 {
3659     unformat_input_t * i = vam->input;
3660     vl_api_proxy_arp_intfc_enable_disable_t *mp;
3661     f64 timeout;
3662     u32 sw_if_index;
3663     u8 enable = 1;
3664     u8 sw_if_index_set = 0;
3665
3666     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3667         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3668             sw_if_index_set = 1;
3669         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3670             sw_if_index_set = 1;
3671         else if (unformat (i, "enable"))
3672             enable = 1;
3673         else if (unformat (i, "disable"))
3674             enable = 0;
3675         else {
3676             clib_warning ("parse error '%U'", format_unformat_error, i);
3677             return -99;
3678         }
3679     }
3680     
3681     if (sw_if_index_set == 0) {
3682         errmsg ("missing interface name or sw_if_index\n");
3683         return -99;
3684     }
3685
3686     M(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable);
3687
3688     mp->sw_if_index = ntohl(sw_if_index);
3689     mp->enable_disable = enable;
3690
3691     S; W;
3692     /* NOTREACHED */
3693     return 0;
3694 }
3695
3696 static int api_mpls_add_del_decap (vat_main_t * vam)
3697 {
3698     unformat_input_t * i = vam->input;
3699     vl_api_mpls_add_del_decap_t *mp;
3700     f64 timeout;
3701     u32 rx_vrf_id = 0;
3702     u32 tx_vrf_id = 0;
3703     u32 label = 0;
3704     u8 is_add = 1;
3705     u8 s_bit = 1;
3706     u32 next_index = 1;
3707
3708     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3709         if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
3710             ;
3711         else if (unformat (i, "tx_vrf_id %d", &tx_vrf_id))
3712             ;
3713         else if (unformat (i, "label %d", &label))
3714             ;
3715         else if (unformat (i, "next-index %d", &next_index))
3716             ;
3717         else if (unformat (i, "del"))
3718             is_add = 0;
3719         else if (unformat (i, "s-bit-clear"))
3720             s_bit = 0;
3721         else {
3722             clib_warning ("parse error '%U'", format_unformat_error, i);
3723             return -99;
3724         }
3725     }
3726     
3727     M(MPLS_ADD_DEL_DECAP, mpls_add_del_decap);
3728
3729     mp->rx_vrf_id = ntohl(rx_vrf_id);
3730     mp->tx_vrf_id = ntohl(tx_vrf_id);
3731     mp->label = ntohl(label);
3732     mp->next_index = ntohl(next_index);
3733     mp->s_bit = s_bit;
3734     mp->is_add = is_add;
3735
3736     S; W;
3737     /* NOTREACHED */
3738     return 0;
3739 }
3740
3741 static int api_mpls_add_del_encap (vat_main_t * vam)
3742 {
3743     unformat_input_t * i = vam->input;
3744     vl_api_mpls_add_del_encap_t *mp;
3745     f64 timeout;
3746     u32 vrf_id = 0;
3747     u32 *labels = 0;
3748     u32 label;
3749     ip4_address_t dst_address;
3750     u8 is_add = 1;
3751
3752     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3753         if (unformat (i, "vrf %d", &vrf_id))
3754             ;
3755         else if (unformat (i, "label %d", &label))
3756             vec_add1 (labels, ntohl(label));
3757         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
3758             ;
3759         else if (unformat (i, "del"))
3760             is_add = 0;
3761         else {
3762             clib_warning ("parse error '%U'", format_unformat_error, i);
3763             return -99;
3764         }
3765     }
3766
3767     if (vec_len (labels) == 0) {
3768         errmsg ("missing encap label stack\n");
3769         return -99;
3770     }
3771     
3772     M2(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap, 
3773        sizeof (u32) * vec_len (labels));
3774
3775     mp->vrf_id = ntohl(vrf_id);
3776     memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
3777     mp->is_add = is_add;
3778     mp->nlabels = vec_len (labels);
3779     memcpy(mp->labels, labels, sizeof(u32)*mp->nlabels);
3780
3781     vec_free(labels);
3782
3783     S; W;
3784     /* NOTREACHED */
3785     return 0;
3786 }
3787
3788 static int api_mpls_gre_add_del_tunnel (vat_main_t * vam)
3789 {
3790     unformat_input_t * i = vam->input;
3791     vl_api_mpls_gre_add_del_tunnel_t *mp;
3792     f64 timeout;
3793     u32 inner_vrf_id = 0;
3794     u32 outer_vrf_id = 0;
3795     ip4_address_t src_address;
3796     ip4_address_t dst_address;
3797     ip4_address_t intfc_address;
3798     u32 tmp;
3799     u8 intfc_address_length = 0;
3800     u8 is_add = 1;
3801     u8 l2_only = 0;
3802     
3803     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3804         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
3805             ;
3806         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
3807             ;
3808         else if (unformat (i, "src %U", unformat_ip4_address, &src_address))
3809             ;
3810         else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address))
3811             ;
3812         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
3813                            &intfc_address, &tmp))
3814             intfc_address_length = tmp;
3815         else if (unformat (i, "l2-only"))
3816             l2_only = 1;
3817         else if (unformat (i, "del"))
3818             is_add = 0;
3819         else {
3820             clib_warning ("parse error '%U'", format_unformat_error, i);
3821             return -99;
3822         }
3823     }
3824     
3825     M(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel);
3826
3827     mp->inner_vrf_id = ntohl(inner_vrf_id);
3828     mp->outer_vrf_id = ntohl(outer_vrf_id);
3829     memcpy(mp->src_address, &src_address, sizeof (src_address));
3830     memcpy(mp->dst_address, &dst_address, sizeof (dst_address));
3831     memcpy(mp->intfc_address, &intfc_address, sizeof (intfc_address));
3832     mp->intfc_address_length = intfc_address_length;
3833     mp->l2_only = l2_only;
3834     mp->is_add = is_add;
3835
3836     S; W;
3837     /* NOTREACHED */
3838     return 0;
3839 }
3840
3841 static int api_mpls_ethernet_add_del_tunnel (vat_main_t * vam)
3842 {
3843     unformat_input_t * i = vam->input;
3844     vl_api_mpls_ethernet_add_del_tunnel_t *mp;
3845     f64 timeout;
3846     u32 inner_vrf_id = 0;
3847     ip4_address_t intfc_address;
3848     u8 dst_mac_address[6];
3849     int dst_set = 1;
3850     u32 tmp;
3851     u8 intfc_address_length = 0;
3852     u8 is_add = 1;
3853     u8 l2_only = 0;
3854     u32 tx_sw_if_index;
3855     int tx_sw_if_index_set = 0;
3856     
3857     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3858         if (unformat (i, "vrf %d", &inner_vrf_id))
3859             ;
3860         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
3861                            &intfc_address, &tmp))
3862             intfc_address_length = tmp;
3863         else if (unformat (i, "%U", 
3864                            unformat_sw_if_index, vam, &tx_sw_if_index))
3865             tx_sw_if_index_set = 1;
3866         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
3867             tx_sw_if_index_set = 1;
3868         else if (unformat (i, "dst %U", unformat_ethernet_address, 
3869                            dst_mac_address))
3870             dst_set = 1;
3871         else if (unformat (i, "l2-only"))
3872             l2_only = 1;
3873         else if (unformat (i, "del"))
3874             is_add = 0;
3875         else {
3876             clib_warning ("parse error '%U'", format_unformat_error, i);
3877             return -99;
3878         }
3879     }
3880
3881     if (!dst_set) {
3882         errmsg ("dst (mac address) not set\n");
3883         return -99;
3884     }
3885     if (!tx_sw_if_index_set) {
3886         errmsg ("tx-intfc not set\n");
3887         return -99;
3888     }
3889     
3890     M(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel);
3891
3892     mp->vrf_id = ntohl(inner_vrf_id);
3893     memcpy (mp->adj_address, &intfc_address, sizeof (intfc_address));
3894     mp->adj_address_length = intfc_address_length;
3895     memcpy (mp->dst_mac_address, dst_mac_address, sizeof (dst_mac_address));
3896     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
3897     mp->l2_only = l2_only;
3898     mp->is_add = is_add;
3899
3900     S; W;
3901     /* NOTREACHED */
3902     return 0;
3903 }
3904
3905 static int api_mpls_ethernet_add_del_tunnel_2 (vat_main_t * vam)
3906 {
3907     unformat_input_t * i = vam->input;
3908     vl_api_mpls_ethernet_add_del_tunnel_2_t *mp;
3909     f64 timeout;
3910     u32 inner_vrf_id = 0;
3911     u32 outer_vrf_id = 0;
3912     ip4_address_t adj_address;
3913     int adj_address_set = 0;
3914     ip4_address_t next_hop_address;
3915     int next_hop_address_set = 0;
3916     u32 tmp;
3917     u8 adj_address_length = 0;
3918     u8 l2_only = 0;
3919     u8 is_add = 1;
3920     u32 resolve_attempts = 5;
3921     u8 resolve_if_needed = 1;
3922     
3923     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3924         if (unformat (i, "inner_vrf_id %d", &inner_vrf_id))
3925             ;
3926         else if (unformat (i, "outer_vrf_id %d", &outer_vrf_id))
3927             ;
3928         else if (unformat (i, "adj %U/%d", unformat_ip4_address,
3929                            &adj_address, &tmp)) {
3930             adj_address_length = tmp;
3931             adj_address_set = 1;
3932         }
3933         else if (unformat (i, "next-hop %U", unformat_ip4_address,
3934                            &next_hop_address))
3935             next_hop_address_set = 1;
3936         else if (unformat (i, "resolve-attempts %d", &resolve_attempts))
3937             ;
3938         else if (unformat (i, "resolve-if-needed %d", &tmp))
3939             resolve_if_needed = tmp;
3940         else if (unformat (i, "l2-only"))
3941             l2_only = 1;
3942         else if (unformat (i, "del"))
3943             is_add = 0;
3944         else {
3945             clib_warning ("parse error '%U'", format_unformat_error, i);
3946             return -99;
3947         }
3948     }
3949     
3950     if (!adj_address_set) {
3951         errmsg ("adjacency address/mask not set\n");
3952         return -99;
3953     }
3954     if (!next_hop_address_set) {
3955         errmsg ("ip4 next hop address (in outer fib) not set\n");
3956         return -99;
3957     }
3958     
3959     M(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2);
3960     
3961     mp->inner_vrf_id = ntohl(inner_vrf_id);
3962     mp->outer_vrf_id = ntohl(outer_vrf_id);
3963     mp->resolve_attempts = ntohl(resolve_attempts);
3964     mp->resolve_if_needed = resolve_if_needed;
3965     mp->is_add = is_add;
3966     mp->l2_only = l2_only;
3967     memcpy (mp->adj_address, &adj_address, sizeof (adj_address));
3968     mp->adj_address_length = adj_address_length;
3969     memcpy (mp->next_hop_ip4_address_in_outer_vrf, &next_hop_address, 
3970             sizeof (next_hop_address));
3971
3972     S; W;
3973     /* NOTREACHED */
3974     return 0;
3975 }
3976
3977 static int api_sw_interface_set_unnumbered (vat_main_t * vam)
3978 {
3979     unformat_input_t * i = vam->input;
3980     vl_api_sw_interface_set_unnumbered_t *mp;
3981     f64 timeout;
3982     u32 sw_if_index;
3983     u32 unnum_sw_index;
3984     u8  is_add = 1;
3985     u8 sw_if_index_set = 0;
3986
3987     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
3988         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
3989             sw_if_index_set = 1;
3990         else if (unformat (i, "sw_if_index %d", &sw_if_index))
3991             sw_if_index_set = 1;
3992         else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
3993             ;
3994         else if (unformat (i, "del"))
3995             is_add = 0;
3996         else {
3997             clib_warning ("parse error '%U'", format_unformat_error, i);
3998             return -99;
3999         }
4000     }
4001     
4002     if (sw_if_index_set == 0) {
4003         errmsg ("missing interface name or sw_if_index\n");
4004         return -99;
4005     }
4006
4007     M(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered);
4008
4009     mp->sw_if_index = ntohl(sw_if_index);
4010     mp->unnumbered_sw_if_index = ntohl(unnum_sw_index);
4011     mp->is_add = is_add;
4012
4013     S; W;
4014     /* NOTREACHED */
4015     return 0;
4016 }
4017
4018 static int api_ip_neighbor_add_del (vat_main_t * vam)
4019 {
4020     unformat_input_t * i = vam->input;
4021     vl_api_ip_neighbor_add_del_t *mp;
4022     f64 timeout;
4023     u32 sw_if_index;
4024     u8 sw_if_index_set = 0;
4025     u32 vrf_id = 0;
4026     u8 is_add = 1;
4027     u8 is_static = 0;
4028     u8 mac_address[6];
4029     u8 mac_set = 0;
4030     u8 v4_address_set = 0;
4031     u8 v6_address_set = 0;
4032     ip4_address_t v4address;
4033     ip6_address_t v6address;
4034     
4035     memset (mac_address, 0, sizeof (mac_address));
4036     
4037     /* Parse args required to build the message */
4038     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4039         if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) {
4040             mac_set = 1;
4041         }
4042         else if (unformat (i, "del"))
4043             is_add = 0;
4044         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4045             sw_if_index_set = 1;
4046         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4047             sw_if_index_set = 1;
4048         else if (unformat (i, "is_static"))
4049             is_static = 1;
4050         else if (unformat (i, "vrf %d", &vrf_id))
4051             ;
4052         else if (unformat (i, "dst %U", 
4053                            unformat_ip4_address, &v4address))
4054                 v4_address_set = 1;
4055         else if (unformat (i, "dst %U", 
4056                            unformat_ip6_address, &v6address))
4057                 v6_address_set = 1;
4058         else {
4059             clib_warning ("parse error '%U'", format_unformat_error, i);
4060             return -99;
4061         }
4062     }
4063
4064     if (sw_if_index_set == 0) {
4065         errmsg ("missing interface name or sw_if_index\n");
4066         return -99;
4067     }
4068     if (v4_address_set && v6_address_set) {
4069         errmsg ("both v4 and v6 addresses set\n");
4070         return -99;
4071     }
4072     if (!v4_address_set && !v6_address_set) {
4073         errmsg ("no addresses set\n");
4074         return -99;
4075     }
4076
4077     /* Construct the API message */
4078     M(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del);
4079
4080     mp->sw_if_index = ntohl (sw_if_index);
4081     mp->is_add = is_add;
4082     mp->vrf_id = ntohl (vrf_id);
4083     mp->is_static = is_static;
4084     if (mac_set)
4085         memcpy (mp->mac_address, mac_address, 6);
4086     if (v6_address_set) {
4087         mp->is_ipv6 = 1;
4088         memcpy (mp->dst_address, &v6address, sizeof (v6address));
4089     } else {
4090         /* mp->is_ipv6 = 0; via memset in M macro above */
4091         memcpy (mp->dst_address, &v4address, sizeof (v4address));
4092     }
4093
4094     /* send it... */
4095     S;
4096
4097     /* Wait for a reply, return good/bad news  */
4098     W;
4099
4100     /* NOTREACHED */
4101     return 0;
4102 }
4103
4104 static int api_reset_vrf (vat_main_t * vam)
4105 {
4106     unformat_input_t * i = vam->input;
4107     vl_api_reset_vrf_t *mp;
4108     f64 timeout;
4109     u32 vrf_id = 0;
4110     u8 is_ipv6 = 0;
4111     u8 vrf_id_set = 0;
4112
4113     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4114         if (unformat (i, "vrf %d", &vrf_id))
4115             vrf_id_set = 1;
4116         else if (unformat (i, "ipv6"))
4117             is_ipv6 = 1;
4118         else {
4119             clib_warning ("parse error '%U'", format_unformat_error, i);
4120             return -99;
4121         }
4122     }
4123
4124     if (vrf_id_set == 0) {
4125         errmsg ("missing vrf id\n");
4126         return -99;
4127     }
4128     
4129     M(RESET_VRF, reset_vrf);
4130
4131     mp->vrf_id = ntohl(vrf_id);
4132     mp->is_ipv6 = is_ipv6;
4133
4134     S; W;
4135     /* NOTREACHED */
4136     return 0;
4137 }
4138
4139 static int api_create_vlan_subif (vat_main_t * vam)
4140 {
4141     unformat_input_t * i = vam->input;
4142     vl_api_create_vlan_subif_t *mp;
4143     f64 timeout;
4144     u32 sw_if_index;
4145     u8  sw_if_index_set = 0;
4146     u32 vlan_id;
4147     u8  vlan_id_set = 0;
4148
4149     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4150         if (unformat (i, "sw_if_index %d", &sw_if_index))
4151             sw_if_index_set = 1;
4152         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4153             sw_if_index_set = 1;
4154         else if (unformat (i, "vlan %d", &vlan_id))
4155             vlan_id_set = 1;
4156         else {
4157             clib_warning ("parse error '%U'", format_unformat_error, i);
4158             return -99;
4159         }
4160     }
4161     
4162     if (sw_if_index_set == 0) {
4163         errmsg ("missing interface name or sw_if_index\n");
4164         return -99;
4165     }
4166
4167     if (vlan_id_set == 0) {
4168         errmsg ("missing vlan_id\n");
4169         return -99;
4170     }
4171     M(CREATE_VLAN_SUBIF, create_vlan_subif);
4172
4173     mp->sw_if_index = ntohl(sw_if_index);
4174     mp->vlan_id = ntohl(vlan_id);
4175
4176     S; W;
4177     /* NOTREACHED */
4178     return 0;
4179 }
4180
4181 #define foreach_create_subif_bit                \
4182 _(no_tags)                                      \
4183 _(one_tag)                                      \
4184 _(two_tags)                                     \
4185 _(dot1ad)                                       \
4186 _(exact_match)                                  \
4187 _(default_sub)                                  \
4188 _(outer_vlan_id_any)                            \
4189 _(inner_vlan_id_any)
4190
4191 static int api_create_subif (vat_main_t * vam)
4192 {
4193     unformat_input_t * i = vam->input;
4194     vl_api_create_subif_t *mp;
4195     f64 timeout;
4196     u32 sw_if_index;
4197     u8  sw_if_index_set = 0;
4198     u32 sub_id;
4199     u8  sub_id_set = 0;
4200     u32 no_tags = 0;
4201     u32 one_tag = 0;
4202     u32 two_tags = 0;
4203     u32 dot1ad = 0;
4204     u32 exact_match = 0;
4205     u32 default_sub = 0;
4206     u32 outer_vlan_id_any = 0;
4207     u32 inner_vlan_id_any = 0;
4208     u32 tmp;
4209     u16 outer_vlan_id = 0;
4210     u16 inner_vlan_id = 0;
4211
4212     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4213         if (unformat (i, "sw_if_index %d", &sw_if_index))
4214             sw_if_index_set = 1;
4215         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4216             sw_if_index_set = 1;
4217         else if (unformat (i, "sub_id %d", &sub_id))
4218             sub_id_set = 1;
4219         else if (unformat (i, "outer_vlan_id %d", &tmp))
4220             outer_vlan_id = tmp;
4221         else if (unformat (i, "inner_vlan_id %d", &tmp))
4222             inner_vlan_id = tmp;
4223
4224 #define _(a) else if (unformat (i, #a)) a = 1 ;
4225         foreach_create_subif_bit
4226 #undef _
4227
4228         else {
4229             clib_warning ("parse error '%U'", format_unformat_error, i);
4230             return -99;
4231         }
4232     }
4233     
4234     if (sw_if_index_set == 0) {
4235         errmsg ("missing interface name or sw_if_index\n");
4236         return -99;
4237     }
4238
4239     if (sub_id_set == 0) {
4240         errmsg ("missing sub_id\n");
4241         return -99;
4242     }
4243     M(CREATE_SUBIF, create_subif);
4244
4245     mp->sw_if_index = ntohl(sw_if_index);
4246     mp->sub_id = ntohl(sub_id);
4247     
4248 #define _(a) mp->a = a;
4249     foreach_create_subif_bit;
4250 #undef _
4251         
4252     mp->outer_vlan_id = ntohs (outer_vlan_id);
4253     mp->inner_vlan_id = ntohs (inner_vlan_id);
4254
4255     S; W;
4256     /* NOTREACHED */
4257     return 0;
4258 }
4259
4260 static int api_oam_add_del (vat_main_t * vam)
4261 {
4262     unformat_input_t * i = vam->input;
4263     vl_api_oam_add_del_t *mp;
4264     f64 timeout;
4265     u32 vrf_id = 0;
4266     u8 is_add = 1;
4267     ip4_address_t src, dst;
4268     u8 src_set = 0;
4269     u8 dst_set = 0;
4270     
4271     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4272         if (unformat (i, "vrf %d", &vrf_id))
4273             ;
4274         else if (unformat (i, "src %U", unformat_ip4_address, &src))
4275             src_set = 1;
4276         else if (unformat (i, "dst %U", unformat_ip4_address, &dst))
4277             dst_set = 1;
4278         else if (unformat (i, "del"))
4279             is_add = 0;
4280         else {
4281             clib_warning ("parse error '%U'", format_unformat_error, i);
4282             return -99;
4283         }
4284     }
4285     
4286     if (src_set == 0) {
4287         errmsg ("missing src addr\n");
4288         return -99;
4289     }
4290
4291     if (dst_set == 0) {
4292         errmsg ("missing dst addr\n");
4293         return -99;
4294     }
4295
4296     M(OAM_ADD_DEL, oam_add_del);
4297
4298     mp->vrf_id = ntohl(vrf_id);
4299     mp->is_add = is_add;
4300     memcpy(mp->src_address, &src, sizeof (mp->src_address));
4301     memcpy(mp->dst_address, &dst, sizeof (mp->dst_address));
4302
4303     S; W;
4304     /* NOTREACHED */
4305     return 0;
4306 }
4307
4308 static int api_reset_fib (vat_main_t * vam)
4309 {
4310     unformat_input_t * i = vam->input;
4311     vl_api_reset_fib_t *mp;
4312     f64 timeout;
4313     u32 vrf_id = 0;
4314     u8 is_ipv6 = 0;
4315     u8 vrf_id_set = 0;
4316
4317     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4318         if (unformat (i, "vrf %d", &vrf_id))
4319             vrf_id_set = 1;
4320         else if (unformat (i, "ipv6"))
4321             is_ipv6 = 1;
4322         else {
4323             clib_warning ("parse error '%U'", format_unformat_error, i);
4324             return -99;
4325         }
4326     }
4327
4328     if (vrf_id_set == 0) {
4329         errmsg ("missing vrf id\n");
4330         return -99;
4331     }
4332     
4333     M(RESET_FIB, reset_fib);
4334
4335     mp->vrf_id = ntohl(vrf_id);
4336     mp->is_ipv6 = is_ipv6;
4337
4338     S; W;
4339     /* NOTREACHED */
4340     return 0;
4341 }
4342
4343 static int api_dhcp_proxy_config (vat_main_t * vam)
4344 {
4345     unformat_input_t * i = vam->input;
4346     vl_api_dhcp_proxy_config_t *mp;
4347     f64 timeout;
4348     u32 vrf_id = 0;
4349     u8 is_add = 1;
4350     u8 insert_cid = 1;
4351     u8 v4_address_set = 0;
4352     u8 v6_address_set = 0;
4353     ip4_address_t v4address;
4354     ip6_address_t v6address;
4355     u8 v4_src_address_set = 0;
4356     u8 v6_src_address_set = 0;
4357     ip4_address_t v4srcaddress;
4358     ip6_address_t v6srcaddress;
4359     
4360     /* Parse args required to build the message */
4361     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4362         if (unformat (i, "del"))
4363             is_add = 0;
4364         else if (unformat (i, "vrf %d", &vrf_id))
4365             ;
4366         else if (unformat (i, "insert-cid %d", &insert_cid))
4367             ;
4368         else if (unformat (i, "svr %U", 
4369                            unformat_ip4_address, &v4address))
4370                 v4_address_set = 1;
4371         else if (unformat (i, "svr %U", 
4372                            unformat_ip6_address, &v6address))
4373                 v6_address_set = 1;
4374         else if (unformat (i, "src %U", 
4375                            unformat_ip4_address, &v4srcaddress))
4376                 v4_src_address_set = 1;
4377         else if (unformat (i, "src %U", 
4378                            unformat_ip6_address, &v6srcaddress))
4379                 v6_src_address_set = 1;
4380         else
4381             break;
4382     }
4383
4384     if (v4_address_set && v6_address_set) {
4385         errmsg ("both v4 and v6 server addresses set\n");
4386         return -99;
4387     }
4388     if (!v4_address_set && !v6_address_set) {
4389         errmsg ("no server addresses set\n");
4390         return -99;
4391     }
4392
4393     if (v4_src_address_set && v6_src_address_set) {
4394         errmsg ("both v4 and v6  src addresses set\n");
4395         return -99;
4396     }
4397     if (!v4_src_address_set && !v6_src_address_set) {
4398         errmsg ("no src addresses set\n");
4399         return -99;
4400     }
4401
4402     if (!(v4_src_address_set && v4_address_set) &&
4403         !(v6_src_address_set && v6_address_set)) {
4404         errmsg ("no matching server and src addresses set\n");
4405         return -99;
4406     }
4407
4408     /* Construct the API message */
4409     M(DHCP_PROXY_CONFIG, dhcp_proxy_config);
4410
4411     mp->insert_circuit_id = insert_cid;
4412     mp->is_add = is_add;
4413     mp->vrf_id = ntohl (vrf_id);
4414     if (v6_address_set) {
4415         mp->is_ipv6 = 1;
4416         memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
4417         memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
4418     } else {
4419         memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
4420         memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
4421     }
4422
4423     /* send it... */
4424     S;
4425
4426     /* Wait for a reply, return good/bad news  */
4427     W;
4428     /* NOTREACHED */
4429     return 0;
4430 }
4431
4432 static int api_dhcp_proxy_config_2 (vat_main_t * vam)
4433 {
4434     unformat_input_t * i = vam->input;
4435     vl_api_dhcp_proxy_config_2_t *mp;
4436     f64 timeout;
4437     u32 rx_vrf_id = 0;
4438     u32 server_vrf_id = 0;
4439     u8 is_add = 1;
4440     u8 insert_cid = 1;
4441     u8 v4_address_set = 0;
4442     u8 v6_address_set = 0;
4443     ip4_address_t v4address;
4444     ip6_address_t v6address;
4445     u8 v4_src_address_set = 0;
4446     u8 v6_src_address_set = 0;
4447     ip4_address_t v4srcaddress;
4448     ip6_address_t v6srcaddress;
4449     
4450     /* Parse args required to build the message */
4451     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4452         if (unformat (i, "del"))
4453             is_add = 0;
4454         else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id))
4455             ;
4456         else if (unformat (i, "server_vrf_id %d", &server_vrf_id))
4457             ;
4458         else if (unformat (i, "insert-cid %d", &insert_cid))
4459             ;
4460         else if (unformat (i, "svr %U", 
4461                            unformat_ip4_address, &v4address))
4462                 v4_address_set = 1;
4463         else if (unformat (i, "svr %U", 
4464                            unformat_ip6_address, &v6address))
4465                 v6_address_set = 1;
4466         else if (unformat (i, "src %U", 
4467                            unformat_ip4_address, &v4srcaddress))
4468                 v4_src_address_set = 1;
4469         else if (unformat (i, "src %U", 
4470                            unformat_ip6_address, &v6srcaddress))
4471                 v6_src_address_set = 1;
4472         else
4473             break;
4474     }
4475
4476     if (v4_address_set && v6_address_set) {
4477         errmsg ("both v4 and v6 server addresses set\n");
4478         return -99;
4479     }
4480     if (!v4_address_set && !v6_address_set) {
4481         errmsg ("no server addresses set\n");
4482         return -99;
4483     }
4484
4485     if (v4_src_address_set && v6_src_address_set) {
4486         errmsg ("both v4 and v6  src addresses set\n");
4487         return -99;
4488     }
4489     if (!v4_src_address_set && !v6_src_address_set) {
4490         errmsg ("no src addresses set\n");
4491         return -99;
4492     }
4493
4494     if (!(v4_src_address_set && v4_address_set) &&
4495         !(v6_src_address_set && v6_address_set)) {
4496         errmsg ("no matching server and src addresses set\n");
4497         return -99;
4498     }
4499
4500     /* Construct the API message */
4501     M(DHCP_PROXY_CONFIG_2, dhcp_proxy_config_2);
4502
4503     mp->insert_circuit_id = insert_cid;
4504     mp->is_add = is_add;
4505     mp->rx_vrf_id = ntohl (rx_vrf_id);
4506     mp->server_vrf_id = ntohl (server_vrf_id);
4507     if (v6_address_set) {
4508         mp->is_ipv6 = 1;
4509         memcpy (mp->dhcp_server, &v6address, sizeof (v6address));
4510         memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address));
4511     } else {
4512         memcpy (mp->dhcp_server, &v4address, sizeof (v4address));
4513         memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address));
4514     }
4515
4516     /* send it... */
4517     S;
4518
4519     /* Wait for a reply, return good/bad news  */
4520     W;
4521     /* NOTREACHED */
4522     return 0;
4523 }
4524
4525 static int api_dhcp_proxy_set_vss (vat_main_t * vam)
4526 {
4527     unformat_input_t * i = vam->input;
4528     vl_api_dhcp_proxy_set_vss_t *mp;
4529     f64 timeout;
4530     u8  is_ipv6 = 0;
4531     u8  is_add = 1;
4532     u32 tbl_id;
4533     u8  tbl_id_set = 0;
4534     u32 oui;
4535     u8  oui_set = 0;
4536     u32 fib_id;
4537     u8  fib_id_set = 0;
4538
4539     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4540         if (unformat (i, "tbl_id %d", &tbl_id))
4541             tbl_id_set = 1;
4542         if (unformat (i, "fib_id %d", &fib_id))
4543             fib_id_set = 1;
4544         if (unformat (i, "oui %d", &oui))
4545             oui_set = 1;
4546         else if (unformat (i, "ipv6"))
4547             is_ipv6 = 1;
4548         else if (unformat (i, "del"))
4549             is_add = 0;
4550         else {
4551             clib_warning ("parse error '%U'", format_unformat_error, i);
4552             return -99;
4553         }
4554     }
4555
4556     if (tbl_id_set == 0) {
4557         errmsg ("missing tbl id\n");
4558         return -99;
4559     }
4560
4561     if (fib_id_set == 0) {
4562         errmsg ("missing fib id\n");
4563         return -99;
4564     }
4565     if (oui_set == 0) {
4566         errmsg ("missing oui\n");
4567         return -99;
4568     }
4569     
4570     M(DHCP_PROXY_SET_VSS, dhcp_proxy_set_vss);
4571     mp->tbl_id = ntohl(tbl_id);
4572     mp->fib_id = ntohl(fib_id);
4573     mp->oui = ntohl(oui);
4574     mp->is_ipv6 = is_ipv6;
4575     mp->is_add = is_add;
4576
4577     S; W;
4578     /* NOTREACHED */
4579     return 0;
4580 }
4581
4582 static int api_dhcp_client_config (vat_main_t * vam)
4583 {
4584     unformat_input_t * i = vam->input;
4585     vl_api_dhcp_client_config_t *mp;
4586     f64 timeout;
4587     u32 sw_if_index;
4588     u8 sw_if_index_set = 0;
4589     u8 is_add = 1;
4590     u8 * hostname = 0;
4591     u8 disable_event = 0;
4592
4593     /* Parse args required to build the message */
4594     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4595         if (unformat (i, "del"))
4596             is_add = 0;
4597         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4598             sw_if_index_set = 1;
4599         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4600             sw_if_index_set = 1;
4601         else if (unformat (i, "hostname %s", &hostname))
4602             ;
4603         else if (unformat (i, "disable_event"))
4604             disable_event = 1;
4605         else
4606             break;
4607     }
4608
4609     if (sw_if_index_set == 0) {
4610         errmsg ("missing interface name or sw_if_index\n");
4611         return -99;
4612     }
4613
4614     if (vec_len (hostname) > 63) {
4615         errmsg ("hostname too long\n");
4616     }
4617     vec_add1 (hostname, 0);
4618
4619     /* Construct the API message */
4620     M(DHCP_CLIENT_CONFIG, dhcp_client_config);
4621
4622     mp->sw_if_index = ntohl (sw_if_index);
4623     memcpy (mp->hostname, hostname, vec_len (hostname));
4624     vec_free (hostname);
4625     mp->is_add = is_add;
4626     mp->want_dhcp_event = disable_event ? 0 : 1;
4627     mp->pid = getpid();
4628    
4629     /* send it... */
4630     S;
4631
4632     /* Wait for a reply, return good/bad news  */
4633     W;
4634     /* NOTREACHED */
4635     return 0;
4636 }
4637
4638 static int api_set_ip_flow_hash (vat_main_t * vam)
4639 {
4640     unformat_input_t * i = vam->input;
4641     vl_api_set_ip_flow_hash_t *mp;
4642     f64 timeout;
4643     u32 vrf_id = 0;
4644     u8 is_ipv6 = 0;
4645     u8 vrf_id_set = 0;
4646     u8 src = 0;
4647     u8 dst = 0;
4648     u8 sport = 0;
4649     u8 dport = 0;
4650     u8 proto = 0;
4651     u8 reverse = 0;
4652
4653     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4654         if (unformat (i, "vrf %d", &vrf_id))
4655             vrf_id_set = 1;
4656         else if (unformat (i, "ipv6"))
4657             is_ipv6 = 1;
4658         else if (unformat (i, "src"))
4659             src = 1;
4660         else if (unformat (i, "dst"))
4661             dst = 1;
4662         else if (unformat (i, "sport"))
4663             sport = 1;
4664         else if (unformat (i, "dport"))
4665             dport = 1;
4666         else if (unformat (i, "proto"))
4667             proto = 1;
4668         else if (unformat (i, "reverse"))
4669             reverse = 1;
4670
4671         else {
4672             clib_warning ("parse error '%U'", format_unformat_error, i);
4673             return -99;
4674         }
4675     }
4676
4677     if (vrf_id_set == 0) {
4678         errmsg ("missing vrf id\n");
4679         return -99;
4680     }
4681     
4682     M(SET_IP_FLOW_HASH, set_ip_flow_hash);
4683     mp->src = src;
4684     mp->dst = dst;
4685     mp->sport = sport;
4686     mp->dport = dport;
4687     mp->proto = proto;
4688     mp->reverse = reverse;
4689     mp->vrf_id = ntohl(vrf_id);
4690     mp->is_ipv6 = is_ipv6;
4691
4692     S; W;
4693     /* NOTREACHED */
4694     return 0;
4695 }
4696
4697 static int api_sw_interface_ip6_enable_disable (vat_main_t * vam)
4698 {
4699     unformat_input_t * i = vam->input;
4700     vl_api_sw_interface_ip6_enable_disable_t *mp;
4701     f64 timeout;
4702     u32 sw_if_index;
4703     u8  sw_if_index_set = 0;
4704     u8  enable = 0;
4705
4706     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4707         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4708             sw_if_index_set = 1;
4709         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4710             sw_if_index_set = 1;
4711         else if (unformat (i, "enable"))
4712             enable = 1;
4713         else if (unformat (i, "disable"))
4714             enable = 0;
4715         else {
4716             clib_warning ("parse error '%U'", format_unformat_error, i);
4717             return -99;
4718         }
4719     }
4720
4721     if (sw_if_index_set == 0) {
4722         errmsg ("missing interface name or sw_if_index\n");
4723         return -99;
4724     }
4725     
4726     M(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable);
4727
4728     mp->sw_if_index = ntohl(sw_if_index);
4729     mp->enable = enable;
4730
4731     S; W;
4732     /* NOTREACHED */
4733     return 0;
4734 }
4735
4736 static int api_sw_interface_ip6_set_link_local_address (vat_main_t * vam)
4737 {
4738     unformat_input_t * i = vam->input;
4739     vl_api_sw_interface_ip6_set_link_local_address_t *mp;
4740     f64 timeout;
4741     u32 sw_if_index;
4742     u8 sw_if_index_set = 0;
4743     u32 address_length = 0;
4744     u8 v6_address_set = 0;
4745     ip6_address_t v6address;
4746     
4747     /* Parse args required to build the message */
4748     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4749         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4750             sw_if_index_set = 1;
4751         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4752             sw_if_index_set = 1;
4753         else if (unformat (i, "%U/%d", 
4754                            unformat_ip6_address, &v6address, 
4755                            &address_length))
4756             v6_address_set = 1;
4757         else
4758             break;
4759     }
4760
4761     if (sw_if_index_set == 0) {
4762         errmsg ("missing interface name or sw_if_index\n");
4763         return -99;
4764     }
4765     if (!v6_address_set) {
4766         errmsg ("no address set\n");
4767         return -99;
4768     }
4769
4770     /* Construct the API message */
4771     M(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
4772       sw_interface_ip6_set_link_local_address);
4773
4774     mp->sw_if_index = ntohl (sw_if_index);
4775     memcpy (mp->address, &v6address, sizeof (v6address));
4776     mp->address_length = address_length;
4777
4778     /* send it... */
4779     S;
4780
4781     /* Wait for a reply, return good/bad news  */
4782     W;
4783
4784     /* NOTREACHED */
4785     return 0;
4786 }
4787
4788
4789 static int api_sw_interface_ip6nd_ra_prefix (vat_main_t * vam)
4790 {
4791     unformat_input_t * i = vam->input;
4792     vl_api_sw_interface_ip6nd_ra_prefix_t *mp;
4793     f64 timeout;
4794     u32 sw_if_index;
4795     u8 sw_if_index_set = 0;
4796     u32 address_length = 0;
4797     u8 v6_address_set = 0;
4798     ip6_address_t v6address;
4799     u8 use_default = 0;
4800     u8 no_advertise = 0;
4801     u8 off_link = 0;
4802     u8 no_autoconfig = 0;
4803     u8 no_onlink = 0;
4804     u8 is_no = 0;
4805     u32 val_lifetime = 0;
4806     u32 pref_lifetime = 0;
4807     
4808     /* Parse args required to build the message */
4809     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4810         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4811             sw_if_index_set = 1;
4812         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4813             sw_if_index_set = 1;
4814         else if (unformat (i, "%U/%d", 
4815                            unformat_ip6_address, &v6address, 
4816                            &address_length))
4817             v6_address_set = 1;
4818         else if (unformat (i, "val_life %d", &val_lifetime))
4819             ;
4820         else if (unformat (i, "pref_life %d", &pref_lifetime))
4821             ;
4822         else if (unformat (i, "def"))
4823             use_default = 1;
4824         else if (unformat (i, "noadv"))
4825             no_advertise = 1;
4826         else if (unformat (i, "offl"))
4827             off_link = 1;
4828         else if (unformat (i, "noauto"))
4829             no_autoconfig = 1;
4830         else if (unformat (i, "nolink"))
4831             no_onlink = 1;
4832         else if (unformat (i, "isno"))
4833             is_no = 1;
4834         else {
4835             clib_warning ("parse error '%U'", format_unformat_error, i);
4836             return -99;
4837         }        
4838     }
4839
4840     if (sw_if_index_set == 0) {
4841         errmsg ("missing interface name or sw_if_index\n");
4842         return -99;
4843     }
4844     if (!v6_address_set) {
4845         errmsg ("no address set\n");
4846         return -99;
4847     }
4848
4849     /* Construct the API message */
4850     M(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix);
4851
4852     mp->sw_if_index = ntohl (sw_if_index);
4853     memcpy (mp->address, &v6address, sizeof (v6address));
4854     mp->address_length = address_length;
4855     mp->use_default = use_default;
4856     mp->no_advertise = no_advertise;
4857     mp->off_link = off_link;
4858     mp->no_autoconfig = no_autoconfig;
4859     mp->no_onlink = no_onlink;
4860     mp->is_no = is_no;
4861     mp->val_lifetime = ntohl(val_lifetime);
4862     mp->pref_lifetime = ntohl(pref_lifetime);
4863
4864     /* send it... */
4865     S;
4866
4867     /* Wait for a reply, return good/bad news  */
4868     W;
4869
4870     /* NOTREACHED */
4871     return 0;
4872 }
4873
4874 static int api_sw_interface_ip6nd_ra_config (vat_main_t * vam)
4875 {
4876     unformat_input_t * i = vam->input;
4877     vl_api_sw_interface_ip6nd_ra_config_t *mp;
4878     f64 timeout;
4879     u32 sw_if_index;
4880     u8 sw_if_index_set = 0;
4881     u8 surpress = 0;
4882     u8 managed = 0;
4883     u8 other = 0;
4884     u8 ll_option = 0;
4885     u8 send_unicast = 0;
4886     u8 cease = 0;
4887     u8 is_no = 0;
4888     u8 default_router = 0;
4889     u32 max_interval = 0;
4890     u32 min_interval = 0;
4891     u32 lifetime = 0;
4892     u32 initial_count = 0;
4893     u32 initial_interval = 0;
4894
4895     
4896     /* Parse args required to build the message */
4897     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4898         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
4899             sw_if_index_set = 1;
4900         else if (unformat (i, "sw_if_index %d", &sw_if_index))
4901             sw_if_index_set = 1;
4902         else if (unformat (i, "maxint %d", &max_interval))
4903             ;
4904         else if (unformat (i, "minint %d", &min_interval))
4905             ;
4906         else if (unformat (i, "life %d", &lifetime))
4907             ;
4908         else if (unformat (i, "count %d", &initial_count))
4909             ;
4910         else if (unformat (i, "interval %d", &initial_interval))
4911             ;
4912         else if (unformat (i, "surpress"))
4913             surpress = 1;
4914         else if (unformat (i, "managed"))
4915             managed = 1;
4916         else if (unformat (i, "other"))
4917             other = 1;
4918         else if (unformat (i, "ll"))
4919             ll_option = 1;
4920         else if (unformat (i, "send"))
4921             send_unicast = 1;
4922         else if (unformat (i, "cease"))
4923             cease = 1;
4924         else if (unformat (i, "isno"))
4925             is_no = 1;
4926         else if (unformat (i, "def"))
4927             default_router = 1;
4928         else {
4929             clib_warning ("parse error '%U'", format_unformat_error, i);
4930             return -99;
4931         }        
4932     }
4933
4934     if (sw_if_index_set == 0) {
4935         errmsg ("missing interface name or sw_if_index\n");
4936         return -99;
4937     }
4938
4939     /* Construct the API message */
4940     M(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config);
4941
4942     mp->sw_if_index = ntohl (sw_if_index);
4943     mp->max_interval = ntohl(max_interval);
4944     mp->min_interval = ntohl(min_interval);
4945     mp->lifetime = ntohl(lifetime);
4946     mp->initial_count = ntohl(initial_count);
4947     mp->initial_interval = ntohl(initial_interval);
4948     mp->surpress = surpress;
4949     mp->managed = managed;
4950     mp->other = other;
4951     mp->ll_option = ll_option;
4952     mp->send_unicast = send_unicast;
4953     mp->cease = cease;
4954     mp->is_no = is_no;
4955     mp->default_router = default_router;
4956
4957     /* send it... */
4958     S;
4959
4960     /* Wait for a reply, return good/bad news  */
4961     W;
4962
4963     /* NOTREACHED */
4964     return 0;
4965 }
4966
4967 static int api_set_arp_neighbor_limit (vat_main_t * vam)
4968 {
4969     unformat_input_t * i = vam->input;
4970     vl_api_set_arp_neighbor_limit_t *mp;
4971     f64 timeout;
4972     u32 arp_nbr_limit;
4973     u8 limit_set = 0;
4974     u8 is_ipv6 = 0;
4975
4976     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
4977         if (unformat (i, "arp_nbr_limit %d", &arp_nbr_limit))
4978             limit_set = 1;
4979         else if (unformat (i, "ipv6"))
4980             is_ipv6 = 1;
4981         else {
4982             clib_warning ("parse error '%U'", format_unformat_error, i);
4983             return -99;
4984         }
4985     }
4986
4987     if (limit_set == 0) {
4988         errmsg ("missing limit value\n");
4989         return -99;
4990     }
4991     
4992     M(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit);
4993
4994     mp->arp_neighbor_limit = ntohl(arp_nbr_limit);
4995     mp->is_ipv6 = is_ipv6;
4996
4997     S; W;
4998     /* NOTREACHED */
4999     return 0;
5000 }
5001
5002 static int api_l2_patch_add_del (vat_main_t * vam)
5003 {
5004     unformat_input_t * i = vam->input;
5005     vl_api_l2_patch_add_del_t *mp;
5006     f64 timeout;
5007     u32 rx_sw_if_index;
5008     u8 rx_sw_if_index_set = 0;
5009     u32 tx_sw_if_index;
5010     u8 tx_sw_if_index_set = 0;
5011     u8 is_add = 1;
5012     
5013     /* Parse args required to build the message */
5014     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5015         if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
5016             rx_sw_if_index_set = 1;     
5017         else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
5018             tx_sw_if_index_set = 1;
5019         else if (unformat (i, "rx")) {
5020             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5021                 if (unformat (i, "%U", unformat_sw_if_index, vam,
5022                               &rx_sw_if_index))
5023                     rx_sw_if_index_set = 1;
5024             } else
5025                 break;
5026         } else if (unformat (i, "tx")) {
5027             if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5028                 if (unformat (i, "%U", unformat_sw_if_index, vam,
5029                               &tx_sw_if_index))
5030                     tx_sw_if_index_set = 1;
5031             } else
5032                 break;
5033         } else if (unformat (i, "del"))
5034             is_add = 0;
5035         else
5036             break;
5037     }
5038
5039     if (rx_sw_if_index_set == 0) {
5040         errmsg ("missing rx interface name or rx_sw_if_index\n");
5041         return -99;
5042     }
5043
5044     if (tx_sw_if_index_set == 0) {
5045         errmsg ("missing tx interface name or tx_sw_if_index\n");
5046         return -99;
5047     }
5048     
5049     M(L2_PATCH_ADD_DEL, l2_patch_add_del);
5050
5051     mp->rx_sw_if_index = ntohl(rx_sw_if_index);
5052     mp->tx_sw_if_index = ntohl(tx_sw_if_index);
5053     mp->is_add = is_add;
5054
5055     S; W;
5056     /* NOTREACHED */
5057     return 0;
5058 }
5059
5060 static int api_sr_tunnel_add_del (vat_main_t * vam)
5061 {
5062   unformat_input_t * i = vam->input;
5063   vl_api_sr_tunnel_add_del_t *mp;
5064   f64 timeout;
5065   int is_del = 0;
5066   int pl_index;
5067   ip6_address_t src_address;
5068   int src_address_set = 0;
5069   ip6_address_t dst_address;
5070   u32 dst_mask_width;
5071   int dst_address_set = 0;
5072   u16 flags = 0;
5073   u32 rx_table_id = 0;
5074   u32 tx_table_id = 0;
5075   ip6_address_t * segments = 0;
5076   ip6_address_t * this_seg;
5077   ip6_address_t * tags = 0;
5078   ip6_address_t * this_tag;
5079   ip6_address_t next_address, tag;
5080
5081   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5082     {
5083       if (unformat (i, "del"))
5084         is_del = 1;
5085       else if (unformat (i, "rx_fib_id %d", &rx_table_id))
5086         ;
5087       else if (unformat (i, "tx_fib_id %d", &tx_table_id))
5088         ;
5089       else if (unformat (i, "src %U", unformat_ip6_address, &src_address))
5090         src_address_set = 1;
5091       else if (unformat (i, "dst %U/%d", 
5092                          unformat_ip6_address, &dst_address,
5093                          &dst_mask_width))
5094         dst_address_set = 1;
5095       else if (unformat (i, "next %U", unformat_ip6_address,
5096                          &next_address))
5097         {
5098           vec_add2 (segments, this_seg, 1);
5099           memcpy (this_seg->as_u8, next_address.as_u8, sizeof (*this_seg));
5100         }
5101       else if (unformat (i, "tag %U", unformat_ip6_address,
5102                          &tag))
5103         {
5104           vec_add2 (tags, this_tag, 1);
5105           memcpy (this_tag->as_u8, tag.as_u8, sizeof (*this_tag));
5106         }
5107       else if (unformat (i, "clean"))
5108         flags |= IP6_SR_HEADER_FLAG_CLEANUP;
5109       else if (unformat (i, "protected"))
5110         flags |= IP6_SR_HEADER_FLAG_PROTECTED;
5111       else if (unformat (i, "InPE %d", &pl_index))
5112         {
5113           if (pl_index <= 0 || pl_index > 4)
5114             {
5115             pl_index_range_error:
5116               errmsg ("pl index %d out of range\n", pl_index);
5117               return -99;
5118             }
5119           flags |= IP6_SR_HEADER_FLAG_PL_ELT_INGRESS_PE << (3*(pl_index - 1));
5120         }
5121       else if (unformat (i, "EgPE %d", &pl_index))
5122         {
5123           if (pl_index <= 0 || pl_index > 4)
5124             goto pl_index_range_error;
5125           flags |= IP6_SR_HEADER_FLAG_PL_ELT_EGRESS_PE << (3*(pl_index - 1));
5126         }
5127       else if (unformat (i, "OrgSrc %d", &pl_index))
5128         {
5129           if (pl_index <= 0 || pl_index > 4)
5130             goto pl_index_range_error;
5131           flags |= IP6_SR_HEADER_FLAG_PL_ELT_ORIG_SRC_ADDR << (3*(pl_index - 1));
5132         }
5133       else 
5134         break;
5135     }
5136
5137   if (!src_address_set)
5138     {
5139       errmsg ("src address required\n");
5140       return -99;
5141     }
5142
5143   if (!dst_address_set)
5144     {
5145       errmsg ("dst address required\n");
5146       return -99;
5147     }
5148
5149   if (!segments)
5150     {
5151       errmsg ("at least one sr segment required\n");
5152       return -99;
5153     }
5154
5155   M2(SR_TUNNEL_ADD_DEL, sr_tunnel_add_del, 
5156      vec_len(segments) * sizeof (ip6_address_t) 
5157      + vec_len(tags) * sizeof (ip6_address_t));
5158
5159   memcpy (mp->src_address, &src_address, sizeof (mp->src_address));
5160   memcpy (mp->dst_address, &dst_address, sizeof (mp->dst_address));
5161   mp->dst_mask_width = dst_mask_width;
5162   mp->flags_net_byte_order = clib_host_to_net_u16 (flags);
5163   mp->n_segments = vec_len (segments);
5164   mp->n_tags = vec_len (tags);
5165   mp->is_add = is_del == 0;
5166   memcpy (mp->segs_and_tags, segments, 
5167           vec_len(segments)* sizeof (ip6_address_t));
5168   memcpy (mp->segs_and_tags + vec_len(segments)*sizeof (ip6_address_t),
5169           tags, vec_len(tags)* sizeof (ip6_address_t));
5170
5171   mp->outer_vrf_id = ntohl (rx_table_id);
5172   mp->inner_vrf_id = ntohl (tx_table_id);
5173
5174   vec_free (segments);
5175   vec_free (tags);
5176   
5177   S; W;
5178   /* NOTREACHED */
5179 }
5180
5181
5182 #define foreach_ip4_proto_field                 \
5183 _(src_address)                                  \
5184 _(dst_address)                                  \
5185 _(tos)                                          \
5186 _(length)                                       \
5187 _(fragment_id)                                  \
5188 _(ttl)                                          \
5189 _(protocol)                                     \
5190 _(checksum)
5191
5192 uword unformat_ip4_mask (unformat_input_t * input, va_list * args)
5193 {
5194   u8 ** maskp = va_arg (*args, u8 **);
5195   u8 * mask = 0;
5196   u8 found_something = 0;
5197   ip4_header_t * ip;
5198   
5199 #define _(a) u8 a=0;
5200   foreach_ip4_proto_field;
5201 #undef _
5202   u8 version = 0;
5203   u8 hdr_length = 0;
5204   
5205   
5206   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5207     {
5208       if (unformat (input, "version")) 
5209         version = 1;
5210       else if (unformat (input, "hdr_length"))
5211         hdr_length = 1;
5212       else if (unformat (input, "src"))
5213         src_address = 1;
5214       else if (unformat (input, "dst"))
5215         dst_address = 1;
5216       else if (unformat (input, "proto"))
5217         protocol = 1;
5218       
5219 #define _(a) else if (unformat (input, #a)) a=1;
5220       foreach_ip4_proto_field
5221 #undef _
5222       else
5223         break;
5224     }
5225   
5226 #define _(a) found_something += a;
5227   foreach_ip4_proto_field;
5228 #undef _
5229   
5230   if (found_something == 0)
5231     return 0;
5232   
5233   vec_validate (mask, sizeof (*ip) - 1);
5234   
5235   ip = (ip4_header_t *) mask;
5236   
5237 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
5238   foreach_ip4_proto_field;
5239 #undef _
5240   
5241   ip->ip_version_and_header_length = 0;
5242   
5243   if (version)
5244     ip->ip_version_and_header_length |= 0xF0;
5245   
5246   if (hdr_length)
5247     ip->ip_version_and_header_length |= 0x0F;
5248   
5249   *maskp = mask;
5250   return 1;
5251 }
5252
5253 #define foreach_ip6_proto_field                 \
5254 _(src_address)                                  \
5255 _(dst_address)                                  \
5256 _(payload_length)                               \
5257 _(hop_limit)                                    \
5258 _(protocol)
5259
5260 uword unformat_ip6_mask (unformat_input_t * input, va_list * args)
5261 {
5262   u8 ** maskp = va_arg (*args, u8 **);
5263   u8 * mask = 0;
5264   u8 found_something = 0;
5265   ip6_header_t * ip;
5266   u32 ip_version_traffic_class_and_flow_label;
5267   
5268 #define _(a) u8 a=0;
5269   foreach_ip6_proto_field;
5270 #undef _
5271   u8 version = 0;
5272   u8 traffic_class = 0;
5273   u8 flow_label = 0;
5274   
5275   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5276     {
5277       if (unformat (input, "version")) 
5278         version = 1;
5279       else if (unformat (input, "traffic-class"))
5280         traffic_class = 1;
5281       else if (unformat (input, "flow-label"))
5282         flow_label = 1;
5283       else if (unformat (input, "src"))
5284         src_address = 1;
5285       else if (unformat (input, "dst"))
5286         dst_address = 1;
5287       else if (unformat (input, "proto"))
5288         protocol = 1;
5289       
5290 #define _(a) else if (unformat (input, #a)) a=1;
5291       foreach_ip6_proto_field
5292 #undef _
5293       else
5294         break;
5295     }
5296   
5297 #define _(a) found_something += a;
5298   foreach_ip6_proto_field;
5299 #undef _
5300   
5301   if (found_something == 0)
5302     return 0;
5303   
5304   vec_validate (mask, sizeof (*ip) - 1);
5305   
5306   ip = (ip6_header_t *) mask;
5307   
5308 #define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
5309   foreach_ip6_proto_field;
5310 #undef _
5311   
5312   ip_version_traffic_class_and_flow_label = 0;
5313   
5314   if (version)
5315     ip_version_traffic_class_and_flow_label |= 0xF0000000;
5316
5317   if (traffic_class)
5318     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
5319
5320   if (flow_label)
5321     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
5322
5323   ip->ip_version_traffic_class_and_flow_label = 
5324     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5325   
5326   *maskp = mask;
5327   return 1;
5328 }
5329
5330 uword unformat_l3_mask (unformat_input_t * input, va_list * args)
5331 {
5332   u8 ** maskp = va_arg (*args, u8 **);
5333
5334   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5335     if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
5336       return 1;
5337     else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
5338       return 1;
5339     else
5340       break;
5341   }
5342   return 0;
5343 }
5344
5345 uword unformat_l2_mask (unformat_input_t * input, va_list * args)
5346 {
5347   u8 ** maskp = va_arg (*args, u8 **);
5348   u8 * mask = 0;
5349   u8 src = 0;
5350   u8 dst = 0;
5351   u8 proto = 0;
5352   u8 tag1 = 0;
5353   u8 tag2 = 0;
5354   u8 ignore_tag1 = 0;
5355   u8 ignore_tag2 = 0;
5356   u8 cos1 = 0;
5357   u8 cos2 = 0;
5358   u8 dot1q = 0;
5359   u8 dot1ad = 0;
5360   int len = 14;
5361
5362   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5363     if (unformat (input, "src"))
5364       src = 1;
5365     else if (unformat (input, "dst"))
5366       dst = 1;
5367     else if (unformat (input, "proto"))
5368       proto = 1;
5369     else if (unformat (input, "tag1"))
5370       tag1 = 1;
5371     else if (unformat (input, "tag2"))
5372       tag2 = 1;
5373     else if (unformat (input, "ignore-tag1"))
5374       ignore_tag1 = 1;
5375     else if (unformat (input, "ignore-tag2"))
5376       ignore_tag2 = 1;
5377     else if (unformat (input, "cos1"))
5378       cos1 = 1;
5379     else if (unformat (input, "cos2"))
5380       cos2 = 1;
5381     else if (unformat (input, "dot1q"))
5382       dot1q = 1;
5383     else if (unformat (input, "dot1ad"))
5384       dot1ad = 1;
5385     else
5386       break;
5387   }
5388   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
5389       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5390     return 0;
5391
5392   if (tag1 || ignore_tag1 || cos1 || dot1q)
5393     len = 18;
5394   if (tag2 || ignore_tag2 || cos2 || dot1ad)
5395     len = 22;
5396
5397   vec_validate (mask, len-1);
5398
5399   if (dst)
5400     memset (mask, 0xff, 6);
5401
5402   if (src)
5403     memset (mask + 6, 0xff, 6);
5404   
5405   if (tag2 || dot1ad)
5406     {
5407       /* inner vlan tag */
5408       if (tag2)
5409         {
5410           mask[19] = 0xff;
5411           mask[18] = 0x0f;
5412         }
5413       if (cos2)
5414         mask[18] |= 0xe0;
5415       if (proto)
5416           mask[21] = mask [20] = 0xff;
5417       if (tag1)
5418         {
5419           mask [15] = 0xff;
5420           mask [14] = 0x0f;
5421         }
5422       if (cos1)
5423         mask[14] |= 0xe0;
5424       *maskp = mask;
5425       return 1;
5426     }
5427   if (tag1 | dot1q)
5428     {
5429       if (tag1)
5430         {
5431           mask [15] = 0xff;
5432           mask [14] = 0x0f;
5433         }
5434       if (cos1)
5435         mask[14] |= 0xe0;
5436       if (proto)
5437           mask[16] = mask [17] = 0xff;
5438
5439       *maskp = mask;
5440       return 1;
5441     }
5442   if (cos2)
5443     mask[18] |= 0xe0;
5444   if (cos1)
5445     mask[14] |= 0xe0;
5446   if (proto)
5447     mask[12] = mask [13] = 0xff;
5448     
5449   *maskp = mask;
5450   return 1;
5451 }
5452
5453 uword unformat_classify_mask (unformat_input_t * input, va_list * args)
5454 {
5455   u8 ** maskp = va_arg (*args, u8 **);
5456   u32 * skipp = va_arg (*args, u32 *);
5457   u32 * matchp = va_arg (*args, u32 *);
5458   u32 match;
5459   u8 * mask = 0;
5460   u8 * l2 = 0;
5461   u8 * l3 = 0;
5462   int i;
5463   
5464   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5465     if (unformat (input, "hex %U", unformat_hex_string, &mask))
5466       ;
5467     else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
5468       ;
5469     else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
5470       ;
5471     else
5472       break;
5473   }
5474
5475   if (mask || l2 || l3)
5476     {
5477       if (l2 || l3)
5478         {
5479           /* "With a free Ethernet header in every package" */
5480           if (l2 == 0)
5481             vec_validate (l2, 13);
5482           mask = l2;
5483           vec_append (mask, l3);
5484           vec_free (l3);
5485         }
5486
5487       /* Scan forward looking for the first significant mask octet */
5488       for (i = 0; i < vec_len (mask); i++)
5489         if (mask[i])
5490           break;
5491
5492       /* compute (skip, match) params */
5493       *skipp = i / sizeof(u32x4);
5494       vec_delete (mask, *skipp * sizeof(u32x4), 0);
5495
5496       /* Pad mask to an even multiple of the vector size */
5497       while (vec_len (mask) % sizeof (u32x4))
5498         vec_add1 (mask, 0);
5499
5500       match = vec_len (mask) / sizeof (u32x4);
5501
5502       for (i = match*sizeof(u32x4); i > 0; i-= sizeof(u32x4))
5503         {
5504           u64 *tmp = (u64 *)(mask + (i-sizeof(u32x4)));
5505           if (*tmp || *(tmp+1))
5506             break;
5507           match--;
5508         }
5509       if (match == 0)
5510         clib_warning ("BUG: match 0");
5511
5512       _vec_len (mask) = match * sizeof(u32x4);
5513
5514       *matchp = match;
5515       *maskp = mask;
5516
5517       return 1;
5518     }
5519
5520   return 0;
5521 }
5522
5523 #define foreach_l2_next                         \
5524 _(drop, DROP)                                   \
5525 _(ethernet, ETHERNET_INPUT)                     \
5526 _(ip4, IP4_INPUT)                               \
5527 _(ip6, IP6_INPUT)
5528
5529 uword unformat_l2_next_index (unformat_input_t * input, va_list * args)
5530 {
5531   u32 * miss_next_indexp = va_arg (*args, u32 *);
5532   u32 next_index = 0;
5533   u32 tmp;
5534   
5535 #define _(n,N) \
5536   if (unformat (input, #n)) { next_index = L2_CLASSIFY_NEXT_##N; goto out;}
5537   foreach_l2_next;
5538 #undef _
5539   
5540   if (unformat (input, "%d", &tmp))
5541     { 
5542       next_index = tmp; 
5543       goto out; 
5544     }
5545   
5546   return 0;
5547
5548  out:
5549   *miss_next_indexp = next_index;
5550   return 1;
5551 }
5552
5553 #define foreach_ip_next                         \
5554 _(miss, MISS)                                   \
5555 _(drop, DROP)                                   \
5556 _(local, LOCAL)                                 \
5557 _(rewrite, REWRITE)
5558
5559 uword unformat_ip_next_index (unformat_input_t * input, va_list * args)
5560 {
5561   u32 * miss_next_indexp = va_arg (*args, u32 *);
5562   u32 next_index = 0;
5563   u32 tmp;
5564   
5565 #define _(n,N) \
5566   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
5567   foreach_ip_next;
5568 #undef _
5569   
5570   if (unformat (input, "%d", &tmp))
5571     { 
5572       next_index = tmp; 
5573       goto out; 
5574     }
5575   
5576   return 0;
5577
5578  out:
5579   *miss_next_indexp = next_index;
5580   return 1;
5581 }
5582
5583 #define foreach_acl_next                        \
5584 _(deny, DENY)
5585
5586 uword unformat_acl_next_index (unformat_input_t * input, va_list * args)
5587 {
5588   u32 * miss_next_indexp = va_arg (*args, u32 *);
5589   u32 next_index = 0;
5590   u32 tmp;
5591
5592 #define _(n,N) \
5593   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
5594   foreach_acl_next;
5595 #undef _
5596
5597   if (unformat (input, "permit"))
5598     {
5599       next_index = ~0;
5600       goto out;
5601     }
5602   else if (unformat (input, "%d", &tmp))
5603     {
5604       next_index = tmp;
5605       goto out;
5606     }
5607
5608   return 0;
5609
5610  out:
5611   *miss_next_indexp = next_index;
5612   return 1;
5613 }
5614
5615 static int api_classify_add_del_table (vat_main_t * vam)
5616 {
5617   unformat_input_t * i = vam->input;
5618   vl_api_classify_add_del_table_t *mp;
5619
5620   u32 nbuckets = 2;
5621   u32 skip = ~0;
5622   u32 match = ~0;
5623   int is_add = 1;
5624   u32 table_index = ~0;
5625   u32 next_table_index = ~0;
5626   u32 miss_next_index = ~0;
5627   u32 memory_size = 32<<20;
5628   u8 * mask = 0;
5629   f64 timeout;
5630
5631   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
5632     if (unformat (i, "del"))
5633       is_add = 0;
5634     else if (unformat (i, "buckets %d", &nbuckets))
5635       ;
5636     else if (unformat (i, "memory_size %d", &memory_size))
5637       ;
5638     else if (unformat (i, "skip %d", &skip))
5639       ;
5640     else if (unformat (i, "match %d", &match))
5641       ;
5642     else if (unformat (i, "table %d", &table_index))
5643       ;
5644     else if (unformat (i, "mask %U", unformat_classify_mask, 
5645                        &mask, &skip, &match))
5646       ;
5647     else if (unformat (i, "next-table %d", &next_table_index))
5648       ;
5649     else if (unformat (i, "miss-next %U", unformat_ip_next_index,
5650                        &miss_next_index))
5651       ;
5652     else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
5653                        &miss_next_index))
5654       ;
5655     else if (unformat (i, "acl-miss-next %U", unformat_acl_next_index,
5656                        &miss_next_index))
5657       ;
5658     else
5659       break;
5660   }
5661   
5662   if (is_add && mask == 0) {
5663       errmsg ("Mask required\n");
5664       return -99;
5665   }
5666
5667   if (is_add && skip == ~0) {
5668       errmsg ("skip count required\n");
5669       return -99;
5670   }
5671
5672   if (is_add && match == ~0) {
5673       errmsg ("match count required\n");
5674       return -99;
5675   }
5676       
5677   if (!is_add && table_index == ~0) {
5678       errmsg ("table index required for delete\n");
5679       return -99;
5680   }
5681
5682   M2 (CLASSIFY_ADD_DEL_TABLE, classify_add_del_table,
5683       vec_len(mask));
5684
5685   mp->is_add = is_add;
5686   mp->table_index = ntohl(table_index);
5687   mp->nbuckets = ntohl(nbuckets);
5688   mp->memory_size = ntohl(memory_size);
5689   mp->skip_n_vectors = ntohl(skip);
5690   mp->match_n_vectors = ntohl(match);
5691   mp->next_table_index = ntohl(next_table_index);
5692   mp->miss_next_index = ntohl(miss_next_index);
5693   memcpy (mp->mask, mask, vec_len(mask));
5694
5695   vec_free(mask);
5696
5697   S; W;
5698   /* NOTREACHED */
5699 }
5700
5701 uword unformat_ip4_match (unformat_input_t * input, va_list * args)
5702 {
5703   u8 ** matchp = va_arg (*args, u8 **);
5704   u8 * match = 0;
5705   ip4_header_t * ip;
5706   int version = 0;
5707   u32 version_val;
5708   int hdr_length = 0;
5709   u32 hdr_length_val;
5710   int src = 0, dst = 0;
5711   ip4_address_t src_val, dst_val;
5712   int proto = 0;
5713   u32 proto_val;
5714   int tos = 0;
5715   u32 tos_val;
5716   int length = 0;
5717   u32 length_val;
5718   int fragment_id = 0;
5719   u32 fragment_id_val;
5720   int ttl = 0;
5721   int ttl_val;
5722   int checksum = 0;
5723   u32 checksum_val;
5724
5725   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5726     {
5727       if (unformat (input, "version %d", &version_val)) 
5728         version = 1;
5729       else if (unformat (input, "hdr_length %d", &hdr_length_val))
5730         hdr_length = 1;
5731       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
5732         src = 1;
5733       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
5734         dst = 1;
5735       else if (unformat (input, "proto %d", &proto_val))
5736         proto = 1;
5737       else if (unformat (input, "tos %d", &tos_val))
5738         tos = 1;
5739       else if (unformat (input, "length %d", &length_val))
5740         length = 1;
5741       else if (unformat (input, "fragment_id %d", &fragment_id_val))
5742         fragment_id = 1;
5743       else if (unformat (input, "ttl %d", &ttl_val))
5744         ttl = 1;
5745       else if (unformat (input, "checksum %d", &checksum_val))
5746         checksum = 1;
5747       else
5748         break;
5749     }
5750   
5751   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
5752       + ttl + checksum == 0)
5753     return 0;
5754
5755   /* 
5756    * Aligned because we use the real comparison functions
5757    */
5758   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
5759   
5760   ip = (ip4_header_t *) match;
5761   
5762   /* These are realistically matched in practice */
5763   if (src)
5764     ip->src_address.as_u32 = src_val.as_u32;
5765
5766   if (dst)
5767     ip->dst_address.as_u32 = dst_val.as_u32;
5768   
5769   if (proto)
5770     ip->protocol = proto_val;
5771     
5772
5773   /* These are not, but they're included for completeness */
5774   if (version)
5775     ip->ip_version_and_header_length |= (version_val & 0xF)<<4;
5776
5777   if (hdr_length)
5778     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
5779     
5780   if (tos)
5781     ip->tos = tos_val;
5782   
5783   if (length)
5784     ip->length = length_val;
5785   
5786   if (ttl)
5787     ip->ttl = ttl_val;
5788
5789   if (checksum)
5790     ip->checksum = checksum_val;
5791
5792   *matchp = match;
5793   return 1;
5794 }
5795
5796 uword unformat_ip6_match (unformat_input_t * input, va_list * args)
5797 {
5798   u8 ** matchp = va_arg (*args, u8 **);
5799   u8 * match = 0;
5800   ip6_header_t * ip;
5801   int version = 0;
5802   u32 version_val;
5803   u8  traffic_class;
5804   u32 traffic_class_val;
5805   u8  flow_label;
5806   u8  flow_label_val;
5807   int src = 0, dst = 0;
5808   ip6_address_t src_val, dst_val;
5809   int proto = 0;
5810   u32 proto_val;
5811   int payload_length = 0;
5812   u32 payload_length_val;
5813   int hop_limit = 0;
5814   int hop_limit_val;
5815   u32 ip_version_traffic_class_and_flow_label;
5816
5817   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
5818     {
5819       if (unformat (input, "version %d", &version_val)) 
5820         version = 1;
5821       else if (unformat (input, "traffic_class %d", &traffic_class_val))
5822         traffic_class = 1;
5823       else if (unformat (input, "flow_label %d", &flow_label_val))
5824         flow_label = 1;
5825       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
5826         src = 1;
5827       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
5828         dst = 1;
5829       else if (unformat (input, "proto %d", &proto_val))
5830         proto = 1;
5831       else if (unformat (input, "payload_length %d", &payload_length_val))
5832         payload_length = 1;
5833       else if (unformat (input, "hop_limit %d", &hop_limit_val))
5834         hop_limit = 1;
5835       else
5836         break;
5837     }
5838   
5839   if (version + traffic_class + flow_label + src + dst + proto +
5840       payload_length + hop_limit == 0)
5841     return 0;
5842
5843   /* 
5844    * Aligned because we use the real comparison functions
5845    */
5846   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof(u32x4));
5847   
5848   ip = (ip6_header_t *) match;
5849   
5850   if (src)
5851     memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
5852
5853   if (dst)
5854     memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
5855   
5856   if (proto)
5857     ip->protocol = proto_val;
5858     
5859   ip_version_traffic_class_and_flow_label = 0;
5860
5861   if (version)
5862     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
5863
5864   if (traffic_class)
5865     ip_version_traffic_class_and_flow_label |= (traffic_class_val & 0xFF) << 20;
5866
5867   if (flow_label)
5868     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
5869     
5870   ip->ip_version_traffic_class_and_flow_label = 
5871     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
5872
5873   if (payload_length)
5874     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
5875   
5876   if (hop_limit)
5877     ip->hop_limit = hop_limit_val;
5878
5879   *matchp = match;
5880   return 1;
5881 }
5882
5883 uword unformat_l3_match (unformat_input_t * input, va_list * args)
5884 {
5885   u8 ** matchp = va_arg (*args, u8 **);
5886
5887   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5888     if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
5889       return 1;
5890     else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
5891       return 1;
5892     else
5893       break;
5894   }
5895   return 0;
5896 }
5897
5898 uword unformat_vlan_tag (unformat_input_t * input, va_list * args)
5899 {
5900   u8 * tagp = va_arg (*args, u8 *);
5901   u32 tag;
5902
5903   if (unformat(input, "%d", &tag))
5904     {
5905       tagp[0] = (tag>>8) & 0x0F;
5906       tagp[1] = tag & 0xFF;
5907       return 1;
5908     }
5909
5910   return 0;
5911 }
5912
5913 uword unformat_l2_match (unformat_input_t * input, va_list * args)
5914 {
5915   u8 ** matchp = va_arg (*args, u8 **);
5916   u8 * match = 0;
5917   u8 src = 0;
5918   u8 src_val[6];
5919   u8 dst = 0;
5920   u8 dst_val[6];
5921   u8 proto = 0;
5922   u16 proto_val;
5923   u8 tag1 = 0;
5924   u8 tag1_val [2];
5925   u8 tag2 = 0;
5926   u8 tag2_val [2];
5927   int len = 14;
5928   u8 ignore_tag1 = 0;
5929   u8 ignore_tag2 = 0;
5930   u8 cos1 = 0;
5931   u8 cos2 = 0;
5932   u32 cos1_val = 0;
5933   u32 cos2_val = 0;
5934
5935   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
5936     if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
5937       src = 1;
5938     else if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
5939       dst = 1;
5940     else if (unformat (input, "proto %U", 
5941                        unformat_ethernet_type_host_byte_order, &proto_val))
5942       proto = 1;
5943     else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
5944       tag1 = 1;
5945     else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
5946       tag2 = 1;
5947     else if (unformat (input, "ignore-tag1"))
5948       ignore_tag1 = 1;
5949     else if (unformat (input, "ignore-tag2"))
5950       ignore_tag2 = 1;
5951     else if (unformat (input, "cos1 %d", &cos1_val))
5952       cos1 = 1;
5953     else if (unformat (input, "cos2 %d", &cos2_val))
5954       cos2 = 1;
5955     else
5956       break;
5957   }
5958   if ((src + dst + proto + tag1 + tag2 +
5959       ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
5960     return 0;
5961
5962   if (tag1 || ignore_tag1 || cos1)
5963     len = 18;
5964   if (tag2 || ignore_tag2 || cos2)
5965     len = 22;
5966
5967   vec_validate_aligned (match, len-1, sizeof(u32x4));
5968
5969   if (dst)
5970     memcpy (match, dst_val, 6);
5971
5972   if (src)
5973     memcpy (match + 6, src_val, 6);
5974   
5975   if (tag2)
5976     {
5977       /* inner vlan tag */
5978       match[19] = tag2_val[1];
5979       match[18] = tag2_val[0];
5980       if (cos2)
5981         match [18] |= (cos2_val & 0x7) << 5;
5982       if (proto)
5983         {
5984           match[21] = proto_val & 0xff;
5985           match[20] = proto_val >> 8;
5986         }
5987       if (tag1)
5988         {
5989           match [15] = tag1_val[1];
5990           match [14] = tag1_val[0];
5991         }
5992       if (cos1)
5993         match [14] |= (cos1_val & 0x7) << 5;
5994       *matchp = match;
5995       return 1;
5996     }
5997   if (tag1)
5998     {
5999       match [15] = tag1_val[1];
6000       match [14] = tag1_val[0];
6001       if (proto)
6002         {
6003           match[17] = proto_val & 0xff;
6004           match[16] = proto_val >> 8;
6005         }
6006       if (cos1)
6007         match [14] |= (cos1_val & 0x7) << 5;
6008
6009       *matchp = match;
6010       return 1;
6011     }
6012   if (cos2)
6013     match [18] |= (cos2_val & 0x7) << 5;
6014   if (cos1)
6015     match [14] |= (cos1_val & 0x7) << 5;
6016   if (proto)
6017     {
6018       match[13] = proto_val & 0xff;
6019       match[12] = proto_val >> 8;
6020     }
6021   
6022   *matchp = match;
6023   return 1;
6024 }
6025
6026
6027 uword unformat_classify_match (unformat_input_t * input, va_list * args)
6028 {
6029   u8 ** matchp = va_arg (*args, u8 **);
6030   u32 skip_n_vectors = va_arg (*args, u32);
6031   u32 match_n_vectors = va_arg (*args, u32);
6032   
6033   u8 * match = 0;
6034   u8 * l2 = 0;
6035   u8 * l3 = 0;
6036
6037   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
6038     if (unformat (input, "hex %U", unformat_hex_string, &match))
6039       ;
6040     else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
6041       ;
6042     else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
6043       ;
6044     else
6045       break;
6046   }
6047
6048   if (match || l2 || l3)
6049     {
6050       if (l2 || l3)
6051         {
6052           /* "Win a free Ethernet header in every packet" */
6053           if (l2 == 0)
6054             vec_validate_aligned (l2, 13, sizeof(u32x4));
6055           match = l2;
6056           vec_append_aligned (match, l3, sizeof(u32x4));
6057           vec_free (l3);
6058         }
6059
6060       /* Make sure the vector is big enough even if key is all 0's */
6061       vec_validate_aligned 
6062           (match, ((match_n_vectors + skip_n_vectors) * sizeof(u32x4)) - 1,
6063            sizeof(u32x4));
6064       
6065       /* Set size, include skipped vectors*/
6066       _vec_len (match) = (match_n_vectors+skip_n_vectors) * sizeof(u32x4);
6067
6068       *matchp = match;
6069
6070       return 1;
6071     }
6072
6073   return 0;
6074 }
6075
6076 static int api_classify_add_del_session (vat_main_t * vam)
6077 {
6078     unformat_input_t * i = vam->input;
6079     vl_api_classify_add_del_session_t *mp;
6080     int is_add = 1;
6081     u32 table_index = ~0;
6082     u32 hit_next_index = ~0;
6083     u32 opaque_index = ~0;
6084     u8 * match = 0;
6085     i32 advance = 0;
6086     f64 timeout;
6087     u32 skip_n_vectors = 0;
6088     u32 match_n_vectors = 0;
6089
6090     /* 
6091      * Warning: you have to supply skip_n and match_n
6092      * because the API client cant simply look at the classify
6093      * table object.
6094      */
6095
6096     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6097         if (unformat (i, "del"))
6098             is_add = 0;
6099         else if (unformat (i, "hit-next %U", unformat_ip_next_index,
6100                            &hit_next_index))
6101             ;
6102         else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
6103                            &hit_next_index))
6104             ;
6105         else if (unformat (i, "acl-hit-next %U", unformat_acl_next_index,
6106                            &hit_next_index))
6107             ;
6108         else if (unformat (i, "opaque-index %d", &opaque_index))
6109             ;
6110         else if (unformat (i, "skip_n %d", &skip_n_vectors))
6111             ;
6112         else if (unformat (i, "match_n %d", &match_n_vectors))
6113             ;
6114         else if (unformat (i, "match %U", unformat_classify_match,
6115                            &match, skip_n_vectors, match_n_vectors))
6116             ;
6117         else if (unformat (i, "advance %d", &advance))
6118             ;
6119         else if (unformat (i, "table-index %d", &table_index))
6120             ;
6121         else
6122             break;
6123     }
6124
6125     if (table_index == ~0) {
6126         errmsg ("Table index required\n");
6127         return -99;
6128     }
6129
6130     if (is_add && match == 0) {
6131         errmsg ("Match value required\n");
6132         return -99;
6133     }
6134
6135     M2 (CLASSIFY_ADD_DEL_SESSION, classify_add_del_session,
6136         vec_len(match));
6137
6138     mp->is_add = is_add;
6139     mp->table_index = ntohl(table_index);
6140     mp->hit_next_index = ntohl(hit_next_index);
6141     mp->opaque_index = ntohl(opaque_index);
6142     mp->advance = ntohl(advance);
6143     memcpy (mp->match, match, vec_len(match));
6144     vec_free(match);
6145
6146     S; W;
6147     /* NOTREACHED */
6148 }
6149
6150 static int api_classify_set_interface_ip_table (vat_main_t * vam)
6151 {
6152     unformat_input_t * i = vam->input;
6153     vl_api_classify_set_interface_ip_table_t *mp;
6154     f64 timeout;
6155     u32 sw_if_index;
6156     int sw_if_index_set;
6157     u32 table_index = ~0;
6158     u8  is_ipv6 = 0;
6159
6160     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6161         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6162             sw_if_index_set = 1;
6163         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6164             sw_if_index_set = 1;
6165         else if (unformat (i, "table %d", &table_index))
6166             ;
6167         else {
6168             clib_warning ("parse error '%U'", format_unformat_error, i);
6169             return -99;
6170         }
6171     }
6172     
6173     if (sw_if_index_set == 0) {
6174         errmsg ("missing interface name or sw_if_index\n");
6175         return -99;
6176     }
6177
6178
6179     M(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table);
6180
6181     mp->sw_if_index = ntohl(sw_if_index);
6182     mp->table_index = ntohl(table_index);
6183     mp->is_ipv6 = is_ipv6;
6184
6185     S; W;
6186     /* NOTREACHED */
6187     return 0;
6188 }
6189
6190 static int api_classify_set_interface_l2_tables (vat_main_t * vam)
6191 {
6192     unformat_input_t * i = vam->input;
6193     vl_api_classify_set_interface_l2_tables_t *mp;
6194     f64 timeout;
6195     u32 sw_if_index;
6196     int sw_if_index_set;
6197     u32 ip4_table_index = ~0;
6198     u32 ip6_table_index = ~0;
6199     u32 other_table_index = ~0;
6200
6201     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6202         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6203             sw_if_index_set = 1;
6204         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6205             sw_if_index_set = 1;
6206         else if (unformat (i, "ip4-table %d", &ip4_table_index))
6207             ;
6208         else if (unformat (i, "ip6-table %d", &ip6_table_index))
6209             ;
6210         else if (unformat (i, "other-table %d", &other_table_index))
6211             ;
6212         else {
6213             clib_warning ("parse error '%U'", format_unformat_error, i);
6214             return -99;
6215         }
6216     }
6217     
6218     if (sw_if_index_set == 0) {
6219         errmsg ("missing interface name or sw_if_index\n");
6220         return -99;
6221     }
6222
6223
6224     M(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables);
6225
6226     mp->sw_if_index = ntohl(sw_if_index);
6227     mp->ip4_table_index = ntohl(ip4_table_index);
6228     mp->ip6_table_index = ntohl(ip6_table_index);
6229     mp->other_table_index = ntohl(other_table_index);
6230
6231
6232     S; W;
6233     /* NOTREACHED */
6234     return 0;
6235 }
6236
6237 static int api_get_node_index (vat_main_t * vam)
6238 {
6239     unformat_input_t * i = vam->input;
6240     vl_api_get_node_index_t * mp;
6241     f64 timeout;
6242     u8 * name = 0;
6243     
6244     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6245         if (unformat (i, "node %s", &name))
6246             ;
6247         else
6248             break;
6249     }
6250     if (name == 0) {
6251         errmsg ("node name required\n");
6252         return -99;
6253     }
6254     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
6255         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
6256         return -99;
6257     }
6258
6259     M(GET_NODE_INDEX, get_node_index);
6260     memcpy (mp->node_name, name, vec_len(name));
6261     vec_free(name);
6262     
6263     S; W;
6264     /* NOTREACHED */
6265     return 0;
6266 }
6267
6268 static int api_add_node_next (vat_main_t * vam)
6269 {
6270     unformat_input_t * i = vam->input;
6271     vl_api_add_node_next_t * mp;
6272     f64 timeout;
6273     u8 * name = 0;
6274     u8 * next = 0;
6275
6276     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6277         if (unformat (i, "node %s", &name))
6278             ;
6279         else if (unformat (i, "next %s", &next))
6280             ;
6281         else
6282             break;
6283     }
6284     if (name == 0) {
6285         errmsg ("node name required\n");
6286         return -99;
6287     }
6288     if (vec_len (name) >= ARRAY_LEN(mp->node_name)) {
6289         errmsg ("node name too long, max %d\n", ARRAY_LEN(mp->node_name));
6290         return -99;
6291     }
6292     if (next == 0) {
6293         errmsg ("next node required\n");
6294         return -99;
6295     }
6296     if (vec_len (next) >= ARRAY_LEN(mp->next_name)) {
6297         errmsg ("next name too long, max %d\n", ARRAY_LEN(mp->next_name));
6298         return -99;
6299     }
6300     
6301     M(ADD_NODE_NEXT, add_node_next);
6302     memcpy (mp->node_name, name, vec_len(name));
6303     memcpy (mp->next_name, next, vec_len(next));
6304     vec_free(name);
6305     vec_free(next);
6306     
6307     S; W;
6308     /* NOTREACHED */
6309     return 0;
6310 }
6311
6312 static int api_l2tpv3_create_tunnel (vat_main_t * vam)
6313 {
6314     unformat_input_t * i = vam->input;
6315     ip6_address_t client_address, our_address;
6316     int client_address_set = 0;
6317     int our_address_set = 0;
6318     u32 local_session_id = 0;
6319     u32 remote_session_id = 0;
6320     u64 local_cookie = 0;
6321     u64 remote_cookie = 0;
6322     u8 l2_sublayer_present = 0;
6323     vl_api_l2tpv3_create_tunnel_t * mp;
6324     f64 timeout;
6325
6326     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6327         if (unformat (i, "client_address %U", unformat_ip6_address, 
6328                       &client_address))
6329             client_address_set = 1;
6330         else if (unformat (i, "our_address %U", unformat_ip6_address, 
6331                            &our_address))
6332             our_address_set = 1;
6333         else if (unformat (i, "local_session_id %d", &local_session_id))
6334             ;
6335         else if (unformat (i, "remote_session_id %d", &remote_session_id))
6336             ;
6337         else if (unformat (i, "local_cookie %lld", &local_cookie))
6338             ;
6339         else if (unformat (i, "remote_cookie %lld", &remote_cookie))
6340             ;
6341         else if (unformat (i, "l2-sublayer-present"))
6342             l2_sublayer_present = 1;
6343         else
6344             break;
6345     }
6346
6347     if (client_address_set == 0) {
6348         errmsg ("client_address required\n");
6349         return -99;
6350     }
6351
6352     if (our_address_set == 0) {
6353         errmsg ("our_address required\n");
6354         return -99;
6355     }
6356
6357     M(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel);
6358
6359     memcpy (mp->client_address, client_address.as_u8, 
6360             sizeof (mp->client_address));
6361
6362     memcpy (mp->our_address, our_address.as_u8, 
6363             sizeof (mp->our_address));
6364     
6365     mp->local_session_id = ntohl (local_session_id);
6366     mp->remote_session_id = ntohl (remote_session_id);
6367     mp->local_cookie = clib_host_to_net_u64 (local_cookie);
6368     mp->remote_cookie = clib_host_to_net_u64 (remote_cookie);
6369     mp->l2_sublayer_present = l2_sublayer_present;
6370     mp->is_ipv6 = 1;
6371
6372     S; W;
6373     /* NOTREACHED */
6374     return 0;
6375 }
6376
6377 static int api_l2tpv3_set_tunnel_cookies (vat_main_t * vam)
6378 {
6379     unformat_input_t * i = vam->input;
6380     u32 sw_if_index;
6381     u8  sw_if_index_set = 0;
6382     u64 new_local_cookie = 0;
6383     u64 new_remote_cookie = 0;
6384     vl_api_l2tpv3_set_tunnel_cookies_t *mp;
6385     f64 timeout;
6386
6387     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6388         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6389             sw_if_index_set = 1;
6390         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6391             sw_if_index_set = 1;
6392         else if (unformat (i, "new_local_cookie %lld", &new_local_cookie))
6393             ;
6394         else if (unformat (i, "new_remote_cookie %lld", &new_remote_cookie))
6395             ;
6396         else
6397             break;
6398     }
6399
6400     if (sw_if_index_set == 0) {
6401         errmsg ("missing interface name or sw_if_index\n");
6402         return -99;
6403     }
6404
6405     M(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies);
6406
6407     mp->sw_if_index = ntohl(sw_if_index);
6408     mp->new_local_cookie = clib_host_to_net_u64 (new_local_cookie);
6409     mp->new_remote_cookie = clib_host_to_net_u64 (new_remote_cookie);
6410
6411     S; W;
6412     /* NOTREACHED */
6413     return 0;
6414 }
6415
6416 static int api_l2tpv3_interface_enable_disable (vat_main_t * vam)
6417 {
6418     unformat_input_t * i = vam->input;
6419     vl_api_l2tpv3_interface_enable_disable_t *mp;
6420     f64 timeout;
6421     u32 sw_if_index;
6422     u8  sw_if_index_set = 0;
6423     u8  enable_disable = 1;
6424
6425     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6426         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6427             sw_if_index_set = 1;
6428         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6429             sw_if_index_set = 1;
6430         else if (unformat (i, "enable"))
6431             enable_disable = 1;
6432         else if (unformat (i, "disable"))
6433             enable_disable = 0;
6434         else
6435             break;
6436     }
6437
6438     if (sw_if_index_set == 0) {
6439         errmsg ("missing interface name or sw_if_index\n");
6440         return -99;
6441     }
6442     
6443     M(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable);
6444
6445     mp->sw_if_index = ntohl(sw_if_index);
6446     mp->enable_disable = enable_disable;
6447
6448     S; W;
6449     /* NOTREACHED */
6450     return 0;
6451 }
6452
6453 static int api_l2tpv3_set_lookup_key (vat_main_t * vam)
6454 {
6455     unformat_input_t * i = vam->input;
6456     vl_api_l2tpv3_set_lookup_key_t * mp;
6457     f64 timeout;
6458     u8 key = ~0;
6459
6460     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6461         if (unformat (i, "lookup_v6_src"))
6462             key = L2T_LOOKUP_SRC_ADDRESS;
6463         else if (unformat (i, "lookup_v6_dst"))
6464             key = L2T_LOOKUP_DST_ADDRESS;
6465         else if (unformat (i, "lookup_session_id"))
6466             key = L2T_LOOKUP_SESSION_ID;
6467         else
6468             break;
6469     }
6470
6471     if (key == ~0) {
6472         errmsg ("l2tp session lookup key unset\n");
6473         return -99;
6474     }
6475     
6476     M(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key);
6477
6478     mp->key = key;
6479
6480     S; W;
6481     /* NOTREACHED */
6482     return 0;
6483 }
6484
6485 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler
6486 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
6487 {
6488     vat_main_t * vam = &vat_main;
6489
6490     fformat(vam->ofp,  "* %U (our) %U (client) (sw_if_index %d)\n",
6491               format_ip6_address, mp->our_address,
6492               format_ip6_address, mp->client_address,
6493               clib_net_to_host_u32(mp->sw_if_index));
6494
6495     fformat (vam->ofp, "   local cookies %016llx %016llx remote cookie %016llx\n",
6496               clib_net_to_host_u64 (mp->local_cookie[0]),
6497               clib_net_to_host_u64 (mp->local_cookie[1]),
6498               clib_net_to_host_u64 (mp->remote_cookie));
6499
6500     fformat (vam->ofp, "   local session-id %d remote session-id %d\n",
6501               clib_net_to_host_u32 (mp->local_session_id),
6502               clib_net_to_host_u32 (mp->remote_session_id));
6503
6504     fformat (vam->ofp, "   l2 specific sublayer %s\n\n",
6505               mp->l2_sublayer_present ? "preset" : "absent");
6506
6507 }
6508
6509 static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler_json
6510 (vl_api_sw_if_l2tpv3_tunnel_details_t * mp)
6511 {
6512     vat_main_t * vam = &vat_main;
6513     vat_json_node_t *node = NULL;
6514     struct in6_addr addr;
6515
6516     if (VAT_JSON_ARRAY != vam->json_tree.type) {
6517         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
6518         vat_json_init_array(&vam->json_tree);
6519     }
6520     node = vat_json_array_add(&vam->json_tree);
6521
6522     vat_json_init_object(node);
6523
6524     memcpy(&addr, mp->our_address, sizeof(addr));
6525     vat_json_object_add_ip6(node, "our_address", addr);
6526     memcpy(&addr, mp->client_address, sizeof(addr));
6527     vat_json_object_add_ip6(node, "client_address", addr);
6528
6529     vat_json_node_t * lc = vat_json_object_add(node, "local_cookie");
6530     vat_json_init_array(lc);
6531     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[0]));
6532     vat_json_array_add_uint(lc, clib_net_to_host_u64(mp->local_cookie[1]));
6533     vat_json_object_add_uint(node, "remote_cookie", clib_net_to_host_u64(mp->remote_cookie));
6534
6535     printf("local id: %u", clib_net_to_host_u32(mp->local_session_id));
6536     vat_json_object_add_uint(node, "local_session_id", clib_net_to_host_u32(mp->local_session_id));
6537     vat_json_object_add_uint(node, "remote_session_id", clib_net_to_host_u32(mp->remote_session_id));
6538     vat_json_object_add_string_copy(node, "l2_sublayer", mp->l2_sublayer_present ?
6539             (u8*)"present" : (u8*)"absent");
6540 }
6541
6542 static int api_sw_if_l2tpv3_tunnel_dump (vat_main_t * vam)
6543 {
6544     vl_api_sw_if_l2tpv3_tunnel_dump_t *mp;
6545     f64 timeout;
6546
6547     /* Get list of l2tpv3-tunnel interfaces */
6548     M(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump);
6549     S;
6550
6551     /* Use a control ping for synchronization */
6552     {
6553         vl_api_control_ping_t * mp;
6554         M(CONTROL_PING, control_ping);
6555         S;
6556     }
6557     W;
6558 }
6559
6560
6561 static void vl_api_sw_interface_tap_details_t_handler
6562 (vl_api_sw_interface_tap_details_t * mp)
6563 {
6564     vat_main_t * vam = &vat_main;
6565
6566     fformat(vam->ofp,  "%-16s %d\n",
6567               mp->dev_name,
6568               clib_net_to_host_u32(mp->sw_if_index));
6569 }
6570
6571 static void vl_api_sw_interface_tap_details_t_handler_json
6572 (vl_api_sw_interface_tap_details_t * mp)
6573 {
6574     vat_main_t * vam = &vat_main;
6575     vat_json_node_t *node = NULL;
6576
6577     if (VAT_JSON_ARRAY != vam->json_tree.type) {
6578         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
6579         vat_json_init_array(&vam->json_tree);
6580     }
6581     node = vat_json_array_add(&vam->json_tree);
6582
6583     vat_json_init_object(node);
6584     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
6585     vat_json_object_add_string_copy(node, "dev_name", mp->dev_name);
6586 }
6587
6588 static int api_sw_interface_tap_dump (vat_main_t * vam)
6589 {
6590     vl_api_sw_interface_tap_dump_t *mp;
6591     f64 timeout;
6592
6593     fformat(vam->ofp,  "\n%-16s %s\n", "dev_name", "sw_if_index");
6594     /* Get list of tap interfaces */
6595     M(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump);
6596     S;
6597
6598     /* Use a control ping for synchronization */
6599     {
6600         vl_api_control_ping_t * mp;
6601         M(CONTROL_PING, control_ping);
6602         S;
6603     }
6604     W;
6605 }
6606
6607 static uword unformat_vxlan_decap_next 
6608 (unformat_input_t * input, va_list * args)
6609 {
6610   u32 * result = va_arg (*args, u32 *);
6611   u32 tmp;
6612   
6613   if (unformat (input, "drop"))
6614     *result = VXLAN_INPUT_NEXT_DROP;
6615   else if (unformat (input, "ip4"))
6616     *result = VXLAN_INPUT_NEXT_IP4_INPUT;
6617   else if (unformat (input, "ip6"))
6618     *result = VXLAN_INPUT_NEXT_IP6_INPUT;
6619   else if (unformat (input, "l2"))
6620     *result = VXLAN_INPUT_NEXT_L2_INPUT;
6621   else if (unformat (input, "%d", &tmp))
6622     *result = tmp;
6623   else
6624     return 0;
6625   return 1;
6626 }
6627
6628 static int api_vxlan_add_del_tunnel (vat_main_t * vam)
6629 {
6630     unformat_input_t * line_input = vam->input;
6631     vl_api_vxlan_add_del_tunnel_t *mp;
6632     f64 timeout;
6633     ip4_address_t src, dst;
6634     u8 is_add = 1;
6635     u8 src_set = 0;
6636     u8 dst_set = 0;
6637     u32 encap_vrf_id = 0;
6638     u32 decap_next_index = ~0;
6639     u32 vni = 0;
6640
6641     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
6642         if (unformat (line_input, "del"))
6643             is_add = 0;
6644         else if (unformat (line_input, "src %U", 
6645                            unformat_ip4_address, &src))
6646             src_set = 1;
6647         else if (unformat (line_input, "dst %U",
6648                            unformat_ip4_address, &dst))
6649             dst_set = 1;
6650         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
6651             ;
6652         else if (unformat (line_input, "decap-next %U", 
6653                            unformat_vxlan_decap_next, &decap_next_index))
6654             ;
6655         else if (unformat (line_input, "vni %d", &vni))
6656             ;
6657         else {
6658             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
6659             return -99;
6660         }
6661     }
6662
6663     if (src_set == 0) {
6664         errmsg ("tunnel src address not specified\n");
6665         return -99;
6666     }
6667     if (dst_set == 0) {
6668         errmsg ("tunnel dst address not specified\n");
6669         return -99;
6670     }
6671
6672     if ((vni == 0) || (vni>>24)) {
6673         errmsg ("vni not specified or out of range\n");
6674         return -99;
6675     }
6676
6677     M (VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel);
6678     
6679     mp->src_address = src.as_u32;
6680     mp->dst_address = dst.as_u32;
6681     mp->encap_vrf_id = ntohl(encap_vrf_id);
6682     mp->decap_next_index = ntohl(decap_next_index);
6683     mp->vni = ntohl(vni);
6684     mp->is_add = is_add;
6685
6686     S; W;
6687     /* NOTREACHED */
6688     return 0;
6689 }
6690
6691 static void vl_api_vxlan_tunnel_details_t_handler
6692 (vl_api_vxlan_tunnel_details_t * mp)
6693 {
6694     vat_main_t * vam = &vat_main;
6695
6696     fformat(vam->ofp, "%11d%13U%13U%14d%18d%13d\n",
6697             ntohl(mp->sw_if_index),
6698             format_ip4_address, &mp->src_address,
6699             format_ip4_address, &mp->dst_address,
6700             ntohl(mp->encap_vrf_id),
6701             ntohl(mp->decap_next_index),
6702             ntohl(mp->vni));
6703 }
6704
6705 static void vl_api_vxlan_tunnel_details_t_handler_json
6706 (vl_api_vxlan_tunnel_details_t * mp)
6707 {
6708     vat_main_t * vam = &vat_main;
6709     vat_json_node_t *node = NULL;
6710     struct in_addr ip4;
6711
6712     if (VAT_JSON_ARRAY != vam->json_tree.type) {
6713         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
6714         vat_json_init_array(&vam->json_tree);
6715     }
6716     node = vat_json_array_add(&vam->json_tree);
6717
6718     vat_json_init_object(node);
6719     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
6720     memcpy(&ip4, &mp->src_address, sizeof(ip4));
6721     vat_json_object_add_ip4(node, "src_address", ip4);
6722     memcpy(&ip4, &mp->dst_address, sizeof(ip4));
6723     vat_json_object_add_ip4(node, "dst_address", ip4);
6724     vat_json_object_add_uint(node, "encap_vrf_id", ntohl(mp->encap_vrf_id));
6725     vat_json_object_add_uint(node, "decap_next_index", ntohl(mp->decap_next_index));
6726     vat_json_object_add_uint(node, "vni", ntohl(mp->vni));
6727 }
6728
6729 static int api_vxlan_tunnel_dump (vat_main_t * vam)
6730 {
6731     unformat_input_t * i = vam->input;
6732     vl_api_vxlan_tunnel_dump_t *mp;
6733     f64 timeout;
6734     u32 sw_if_index;
6735     u8 sw_if_index_set = 0;
6736
6737     /* Parse args required to build the message */
6738     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6739         if (unformat (i, "sw_if_index %d", &sw_if_index))
6740             sw_if_index_set = 1;
6741         else
6742             break;
6743     }
6744
6745     if (sw_if_index_set == 0) {
6746         sw_if_index = ~0;
6747     }
6748
6749     if (!vam->json_output) {
6750         fformat(vam->ofp, "%11s%13s%13s%14s%18s%13s\n",
6751                 "sw_if_index", "src_address", "dst_address",
6752                 "encap_vrf_id", "decap_next_index", "vni");
6753     }
6754
6755     /* Get list of l2tpv3-tunnel interfaces */
6756     M(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump);
6757
6758     mp->sw_if_index = htonl(sw_if_index);
6759
6760     S;
6761
6762     /* Use a control ping for synchronization */
6763     {
6764         vl_api_control_ping_t * mp;
6765         M(CONTROL_PING, control_ping);
6766         S;
6767     }
6768     W;
6769 }
6770
6771 static int api_l2_fib_clear_table (vat_main_t * vam)
6772 {
6773 //  unformat_input_t * i = vam->input;
6774     vl_api_l2_fib_clear_table_t *mp;
6775     f64 timeout;
6776
6777     M(L2_FIB_CLEAR_TABLE, l2_fib_clear_table);
6778
6779     S; W;
6780     /* NOTREACHED */
6781     return 0;
6782 }
6783
6784 static int api_l2_interface_efp_filter (vat_main_t * vam)
6785 {
6786     unformat_input_t * i = vam->input;
6787     vl_api_l2_interface_efp_filter_t *mp;
6788     f64 timeout;
6789     u32 sw_if_index;
6790     u8 enable = 1;
6791     u8 sw_if_index_set = 0;
6792
6793     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6794         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6795             sw_if_index_set = 1;
6796         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6797             sw_if_index_set = 1;
6798         else if (unformat (i, "enable"))
6799             enable = 1;
6800         else if (unformat (i, "disable"))
6801             enable = 0;
6802         else {
6803             clib_warning ("parse error '%U'", format_unformat_error, i);
6804             return -99;
6805         }
6806     }
6807     
6808     if (sw_if_index_set == 0) {
6809         errmsg ("missing sw_if_index\n");
6810         return -99;
6811     }
6812
6813     M(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter);
6814
6815     mp->sw_if_index = ntohl(sw_if_index);
6816     mp->enable_disable = enable;
6817
6818     S; W;
6819     /* NOTREACHED */
6820     return 0;
6821 }
6822
6823 #define foreach_vtr_op                          \
6824 _("disable",  L2_VTR_DISABLED)                  \
6825 _("push-1",  L2_VTR_PUSH_1)                     \
6826 _("push-2",  L2_VTR_PUSH_2)                     \
6827 _("pop-1",  L2_VTR_POP_1)                       \
6828 _("pop-2",  L2_VTR_POP_2)                       \
6829 _("translate-1-1",  L2_VTR_TRANSLATE_1_1)       \
6830 _("translate-1-2",  L2_VTR_TRANSLATE_1_2)       \
6831 _("translate-2-1",  L2_VTR_TRANSLATE_2_1)       \
6832 _("translate-2-2",  L2_VTR_TRANSLATE_2_2)
6833
6834 static int api_l2_interface_vlan_tag_rewrite (vat_main_t * vam)
6835 {
6836     unformat_input_t * i = vam->input;
6837     vl_api_l2_interface_vlan_tag_rewrite_t *mp;
6838     f64 timeout;
6839     u32 sw_if_index;
6840     u8 sw_if_index_set = 0;
6841     u8 vtr_op_set = 0;
6842     u32 vtr_op = 0;
6843     u32 push_dot1q = 1;
6844     u32 tag1 = ~0;
6845     u32 tag2 = ~0;
6846
6847     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6848         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6849             sw_if_index_set = 1;
6850         else if (unformat (i, "sw_if_index %d", &sw_if_index))
6851             sw_if_index_set = 1;
6852         else if (unformat (i, "vtr_op %d", &vtr_op))
6853             vtr_op_set = 1;
6854 #define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;}
6855         foreach_vtr_op
6856 #undef _
6857         
6858         else if (unformat (i, "push_dot1q %d", &push_dot1q))
6859             ;
6860         else if (unformat (i, "tag1 %d", &tag1))
6861             ;
6862         else if (unformat (i, "tag2 %d", &tag2))
6863             ;
6864         else {
6865             clib_warning ("parse error '%U'", format_unformat_error, i);
6866             return -99;
6867         }
6868     }
6869     
6870     if ((sw_if_index_set == 0)||(vtr_op_set == 0)) {
6871         errmsg ("missing vtr operation or sw_if_index\n");
6872         return -99;
6873     }
6874
6875     M(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)
6876
6877     mp->sw_if_index = ntohl(sw_if_index);
6878     mp->vtr_op = ntohl(vtr_op);
6879     mp->push_dot1q = ntohl(push_dot1q);
6880     mp->tag1 = ntohl(tag1);
6881     mp->tag2 = ntohl(tag2);
6882
6883     S; W;
6884     /* NOTREACHED */
6885     return 0;
6886 }
6887
6888 static int api_create_vhost_user_if (vat_main_t * vam)
6889 {
6890     unformat_input_t * i = vam->input;
6891     vl_api_create_vhost_user_if_t *mp;
6892     f64 timeout;
6893     u8 * file_name;
6894     u8 is_server = 0;
6895     u8 file_name_set = 0;
6896     u32 custom_dev_instance = ~0;
6897     u8 hwaddr[6];
6898     u8 use_custom_mac = 0;
6899
6900     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6901       if (unformat (i, "socket %s", &file_name)) {
6902         file_name_set = 1;
6903       }
6904       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
6905         ;
6906       else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr))
6907         use_custom_mac = 1;
6908       else if (unformat (i, "server"))
6909         is_server = 1;
6910       else
6911         break;
6912     }
6913
6914     if (file_name_set == 0) {
6915       errmsg ("missing socket file name\n");
6916       return -99;
6917     }
6918
6919     if (vec_len (file_name) > 255) {
6920       errmsg ("socket file name too long\n");
6921       return -99;
6922     }
6923     vec_add1 (file_name, 0);
6924
6925     M(CREATE_VHOST_USER_IF, create_vhost_user_if);
6926
6927     mp->is_server = is_server;
6928     memcpy(mp->sock_filename, file_name, vec_len(file_name));
6929     vec_free(file_name);
6930     if (custom_dev_instance != ~0) {
6931         mp->renumber = 1;
6932         mp->custom_dev_instance = ntohl(custom_dev_instance);
6933     }
6934     mp->use_custom_mac = use_custom_mac;
6935     memcpy(mp->mac_address, hwaddr, 6);
6936
6937     S; W;
6938     /* NOTREACHED */
6939     return 0;
6940 }
6941
6942 static int api_modify_vhost_user_if (vat_main_t * vam)
6943 {
6944     unformat_input_t * i = vam->input;
6945     vl_api_modify_vhost_user_if_t *mp;
6946     f64 timeout;
6947     u8 * file_name;
6948     u8 is_server = 0;
6949     u8 file_name_set = 0;
6950     u32 custom_dev_instance = ~0;
6951     u8 sw_if_index_set = 0;
6952     u32 sw_if_index = (u32)~0;
6953
6954     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
6955       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
6956           sw_if_index_set = 1;
6957       else if (unformat (i, "sw_if_index %d", &sw_if_index))
6958           sw_if_index_set = 1;
6959       else if (unformat (i, "socket %s", &file_name)) {
6960         file_name_set = 1;
6961       }
6962       else if (unformat (i, "renumber %"PRIu32, &custom_dev_instance))
6963         ;
6964       else if (unformat (i, "server"))
6965         is_server = 1;
6966       else
6967         break;
6968     }
6969
6970     if (sw_if_index_set == 0) {
6971        errmsg ("missing sw_if_index or interface name\n");
6972        return -99;
6973     }
6974
6975     if (file_name_set == 0) {
6976       errmsg ("missing socket file name\n");
6977       return -99;
6978     }
6979
6980     if (vec_len (file_name) > 255) {
6981       errmsg ("socket file name too long\n");
6982       return -99;
6983     }
6984     vec_add1 (file_name, 0);
6985
6986     M(MODIFY_VHOST_USER_IF, modify_vhost_user_if);
6987
6988     mp->sw_if_index = ntohl(sw_if_index);
6989     mp->is_server = is_server;
6990     memcpy(mp->sock_filename, file_name, vec_len(file_name));
6991     vec_free(file_name);
6992     if (custom_dev_instance != ~0) {
6993         mp->renumber = 1;
6994         mp->custom_dev_instance = ntohl(custom_dev_instance);
6995     }
6996
6997     S; W;
6998     /* NOTREACHED */
6999     return 0;
7000 }
7001
7002 static int api_delete_vhost_user_if (vat_main_t * vam)
7003 {
7004     unformat_input_t * i = vam->input;
7005     vl_api_delete_vhost_user_if_t *mp;
7006     f64 timeout;
7007     u32 sw_if_index = ~0;
7008     u8 sw_if_index_set = 0;
7009
7010     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7011       if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7012           sw_if_index_set = 1;
7013       else if (unformat (i, "sw_if_index %d", &sw_if_index))
7014           sw_if_index_set = 1;
7015       else
7016         break;
7017     }
7018
7019     if (sw_if_index_set == 0) {
7020        errmsg ("missing sw_if_index or interface name\n");
7021        return -99;
7022     }
7023
7024
7025     M(DELETE_VHOST_USER_IF, delete_vhost_user_if);
7026
7027     mp->sw_if_index = ntohl(sw_if_index);
7028
7029     S; W;
7030     /* NOTREACHED */
7031     return 0;
7032 }
7033
7034 static void vl_api_sw_interface_vhost_user_details_t_handler
7035 (vl_api_sw_interface_vhost_user_details_t * mp)
7036 {
7037     vat_main_t * vam = &vat_main;
7038
7039     fformat(vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s\n",
7040             (char *)mp->interface_name,
7041             ntohl(mp->sw_if_index), ntohl(mp->virtio_net_hdr_sz),
7042             clib_net_to_host_u64(mp->features), mp->is_server,
7043             ntohl(mp->num_regions), (char *)mp->sock_filename);
7044     fformat(vam->ofp, "    Status: '%s'\n", strerror(ntohl(mp->sock_errno)));
7045 }
7046
7047 static void vl_api_sw_interface_vhost_user_details_t_handler_json
7048 (vl_api_sw_interface_vhost_user_details_t * mp)
7049 {
7050     vat_main_t * vam = &vat_main;
7051     vat_json_node_t *node = NULL;
7052
7053     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7054         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7055         vat_json_init_array(&vam->json_tree);
7056     }
7057     node = vat_json_array_add(&vam->json_tree);
7058
7059     vat_json_init_object(node);
7060     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7061     vat_json_object_add_string_copy(node, "interface_name", mp->interface_name);
7062     vat_json_object_add_uint(node, "virtio_net_hdr_sz", ntohl(mp->virtio_net_hdr_sz));
7063     vat_json_object_add_uint(node, "features", clib_net_to_host_u64(mp->features));
7064     vat_json_object_add_uint(node, "is_server", mp->is_server);
7065     vat_json_object_add_string_copy(node, "sock_filename", mp->sock_filename);
7066     vat_json_object_add_uint(node, "num_regions", ntohl(mp->num_regions));
7067     vat_json_object_add_uint(node, "sock_errno", ntohl(mp->sock_errno));
7068 }
7069
7070 static int api_sw_interface_vhost_user_dump (vat_main_t * vam)
7071 {
7072     vl_api_sw_interface_vhost_user_dump_t *mp;
7073     f64 timeout;
7074     fformat(vam->ofp, "Interface name           idx hdr_sz features server regions filename\n");
7075
7076     /* Get list of vhost-user interfaces */
7077     M(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump);
7078     S;
7079
7080     /* Use a control ping for synchronization */
7081     {
7082         vl_api_control_ping_t * mp;
7083         M(CONTROL_PING, control_ping);
7084         S;
7085     }
7086     W;
7087 }
7088
7089 static int api_show_version (vat_main_t * vam)
7090 {
7091     vl_api_show_version_t *mp;
7092     f64 timeout;
7093
7094     M(SHOW_VERSION, show_version);
7095
7096     S; W;
7097     /* NOTREACHED */
7098     return 0;
7099 }
7100
7101 static uword unformat_nsh_gre_decap_next 
7102 (unformat_input_t * input, va_list * args)
7103 {
7104   u32 * result = va_arg (*args, u32 *);
7105   u32 tmp;
7106   
7107   if (unformat (input, "drop"))
7108     *result = NSH_INPUT_NEXT_DROP;
7109   else if (unformat (input, "ip4"))
7110     *result = NSH_INPUT_NEXT_IP4_INPUT;
7111   else if (unformat (input, "ip6"))
7112     *result = NSH_INPUT_NEXT_IP6_INPUT;
7113   else if (unformat (input, "ethernet"))
7114     *result = NSH_INPUT_NEXT_ETHERNET_INPUT;
7115   else if (unformat (input, "%d", &tmp))
7116     *result = tmp;
7117   else
7118     return 0;
7119   return 1;
7120 }
7121
7122 static int api_nsh_gre_add_del_tunnel (vat_main_t * vam)
7123 {
7124     unformat_input_t * line_input = vam->input;
7125     vl_api_nsh_gre_add_del_tunnel_t *mp;
7126     f64 timeout;
7127     ip4_address_t src, dst;
7128     u8 is_add = 1;
7129     u8 src_set = 0;
7130     u8 dst_set = 0;
7131     u32 encap_vrf_id = 0;
7132     u32 decap_vrf_id = 0;
7133     u8 ver_o_c = 0;
7134     u8 md_type = 0;
7135     u8 next_protocol = 1; /* ip4 */
7136     u32 spi;
7137     u8 spi_set = 0;
7138     u32 si;
7139     u8 si_set = 0;
7140     u32 spi_si;
7141     u32 c1 = 0;
7142     u32 c2 = 0;
7143     u32 c3 = 0;
7144     u32 c4 = 0;
7145     u32 *tlvs = 0;
7146     u32 decap_next_index = NSH_INPUT_NEXT_IP4_INPUT;
7147     u32 tmp;
7148     int i;
7149
7150     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7151         if (unformat (line_input, "del"))
7152             is_add = 0;
7153         else if (unformat (line_input, "src %U", 
7154                            unformat_ip4_address, &src))
7155             src_set = 1;
7156         else if (unformat (line_input, "dst %U",
7157                            unformat_ip4_address, &dst))
7158             dst_set = 1;
7159         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7160             ;
7161         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7162             ;
7163         else if (unformat (line_input, "decap-next %U", 
7164                            unformat_nsh_gre_decap_next, &decap_next_index))
7165             ;
7166         else if (unformat (line_input, "version %d", &tmp))
7167             ver_o_c |= (tmp & 3) << 6;
7168         else if (unformat (line_input, "o-bit %d", &tmp))
7169             ver_o_c |= (tmp & 1) << 5;
7170         else if (unformat (line_input, "c-bit %d", &tmp))
7171             ver_o_c |= (tmp & 1) << 4;
7172         else if (unformat (line_input, "md-type %d", &tmp))
7173             md_type = tmp;
7174         else if (unformat(line_input, "next-ip4"))
7175             next_protocol = 1;
7176         else if (unformat(line_input, "next-ip6"))
7177             next_protocol = 2;
7178         else if (unformat(line_input, "next-ethernet"))
7179             next_protocol = 3;
7180         else if (unformat (line_input, "c1 %d", &c1))
7181             ;
7182         else if (unformat (line_input, "c2 %d", &c2))
7183             ;
7184         else if (unformat (line_input, "c3 %d", &c3))
7185             ;
7186         else if (unformat (line_input, "c4 %d", &c4))
7187             ;
7188         else if (unformat (line_input, "spi %d", &spi))
7189             spi_set = 1;
7190         else if (unformat (line_input, "si %d", &si))
7191             si_set = 1;
7192         else if (unformat (line_input, "tlv %x"))
7193             vec_add1 (tlvs, tmp);
7194         else {
7195             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7196             return -99;
7197         }
7198     }
7199
7200     if (src_set == 0) {
7201         errmsg ("tunnel src address not specified\n");
7202         return -99;
7203     }
7204     if (dst_set == 0) {
7205         errmsg ("tunnel dst address not specified\n");
7206         return -99;
7207     }
7208
7209     if (spi_set == 0) {
7210         errmsg ("spi not specified\n");
7211         return -99;
7212     }
7213
7214     if (si_set == 0) {
7215         errmsg ("si not specified\n");
7216         return -99;
7217     }
7218
7219     M2 (NSH_GRE_ADD_DEL_TUNNEL, nsh_gre_add_del_tunnel,
7220         sizeof(u32) * vec_len (tlvs));
7221     
7222     spi_si = (spi<<8) | si;
7223
7224     mp->src = src.as_u32;
7225     mp->dst = dst.as_u32;
7226     mp->encap_vrf_id = ntohl(encap_vrf_id);
7227     mp->decap_vrf_id = ntohl(decap_vrf_id);
7228     mp->decap_next_index = ntohl(decap_next_index);
7229     mp->tlv_len_in_words = vec_len (tlvs);
7230     mp->is_add = is_add;
7231     mp->ver_o_c = ver_o_c;
7232     mp->length = 6 + vec_len(tlvs);
7233     mp->md_type = md_type;
7234     mp->next_protocol = next_protocol;
7235     mp->spi_si = ntohl(spi_si);
7236     mp->c1 = ntohl(c1);
7237     mp->c2 = ntohl(c2);
7238     mp->c3 = ntohl(c3);
7239     mp->c4 = ntohl(c4);
7240     
7241     for (i = 0; i < vec_len(tlvs); i++)
7242         mp->tlvs[i] = ntohl(tlvs[i]);
7243
7244     vec_free (tlvs);
7245
7246     S; W;
7247     /* NOTREACHED */
7248     return 0;
7249 }
7250
7251 static uword unformat_nsh_vxlan_gpe_decap_next 
7252 (unformat_input_t * input, va_list * args)
7253 {
7254   u32 * result = va_arg (*args, u32 *);
7255   u32 tmp;
7256   
7257   if (unformat (input, "drop"))
7258     *result = NSH_VXLAN_GPE_INPUT_NEXT_DROP;
7259   else if (unformat (input, "ip4"))
7260     *result = NSH_VXLAN_GPE_INPUT_NEXT_IP4_INPUT;
7261   else if (unformat (input, "ip6"))
7262     *result = NSH_VXLAN_GPE_INPUT_NEXT_IP6_INPUT;
7263   else if (unformat (input, "ethernet"))
7264     *result = NSH_VXLAN_GPE_INPUT_NEXT_ETHERNET_INPUT;
7265   else if (unformat (input, "nsh-vxlan-gpe"))
7266       *result = NSH_VXLAN_GPE_INPUT_NEXT_ETHERNET_INPUT;
7267   else if (unformat (input, "%d", &tmp))
7268     *result = tmp;
7269   else
7270     return 0;
7271   return 1;
7272 }
7273
7274 static int api_nsh_vxlan_gpe_add_del_tunnel (vat_main_t * vam)
7275 {
7276     unformat_input_t * line_input = vam->input;
7277     vl_api_nsh_vxlan_gpe_add_del_tunnel_t *mp;
7278     f64 timeout;
7279     ip4_address_t src, dst;
7280     u8 is_add = 1;
7281     u8 src_set = 0;
7282     u8 dst_set = 0;
7283     u32 encap_vrf_id = 0;
7284     u32 decap_vrf_id = 0;
7285     u8 ver_o_c = 0;
7286     u8 md_type = 0;
7287     u8 next_protocol = 1; /* ip4 */
7288     u32 spi;
7289     u8 spi_set = 0;
7290     u32 si;
7291     u8 si_set = 0;
7292     u32 spi_si;
7293     u32 c1 = 0;
7294     u32 c2 = 0;
7295     u32 c3 = 0;
7296     u32 c4 = 0;
7297     u32 *tlvs = 0;
7298     u32 decap_next_index = NSH_INPUT_NEXT_IP4_INPUT;
7299     u32 vni;
7300     u8 vni_set = 0;
7301     u32 tmp;
7302     int i;
7303
7304     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7305         if (unformat (line_input, "del"))
7306             is_add = 0;
7307         else if (unformat (line_input, "src %U", 
7308                            unformat_ip4_address, &src))
7309             src_set = 1;
7310         else if (unformat (line_input, "dst %U",
7311                            unformat_ip4_address, &dst))
7312             dst_set = 1;
7313         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7314             ;
7315         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7316             ;
7317         else if (unformat (line_input, "decap-next %U", 
7318                            unformat_nsh_vxlan_gpe_decap_next, 
7319                            &decap_next_index))
7320             ;
7321         else if (unformat (line_input, "vni %d", &vni))
7322             vni_set = 1;
7323         else if (unformat (line_input, "version %d", &tmp))
7324             ver_o_c |= (tmp & 3) << 6;
7325         else if (unformat (line_input, "o-bit %d", &tmp))
7326             ver_o_c |= (tmp & 1) << 5;
7327         else if (unformat (line_input, "c-bit %d", &tmp))
7328             ver_o_c |= (tmp & 1) << 4;
7329         else if (unformat (line_input, "md-type %d", &tmp))
7330             md_type = tmp;
7331         else if (unformat(line_input, "next-ip4"))
7332             next_protocol = 1;
7333         else if (unformat(line_input, "next-ip6"))
7334             next_protocol = 2;
7335         else if (unformat(line_input, "next-ethernet"))
7336             next_protocol = 3;
7337         else if (unformat (line_input, "c1 %d", &c1))
7338             ;
7339         else if (unformat (line_input, "c2 %d", &c2))
7340             ;
7341         else if (unformat (line_input, "c3 %d", &c3))
7342             ;
7343         else if (unformat (line_input, "c4 %d", &c4))
7344             ;
7345         else if (unformat (line_input, "spi %d", &spi))
7346             spi_set = 1;
7347         else if (unformat (line_input, "si %d", &si))
7348             si_set = 1;
7349         else if (unformat (line_input, "tlv %x"))
7350             vec_add1 (tlvs, tmp);
7351         else {
7352             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7353             return -99;
7354         }
7355     }
7356
7357     if (src_set == 0) {
7358         errmsg ("tunnel src address not specified\n");
7359         return -99;
7360     }
7361     if (dst_set == 0) {
7362         errmsg ("tunnel dst address not specified\n");
7363         return -99;
7364     }
7365
7366     if (spi_set == 0) {
7367         errmsg ("spi not specified\n");
7368         return -99;
7369     }
7370
7371     if (si_set == 0) {
7372         errmsg ("si not specified\n");
7373         return -99;
7374     }
7375     if (vni_set == 0) {
7376         errmsg ("vni not specified\n");
7377         return -99;
7378     }
7379
7380     M2 (NSH_VXLAN_GPE_ADD_DEL_TUNNEL, nsh_vxlan_gpe_add_del_tunnel,
7381         sizeof(u32) * vec_len (tlvs));
7382     
7383     spi_si = (spi<<8) | si;
7384
7385     mp->src = src.as_u32;
7386     mp->dst = dst.as_u32;
7387     mp->encap_vrf_id = ntohl(encap_vrf_id);
7388     mp->decap_vrf_id = ntohl(decap_vrf_id);
7389     mp->decap_next_index = ntohl(decap_next_index);
7390     mp->tlv_len_in_words = vec_len (tlvs);
7391     mp->vni = ntohl(vni);
7392     mp->is_add = is_add;
7393     mp->ver_o_c = ver_o_c;
7394     mp->length = 6 + vec_len(tlvs);
7395     mp->md_type = md_type;
7396     mp->next_protocol = next_protocol;
7397     mp->spi_si = ntohl(spi_si);
7398     mp->c1 = ntohl(c1);
7399     mp->c2 = ntohl(c2);
7400     mp->c3 = ntohl(c3);
7401     mp->c4 = ntohl(c4);
7402     
7403     for (i = 0; i < vec_len(tlvs); i++)
7404         mp->tlvs[i] = ntohl(tlvs[i]);
7405
7406     vec_free (tlvs);
7407
7408     S; W;
7409     /* NOTREACHED */
7410     return 0;
7411 }
7412
7413 static uword unformat_lisp_gpe_decap_next (unformat_input_t * input, 
7414                                                va_list * args)
7415 {
7416     u32 * result = va_arg (*args, u32 *);
7417     u32 tmp;
7418   
7419     if (unformat (input, "drop"))
7420         *result = LISP_GPE_INPUT_NEXT_DROP;
7421     else if (unformat (input, "ip4"))
7422         *result = LISP_GPE_INPUT_NEXT_IP4_INPUT;
7423     else if (unformat (input, "ip6"))
7424         *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
7425     else if (unformat (input, "ethernet"))
7426         *result = LISP_GPE_INPUT_NEXT_IP6_INPUT;
7427     else if (unformat (input, "lisp-gpe"))
7428         *result = LISP_GPE_INPUT_NEXT_LISP_GPE_ENCAP;
7429     else if (unformat (input, "%d", &tmp))
7430         *result = tmp;
7431     else
7432         return 0;
7433     return 1;
7434 }
7435
7436 static int
7437 api_lisp_gpe_add_del_tunnel (vat_main_t * vam)
7438 {
7439     unformat_input_t * line_input = vam->input;
7440     vl_api_lisp_gpe_add_del_tunnel_t *mp;
7441     f64 timeout;
7442     ip4_address_t src, dst;
7443     u8 is_add = 1;
7444     u8 src_set = 0;
7445     u8 dst_set = 0;
7446     u32 encap_vrf_id = 0;
7447     u32 decap_vrf_id = 0;
7448     u8 next_protocol = LISP_GPE_NEXT_PROTOCOL_IP4;
7449     u32 decap_next_index = LISP_GPE_INPUT_NEXT_IP4_INPUT;
7450     u8 flags = LISP_GPE_FLAGS_P;
7451     u8 ver_res = 0;
7452     u8 res = 0;
7453     u32 iid = 0;
7454     u8 iid_set = 0;
7455     u32 tmp;
7456   
7457     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7458         if (unformat (line_input, "del"))
7459             is_add = 0;
7460         else if (unformat (line_input, "src %U", 
7461                            unformat_ip4_address, &src))
7462             src_set = 1;
7463         else if (unformat (line_input, "dst %U",
7464                            unformat_ip4_address, &dst))
7465             dst_set = 1;
7466         else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id))
7467             ;
7468         else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id))
7469             ;
7470         else if (unformat (line_input, "decap-next %U", 
7471                            unformat_lisp_gpe_decap_next, 
7472                            &decap_next_index))
7473             ;
7474         else if (unformat(line_input, "next-ip4"))
7475             next_protocol = 1;
7476         else if (unformat(line_input, "next-ip6"))
7477             next_protocol = 2;
7478         else if (unformat(line_input, "next-ethernet"))
7479             next_protocol = 3;
7480         else if (unformat(line_input, "next-nsh"))
7481             next_protocol = 4;
7482         /* Allow the user to specify anything they want in the LISP hdr */
7483         else if (unformat (line_input, "ver_res %x", &tmp))
7484             ver_res = tmp;
7485         else if (unformat (line_input, "res %x", &tmp))
7486             res = tmp;
7487         else if (unformat (line_input, "flags %x", &tmp))
7488             flags = tmp;
7489         else if (unformat (line_input, "n-bit"))
7490             flags |= LISP_GPE_FLAGS_N;
7491         else if (unformat (line_input, "l-bit"))
7492             flags |= LISP_GPE_FLAGS_L;
7493         else if (unformat (line_input, "e-bit"))
7494             flags |= LISP_GPE_FLAGS_E;
7495         else if (unformat (line_input, "v-bit"))
7496             flags |= LISP_GPE_FLAGS_V;
7497         else if (unformat (line_input, "i-bit"))
7498             flags |= LISP_GPE_FLAGS_V;
7499         else if (unformat (line_input, "not-p-bit"))
7500             flags &= !LISP_GPE_FLAGS_P;
7501         else if (unformat (line_input, "p-bit"))
7502             flags |= LISP_GPE_FLAGS_P;
7503         else if (unformat (line_input, "o-bit"))
7504             flags |= LISP_GPE_FLAGS_O;
7505         else if (unformat (line_input, "iidx %x", &iid))
7506             iid_set = 1;
7507         else if (unformat (line_input, "iid %d", &iid))
7508             iid_set = 1;
7509         else {
7510             errmsg ("parse error '%U'\n", format_unformat_error, line_input);
7511             return -99;
7512         }
7513     }
7514
7515     if (src_set == 0) {
7516         errmsg ("tunnel src address not specified\n");
7517         return -99;
7518     }
7519     if (dst_set == 0) {
7520         errmsg ("tunnel dst address not specified\n");
7521         return -99;
7522     }
7523     if (iid_set == 0) {
7524         errmsg ("iid not specified\n");
7525         return -99;
7526     }
7527
7528     M(LISP_GPE_ADD_DEL_TUNNEL, lisp_gpe_add_del_tunnel);
7529
7530     mp->src = src.as_u32;
7531     mp->dst = dst.as_u32;
7532     mp->encap_vrf_id = ntohl(encap_vrf_id);
7533     mp->decap_vrf_id = ntohl(decap_vrf_id);
7534     mp->decap_next_index = ntohl(decap_next_index);
7535     mp->is_add = is_add;
7536     mp->flags = flags;
7537     mp->ver_res = ver_res;
7538     mp->res = res;
7539     mp->next_protocol = next_protocol;
7540     mp->iid = ntohl(iid);
7541
7542     S; W; 
7543
7544     /* NOTREACHED */
7545     return 0;
7546 }
7547
7548
7549 u8 * format_l2_fib_mac_address (u8 * s, va_list * args)
7550 {
7551   u8 * a = va_arg (*args, u8 *);
7552
7553   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
7554                  a[2], a[3], a[4], a[5], a[6], a[7]);
7555 }
7556
7557 static void vl_api_l2_fib_table_entry_t_handler
7558 (vl_api_l2_fib_table_entry_t * mp)
7559 {
7560     vat_main_t * vam = &vat_main;
7561
7562     fformat(vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32
7563             "       %d       %d     %d\n",
7564             ntohl(mp->bd_id), format_l2_fib_mac_address, &mp->mac,
7565             ntohl(mp->sw_if_index), mp->static_mac, mp->filter_mac,
7566             mp->bvi_mac);
7567 }
7568
7569 static void vl_api_l2_fib_table_entry_t_handler_json
7570 (vl_api_l2_fib_table_entry_t * mp)
7571 {
7572     vat_main_t * vam = &vat_main;
7573     vat_json_node_t *node = NULL;
7574
7575     if (VAT_JSON_ARRAY != vam->json_tree.type) {
7576         ASSERT(VAT_JSON_NONE == vam->json_tree.type);
7577         vat_json_init_array(&vam->json_tree);
7578     }
7579     node = vat_json_array_add(&vam->json_tree);
7580
7581     vat_json_init_object(node);
7582     vat_json_object_add_uint(node, "bd_id", ntohl(mp->bd_id));
7583     vat_json_object_add_uint(node, "mac", clib_net_to_host_u64(mp->mac));
7584     vat_json_object_add_uint(node, "sw_if_index", ntohl(mp->sw_if_index));
7585     vat_json_object_add_uint(node, "static_mac", mp->static_mac);
7586     vat_json_object_add_uint(node, "filter_mac", mp->filter_mac);
7587     vat_json_object_add_uint(node, "bvi_mac", mp->bvi_mac);
7588 }
7589
7590 static int api_l2_fib_table_dump (vat_main_t * vam)
7591 {
7592     unformat_input_t * i = vam->input;
7593     vl_api_l2_fib_table_dump_t *mp;
7594     f64 timeout;
7595     u32 bd_id;
7596     u8 bd_id_set = 0;
7597
7598     /* Parse args required to build the message */
7599     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7600         if (unformat (i, "bd_id %d", &bd_id))
7601             bd_id_set = 1;
7602         else
7603             break;
7604     }
7605
7606     if (bd_id_set == 0) {
7607         errmsg ("missing bridge domain\n");
7608         return -99;
7609     }
7610
7611     fformat(vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI\n");
7612
7613     /* Get list of l2 fib entries */
7614     M(L2_FIB_TABLE_DUMP, l2_fib_table_dump);
7615
7616     mp->bd_id = ntohl(bd_id);
7617     S;
7618
7619     /* Use a control ping for synchronization */
7620     {
7621         vl_api_control_ping_t * mp;
7622         M(CONTROL_PING, control_ping);
7623         S;
7624     }
7625     W;
7626 }
7627
7628
7629 static int
7630 api_interface_name_renumber (vat_main_t * vam)
7631 {
7632     unformat_input_t * line_input = vam->input;
7633     vl_api_interface_name_renumber_t *mp;
7634     u32 sw_if_index = ~0;
7635     f64 timeout;
7636     u32 new_show_dev_instance = ~0;
7637
7638     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7639         if (unformat (line_input, "%U", unformat_sw_if_index, vam, 
7640                       &sw_if_index))
7641             ;
7642         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
7643             ;
7644         else if (unformat (line_input, "new_show_dev_instance %d", 
7645                            &new_show_dev_instance))
7646             ;
7647         else
7648             break;
7649     }
7650
7651     if (sw_if_index == ~0) {
7652         errmsg ("missing interface name or sw_if_index\n");
7653         return -99;
7654     }
7655
7656     if (new_show_dev_instance == ~0) {
7657         errmsg ("missing new_show_dev_instance\n");
7658         return -99;
7659     }
7660
7661     M(INTERFACE_NAME_RENUMBER, interface_name_renumber);
7662
7663     mp->sw_if_index = ntohl (sw_if_index);
7664     mp->new_show_dev_instance = ntohl (new_show_dev_instance);
7665
7666     S; W;
7667 }
7668
7669 static int
7670 api_want_ip4_arp_events (vat_main_t * vam)
7671 {
7672     unformat_input_t * line_input = vam->input;
7673     vl_api_want_ip4_arp_events_t * mp;
7674     f64 timeout;
7675     ip4_address_t address;
7676     int address_set = 0;
7677     u32 enable_disable = 1;
7678
7679     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
7680         if (unformat (line_input, "address %U", 
7681                       unformat_ip4_address, &address))
7682             address_set = 1;
7683         else if (unformat (line_input, "del"))
7684             enable_disable = 0;
7685         else
7686             break;
7687     }
7688     
7689     if (address_set == 0) {
7690         errmsg ("missing addresses\n");
7691         return -99;
7692     }
7693         
7694     M(WANT_IP4_ARP_EVENTS, want_ip4_arp_events);
7695     mp->enable_disable = enable_disable;
7696     mp->pid = getpid();
7697     mp->address = address.as_u32;
7698
7699     S; W; 
7700 }
7701
7702 static int api_input_acl_set_interface (vat_main_t * vam)
7703 {
7704     unformat_input_t * i = vam->input;
7705     vl_api_input_acl_set_interface_t *mp;
7706     f64 timeout;
7707     u32 sw_if_index;
7708     int sw_if_index_set;
7709     u32 ip4_table_index = ~0;
7710     u32 ip6_table_index = ~0;
7711     u32 l2_table_index = ~0;
7712     u8 is_add = 1;
7713
7714     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7715         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7716             sw_if_index_set = 1;
7717         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7718             sw_if_index_set = 1;
7719         else if (unformat (i, "del"))
7720             is_add = 0;
7721         else if (unformat (i, "ip4-table %d", &ip4_table_index))
7722             ;
7723         else if (unformat (i, "ip6-table %d", &ip6_table_index))
7724             ;
7725         else if (unformat (i, "l2-table %d", &l2_table_index))
7726             ;
7727         else {
7728             clib_warning ("parse error '%U'", format_unformat_error, i);
7729             return -99;
7730         }
7731     }
7732
7733     if (sw_if_index_set == 0) {
7734         errmsg ("missing interface name or sw_if_index\n");
7735         return -99;
7736     }
7737
7738     M(INPUT_ACL_SET_INTERFACE, input_acl_set_interface);
7739
7740     mp->sw_if_index = ntohl(sw_if_index);
7741     mp->ip4_table_index = ntohl(ip4_table_index);
7742     mp->ip6_table_index = ntohl(ip6_table_index);
7743     mp->l2_table_index = ntohl(l2_table_index);
7744     mp->is_add = is_add;
7745
7746     S; W;
7747     /* NOTREACHED */
7748     return 0;
7749 }
7750
7751 static int
7752 api_ip_address_dump (vat_main_t * vam)
7753 {
7754     unformat_input_t * i = vam->input;
7755     vl_api_ip_address_dump_t * mp;
7756     u32 sw_if_index = ~0;
7757     u8 sw_if_index_set = 0;
7758     u8 ipv4_set = 0;
7759     u8 ipv6_set = 0;
7760     f64 timeout;
7761
7762     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7763         if (unformat (i, "sw_if_index %d", &sw_if_index))
7764             sw_if_index_set = 1;
7765         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7766             sw_if_index_set = 1;
7767         else if (unformat (i, "ipv4"))
7768             ipv4_set = 1;
7769         else if (unformat (i, "ipv6"))
7770             ipv6_set = 1;
7771         else
7772             break;
7773     }
7774
7775     if (ipv4_set && ipv6_set) {
7776         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
7777         return -99;
7778     }
7779
7780     if ((!ipv4_set) && (!ipv6_set)) {
7781         errmsg ("no ipv4 nor ipv6 flag set\n");
7782         return -99;
7783     }
7784
7785     if (sw_if_index_set == 0) {
7786         errmsg ("missing interface name or sw_if_index\n");
7787         return -99;
7788     }
7789
7790     vam->current_sw_if_index = sw_if_index;
7791     vam->is_ipv6 = ipv6_set;
7792
7793     M(IP_ADDRESS_DUMP, ip_address_dump);
7794     mp->sw_if_index = ntohl(sw_if_index);
7795     mp->is_ipv6 = ipv6_set;
7796     S;
7797
7798     /* Use a control ping for synchronization */
7799     {
7800         vl_api_control_ping_t * mp;
7801         M(CONTROL_PING, control_ping);
7802         S;
7803     }
7804     W;
7805 }
7806
7807 static int
7808 api_ip_dump (vat_main_t * vam)
7809 {
7810     vl_api_ip_dump_t * mp;
7811     unformat_input_t * in = vam->input;
7812     int ipv4_set = 0;
7813     int ipv6_set = 0;
7814     int is_ipv6;
7815     f64 timeout;
7816     int i;
7817
7818     while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT) {
7819         if (unformat (in, "ipv4"))
7820             ipv4_set = 1;
7821         else if (unformat (in, "ipv6"))
7822             ipv6_set = 1;
7823         else
7824             break;
7825     }
7826
7827     if (ipv4_set && ipv6_set) {
7828         errmsg ("ipv4 and ipv6 flags cannot be both set\n");
7829         return -99;
7830     }
7831
7832     if ((!ipv4_set) && (!ipv6_set)) {
7833         errmsg ("no ipv4 nor ipv6 flag set\n");
7834         return -99;
7835     }
7836
7837     is_ipv6 = ipv6_set;
7838     vam->is_ipv6 = is_ipv6;
7839
7840     /* free old data */
7841     for (i = 0; i < vec_len(vam->ip_details_by_sw_if_index[is_ipv6]); i++) {
7842         vec_free(vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
7843     }
7844     vec_free(vam->ip_details_by_sw_if_index[is_ipv6]);
7845
7846     M(IP_DUMP, ip_dump);
7847     mp->is_ipv6 = ipv6_set;
7848     S;
7849
7850     /* Use a control ping for synchronization */
7851     {
7852         vl_api_control_ping_t * mp;
7853         M(CONTROL_PING, control_ping);
7854         S;
7855     }
7856     W;
7857 }
7858
7859 static int
7860 api_ipsec_spd_add_del (vat_main_t * vam)
7861 {
7862 #if DPDK > 0
7863     unformat_input_t * i = vam->input;
7864     vl_api_ipsec_spd_add_del_t *mp;
7865     f64 timeout;
7866     u32 spd_id = ~0;
7867     u8 is_add = 1;
7868
7869     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7870         if (unformat (i, "spd_id %d", &spd_id))
7871             ;
7872         else if (unformat (i, "del"))
7873             is_add = 0;
7874         else {
7875             clib_warning ("parse error '%U'", format_unformat_error, i);
7876             return -99;
7877         }
7878     }
7879     if (spd_id == ~0) {
7880         errmsg ("spd_id must be set\n");
7881         return -99;
7882     }
7883
7884     M(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del);
7885
7886     mp->spd_id = ntohl(spd_id);
7887     mp->is_add = is_add;
7888
7889     S; W;
7890     /* NOTREACHED */
7891     return 0;
7892 #else
7893     clib_warning ("unsupported (no dpdk)");
7894     return -99;
7895 #endif
7896 }
7897
7898 static int
7899 api_ipsec_interface_add_del_spd (vat_main_t * vam)
7900 {
7901 #if DPDK > 0
7902     unformat_input_t * i = vam->input;
7903     vl_api_ipsec_interface_add_del_spd_t *mp;
7904     f64 timeout;
7905     u32 sw_if_index;
7906     u8 sw_if_index_set = 0;
7907     u32 spd_id = (u32) ~0;
7908     u8 is_add = 1;
7909
7910     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7911         if (unformat (i, "del"))
7912             is_add = 0;
7913         else if (unformat (i, "spd_id %d", &spd_id))
7914             ;
7915         else if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
7916             sw_if_index_set = 1;
7917         else if (unformat (i, "sw_if_index %d", &sw_if_index))
7918             sw_if_index_set = 1;
7919         else {
7920             clib_warning ("parse error '%U'", format_unformat_error, i);
7921             return -99;
7922         }
7923
7924     }
7925
7926     if (spd_id == (u32) ~0) {
7927         errmsg ("spd_id must be set\n");
7928         return -99;
7929     }
7930
7931     if (sw_if_index_set == 0) {
7932         errmsg ("missing interface name or sw_if_index\n");
7933         return -99;
7934     }
7935
7936     M(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd);
7937
7938     mp->spd_id = ntohl(spd_id);
7939     mp->sw_if_index = ntohl (sw_if_index);
7940     mp->is_add = is_add;
7941
7942     S; W;
7943     /* NOTREACHED */
7944     return 0;
7945 #else
7946     clib_warning ("unsupported (no dpdk)");
7947     return -99;
7948 #endif
7949 }
7950
7951 static int
7952 api_ipsec_spd_add_del_entry (vat_main_t * vam)
7953 {
7954 #if DPDK > 0
7955     unformat_input_t * i = vam->input;
7956     vl_api_ipsec_spd_add_del_entry_t *mp;
7957     f64 timeout;
7958     u8 is_add = 1, is_outbound = 0, is_ipv6 = 0, is_ip_any = 1;
7959     u32 spd_id, sa_id, protocol = 0, policy = 0;
7960     i32 priority;
7961     u32 rport_start = 0, rport_stop = (u32) ~0;
7962     u32 lport_start = 0, lport_stop = (u32) ~0;
7963     ip4_address_t laddr4_start, laddr4_stop, raddr4_start, raddr4_stop;
7964     ip6_address_t laddr6_start, laddr6_stop, raddr6_start, raddr6_stop;
7965
7966     laddr4_start.as_u32 = raddr4_start.as_u32 = 0;
7967     laddr4_stop.as_u32 = raddr4_stop.as_u32 = (u32) ~0;
7968     laddr6_start.as_u64[0] = raddr6_start.as_u64[0] = 0;
7969     laddr6_start.as_u64[1] = raddr6_start.as_u64[1] = 0;
7970     laddr6_stop.as_u64[0] = raddr6_stop.as_u64[0] = (u64) ~0;
7971     laddr6_stop.as_u64[1] = raddr6_stop.as_u64[1] = (u64) ~0;
7972
7973     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
7974         if (unformat (i, "del"))
7975             is_add = 0;
7976         if (unformat (i, "outbound"))
7977             is_outbound = 1;
7978         if (unformat (i, "inbound"))
7979             is_outbound = 0;
7980         else if (unformat (i, "spd_id %d", &spd_id))
7981             ;
7982         else if (unformat (i, "sa_id %d", &sa_id))
7983             ;
7984         else if (unformat (i, "priority %d", &priority))
7985             ;
7986         else if (unformat (i, "protocol %d", &protocol))
7987             ;
7988         else if (unformat (i, "lport_start %d", &lport_start))
7989             ;
7990         else if (unformat (i, "lport_stop %d", &lport_stop))
7991             ;
7992         else if (unformat (i, "rport_start %d", &rport_start))
7993             ;
7994         else if (unformat (i, "rport_stop %d", &rport_stop))
7995             ;
7996         else if (unformat (i, "laddr_start %U", unformat_ip4_address, &laddr4_start))
7997           {
7998             is_ipv6 = 0;
7999             is_ip_any =0;
8000           }
8001         else if (unformat (i, "laddr_stop %U", unformat_ip4_address, &laddr4_stop))
8002           {
8003             is_ipv6 = 0;
8004             is_ip_any = 0;
8005           }
8006         else if (unformat (i, "raddr_start %U", unformat_ip4_address, &raddr4_start))
8007           {
8008             is_ipv6 = 0;
8009             is_ip_any = 0;
8010           }
8011         else if (unformat (i, "raddr_stop %U", unformat_ip4_address, &raddr4_stop))
8012           {
8013             is_ipv6 = 0;
8014             is_ip_any = 0;
8015           }
8016         else if (unformat (i, "laddr_start %U", unformat_ip6_address, &laddr6_start))
8017           {
8018             is_ipv6 = 1;
8019             is_ip_any = 0;
8020           }
8021         else if (unformat (i, "laddr_stop %U", unformat_ip6_address, &laddr6_stop))
8022           {
8023             is_ipv6 = 1;
8024             is_ip_any = 0;
8025           }
8026         else if (unformat (i, "raddr_start %U", unformat_ip6_address, &raddr6_start))
8027           {
8028             is_ipv6 = 1;
8029             is_ip_any = 0;
8030           }
8031         else if (unformat (i, "raddr_stop %U", unformat_ip6_address, &raddr6_stop))
8032           {
8033             is_ipv6 = 1;
8034             is_ip_any = 0;
8035           }
8036         else if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
8037           {
8038             if (policy == IPSEC_POLICY_ACTION_RESOLVE) {
8039                 clib_warning ("unsupported action: 'resolve'");
8040                 return -99;
8041             }
8042           }
8043         else {
8044             clib_warning ("parse error '%U'", format_unformat_error, i);
8045             return -99;
8046         }
8047
8048     }
8049
8050     M(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry);
8051
8052     mp->spd_id = ntohl(spd_id);
8053     mp->priority = ntohl(priority);
8054     mp->is_outbound = is_outbound;
8055
8056     mp->is_ipv6 = is_ipv6;
8057     if (is_ipv6 || is_ip_any) {
8058         memcpy (mp->remote_address_start, &raddr6_start, sizeof(ip6_address_t));
8059         memcpy (mp->remote_address_stop, &raddr6_stop, sizeof(ip6_address_t));
8060         memcpy (mp->local_address_start, &laddr6_start, sizeof(ip6_address_t));
8061         memcpy (mp->local_address_stop, &laddr6_stop, sizeof(ip6_address_t));
8062     } else {
8063         memcpy (mp->remote_address_start, &raddr4_start, sizeof(ip4_address_t));
8064         memcpy (mp->remote_address_stop, &raddr4_stop, sizeof(ip4_address_t));
8065         memcpy (mp->local_address_start, &laddr4_start, sizeof(ip4_address_t));
8066         memcpy (mp->local_address_stop, &laddr4_stop, sizeof(ip4_address_t));
8067     }
8068     mp->protocol = (u8) protocol;
8069     mp->local_port_start = ntohs((u16) lport_start);
8070     mp->local_port_stop = ntohs((u16) lport_stop);
8071     mp->remote_port_start = ntohs((u16) rport_start);
8072     mp->remote_port_stop = ntohs((u16) rport_stop);
8073     mp->policy = (u8) policy;
8074     mp->sa_id = ntohl(sa_id);
8075     mp->is_add = is_add;
8076     mp->is_ip_any = is_ip_any;
8077     S; W;
8078     /* NOTREACHED */
8079     return 0;
8080 #else
8081     clib_warning ("unsupported (no dpdk)");
8082     return -99;
8083 #endif
8084 }
8085
8086 static int
8087 api_ipsec_sad_add_del_entry (vat_main_t * vam)
8088 {
8089 #if DPDK > 0
8090     unformat_input_t * i = vam->input;
8091     vl_api_ipsec_sad_add_del_entry_t *mp;
8092     f64 timeout;
8093     u32 sad_id, spi;
8094     u8 * ck, * ik;
8095     u8 is_add = 1;
8096
8097     u8 protocol = IPSEC_PROTOCOL_AH;
8098     u8 is_tunnel = 0, is_tunnel_ipv6 = 0;
8099     u32 crypto_alg = 0, integ_alg = 0;
8100     ip4_address_t tun_src4;
8101     ip4_address_t tun_dst4;
8102     ip6_address_t tun_src6;
8103     ip6_address_t tun_dst6;
8104
8105     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8106         if (unformat (i, "del"))
8107             is_add = 0;
8108         else if (unformat (i, "sad_id %d", &sad_id))
8109             ;
8110         else if (unformat (i, "spi %d", &spi))
8111             ;
8112         else if (unformat (i, "esp"))
8113             protocol = IPSEC_PROTOCOL_ESP;
8114         else if (unformat (i, "tunnel_src %U", unformat_ip4_address, &tun_src4)) {
8115             is_tunnel = 1;
8116             is_tunnel_ipv6 = 0;
8117         }
8118         else if (unformat (i, "tunnel_dst %U", unformat_ip4_address, &tun_dst4)) {
8119             is_tunnel = 1;
8120             is_tunnel_ipv6 = 0;
8121         }
8122         else if (unformat (i, "tunnel_src %U", unformat_ip6_address, &tun_src6)) {
8123             is_tunnel = 1;
8124             is_tunnel_ipv6 = 1;
8125         }
8126         else if (unformat (i, "tunnel_dst %U", unformat_ip6_address, &tun_dst6)) {
8127             is_tunnel = 1;
8128             is_tunnel_ipv6 = 1;
8129         }
8130         else if (unformat (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg)) {
8131             if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
8132                 crypto_alg > IPSEC_INTEG_ALG_SHA_512_256) {
8133                 clib_warning ("unsupported crypto-alg: '%U'",
8134                               format_ipsec_crypto_alg, crypto_alg);
8135                 return -99;
8136             }
8137         }
8138         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8139             ;
8140         else if (unformat (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) {
8141             if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
8142                 integ_alg > IPSEC_INTEG_ALG_SHA_512_256) {
8143                 clib_warning ("unsupported integ-alg: '%U'",
8144                               format_ipsec_integ_alg, integ_alg);
8145                 return -99;
8146             }
8147         }
8148         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8149             ;
8150         else {
8151             clib_warning ("parse error '%U'", format_unformat_error, i);
8152             return -99;
8153         }
8154
8155     }
8156
8157     M(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry);
8158
8159     mp->sad_id = ntohl(sad_id);
8160     mp->is_add = is_add;
8161     mp->protocol = protocol;
8162     mp->spi = ntohl(spi);
8163     mp->is_tunnel = is_tunnel;
8164     mp->is_tunnel_ipv6 = is_tunnel_ipv6;
8165     mp->crypto_algorithm = crypto_alg;
8166     mp->integrity_algorithm = integ_alg;
8167     mp->crypto_key_length = vec_len(ck);
8168     mp->integrity_key_length = vec_len(ik);
8169
8170     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8171       mp->crypto_key_length = sizeof(mp->crypto_key);
8172
8173     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8174       mp->integrity_key_length = sizeof(mp->integrity_key);
8175
8176     memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8177     memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8178
8179     if (is_tunnel) {
8180       if (is_tunnel_ipv6) {
8181         memcpy (mp->tunnel_src_address, &tun_src6, sizeof(ip6_address_t));
8182         memcpy (mp->tunnel_dst_address, &tun_dst6, sizeof(ip6_address_t));
8183       } else {
8184         memcpy (mp->tunnel_src_address, &tun_src4, sizeof(ip4_address_t));
8185         memcpy (mp->tunnel_dst_address, &tun_dst4, sizeof(ip4_address_t));
8186       }
8187     }
8188
8189     S; W;
8190     /* NOTREACHED */
8191     return 0;
8192 #else
8193     clib_warning ("unsupported (no dpdk)");
8194     return -99;
8195 #endif
8196 }
8197
8198 static int
8199 api_ipsec_sa_set_key (vat_main_t * vam)
8200 {
8201 #if DPDK > 0
8202     unformat_input_t * i = vam->input;
8203     vl_api_ipsec_sa_set_key_t *mp;
8204     f64 timeout;
8205     u32 sa_id;
8206     u8 * ck, * ik;
8207
8208     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8209         if (unformat (i, "sa_id %d", &sa_id))
8210             ;
8211         else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
8212             ;
8213         else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
8214             ;
8215         else {
8216             clib_warning ("parse error '%U'", format_unformat_error, i);
8217             return -99;
8218         }
8219     }
8220
8221     M(IPSEC_SA_SET_KEY, ipsec_set_sa_key);
8222
8223     mp->sa_id = ntohl(sa_id);
8224     mp->crypto_key_length = vec_len(ck);
8225     mp->integrity_key_length = vec_len(ik);
8226
8227     if (mp->crypto_key_length > sizeof(mp->crypto_key))
8228       mp->crypto_key_length = sizeof(mp->crypto_key);
8229
8230     if (mp->integrity_key_length > sizeof(mp->integrity_key))
8231       mp->integrity_key_length = sizeof(mp->integrity_key);
8232
8233     memcpy (mp->crypto_key, ck, mp->crypto_key_length);
8234     memcpy (mp->integrity_key, ik, mp->integrity_key_length);
8235
8236     S; W;
8237     /* NOTREACHED */
8238     return 0;
8239 #else
8240     clib_warning ("unsupported (no dpdk)");
8241     return -99;
8242 #endif
8243 }
8244
8245 /*
8246  * MAP
8247  */
8248 static int api_map_add_domain (vat_main_t * vam)
8249 {
8250   unformat_input_t *i = vam->input;
8251   vl_api_map_add_domain_t *mp;
8252   f64 timeout;
8253
8254   ip4_address_t ip4_prefix;
8255   ip6_address_t ip6_prefix;
8256   ip6_address_t ip6_src;
8257   u32 num_m_args = 0;
8258   u32 ip6_prefix_len, ip4_prefix_len, ea_bits_len, psid_offset,
8259     psid_length;
8260   u8 is_translation = 0;
8261   u32 mtu = 0;
8262   u8 ip6_src_len = 128;
8263
8264   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8265     if (unformat (i, "ip4-pfx %U/%d", unformat_ip4_address,
8266                   &ip4_prefix, &ip4_prefix_len))
8267       num_m_args++;
8268     else if (unformat (i, "ip6-pfx %U/%d", unformat_ip6_address,
8269                        &ip6_prefix, &ip6_prefix_len))
8270       num_m_args++;
8271     else if (unformat (i, "ip6-src %U/%d", unformat_ip6_address, &ip6_src, &ip6_src_len))
8272       num_m_args++;
8273     else if (unformat (i, "ip6-src %U", unformat_ip6_address, &ip6_src))
8274       num_m_args++;
8275     else if (unformat (i, "ea-bits-len %d", &ea_bits_len))
8276       num_m_args++;
8277     else if (unformat (i, "psid-offset %d", &psid_offset))
8278       num_m_args++;
8279     else if (unformat (i, "psid-len %d", &psid_length))
8280       num_m_args++;
8281     else if (unformat (i, "mtu %d", &mtu))
8282       num_m_args++;
8283     else if (unformat (i, "map-t"))
8284       is_translation = 1;
8285     else {
8286       clib_warning ("parse error '%U'", format_unformat_error, i);
8287       return -99;
8288     }
8289   }
8290
8291   if (num_m_args != 6) {
8292     errmsg("mandatory argument(s) missing\n");
8293     return -99;
8294   }
8295
8296   /* Construct the API message */
8297   M(MAP_ADD_DOMAIN, map_add_domain);
8298
8299   memcpy(mp->ip4_prefix, &ip4_prefix, sizeof(ip4_prefix));
8300   mp->ip4_prefix_len = ip4_prefix_len;
8301
8302   memcpy(mp->ip6_prefix, &ip6_prefix, sizeof(ip6_prefix));
8303   mp->ip6_prefix_len = ip6_prefix_len;
8304
8305   memcpy(mp->ip6_src, &ip6_src, sizeof(ip6_src));
8306   mp->ip6_src_prefix_len = ip6_src_len;
8307
8308   mp->ea_bits_len = ea_bits_len;
8309   mp->psid_offset = psid_offset;
8310   mp->psid_length = psid_length;
8311   mp->is_translation = is_translation;
8312   mp->mtu = htons(mtu);
8313
8314   /* send it... */
8315   S;
8316
8317   /* Wait for a reply, return good/bad news  */
8318   W;
8319 }
8320
8321 static int api_map_del_domain (vat_main_t * vam)
8322 {
8323   unformat_input_t *i = vam->input;
8324   vl_api_map_del_domain_t *mp;
8325   f64 timeout;
8326
8327   u32 num_m_args = 0;
8328   u32 index;
8329
8330   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8331     if (unformat (i, "index %d", &index))
8332       num_m_args++;
8333     else {
8334       clib_warning ("parse error '%U'", format_unformat_error, i);
8335       return -99;
8336     }
8337   }
8338
8339   if (num_m_args != 1) {
8340     errmsg("mandatory argument(s) missing\n");
8341     return -99;
8342   }
8343
8344   /* Construct the API message */
8345   M(MAP_DEL_DOMAIN, map_del_domain);
8346
8347   mp->index = ntohl(index);
8348
8349   /* send it... */
8350   S;
8351
8352   /* Wait for a reply, return good/bad news  */
8353   W;
8354 }
8355
8356 static int api_map_add_del_rule (vat_main_t * vam)
8357 {
8358   unformat_input_t *i = vam->input;
8359   vl_api_map_add_del_rule_t *mp;
8360   f64 timeout;
8361   u8 is_add = 1;
8362   ip6_address_t ip6_dst;
8363   u32 num_m_args = 0, index, psid;
8364
8365   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8366     if (unformat (i, "index %d", &index))
8367       num_m_args++;
8368     else if (unformat (i, "psid %d", &psid))
8369       num_m_args++;
8370     else if (unformat (i, "dst %U", unformat_ip6_address, &ip6_dst))
8371       num_m_args++;
8372     else if (unformat (i, "del")) {
8373       is_add = 0;
8374     } else {
8375       clib_warning ("parse error '%U'", format_unformat_error, i);
8376       return -99;
8377     }
8378   }
8379
8380   /* Construct the API message */
8381   M(MAP_ADD_DEL_RULE, map_add_del_rule);
8382
8383   mp->index = ntohl(index);
8384   mp->is_add = is_add;
8385   memcpy(mp->ip6_dst, &ip6_dst, sizeof(ip6_dst));
8386   mp->psid = ntohs(psid);
8387
8388   /* send it... */
8389   S;
8390
8391   /* Wait for a reply, return good/bad news  */
8392   W;
8393 }
8394
8395 static int api_map_domain_dump (vat_main_t * vam)
8396 {
8397     vl_api_map_domain_dump_t *mp;
8398     f64 timeout;
8399
8400     /* Construct the API message */
8401     M(MAP_DOMAIN_DUMP, map_domain_dump);
8402
8403     /* send it... */
8404     S;
8405
8406     /* Use a control ping for synchronization */
8407     {
8408         vl_api_control_ping_t * mp;
8409         M(CONTROL_PING, control_ping);
8410         S;
8411     }
8412     W;
8413 }
8414
8415 static int api_map_rule_dump (vat_main_t * vam)
8416 {
8417     unformat_input_t *i = vam->input;
8418     vl_api_map_rule_dump_t *mp;
8419     f64 timeout;
8420     u32 domain_index = ~0;
8421
8422     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8423         if (unformat (i, "index %u", &domain_index))
8424             ;
8425         else
8426             break;
8427     }
8428
8429     if (domain_index == ~0) {
8430         clib_warning("parse error: domain index expected");
8431         return -99;
8432     }
8433
8434     /* Construct the API message */
8435     M(MAP_RULE_DUMP, map_rule_dump);
8436
8437     mp->domain_index = htonl(domain_index);
8438
8439     /* send it... */
8440     S;
8441
8442     /* Use a control ping for synchronization */
8443     {
8444         vl_api_control_ping_t * mp;
8445         M(CONTROL_PING, control_ping);
8446         S;
8447     }
8448     W;
8449 }
8450
8451 static void vl_api_map_add_domain_reply_t_handler
8452 (vl_api_map_add_domain_reply_t * mp)
8453 {
8454   vat_main_t * vam = &vat_main;
8455   i32 retval = ntohl(mp->retval);
8456
8457   if (vam->async_mode) {
8458       vam->async_errors += (retval < 0);
8459   } else {
8460       vam->retval = retval;
8461       vam->result_ready = 1;
8462   }
8463 }
8464
8465 static void vl_api_map_add_domain_reply_t_handler_json
8466 (vl_api_map_add_domain_reply_t * mp)
8467 {
8468   vat_main_t * vam = &vat_main;
8469   vat_json_node_t node;
8470
8471   vat_json_init_object(&node);
8472   vat_json_object_add_int(&node, "retval", ntohl(mp->retval));
8473   vat_json_object_add_uint(&node, "index", ntohl(mp->index));
8474
8475   vat_json_print(vam->ofp, &node);
8476   vat_json_free(&node);
8477
8478   vam->retval = ntohl(mp->retval);
8479   vam->result_ready = 1;
8480 }
8481
8482 static int
8483 api_get_first_msg_id (vat_main_t * vam)
8484 {
8485     vl_api_get_first_msg_id_t * mp;
8486     f64 timeout;
8487     unformat_input_t * i = vam->input;
8488     u8 * name;
8489     u8 name_set = 0;
8490     
8491     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
8492         if (unformat (i, "client %s", &name))
8493             name_set = 1;
8494         else 
8495             break;
8496     }
8497
8498     if (name_set == 0) {
8499         errmsg ("missing client name\n");
8500         return -99;
8501     }
8502     vec_add1 (name, 0);
8503
8504     if (vec_len (name) > 63) {
8505         errmsg ("client name too long\n");
8506         return -99;
8507     }
8508
8509     M(GET_FIRST_MSG_ID, get_first_msg_id);
8510     memcpy (mp->name, name, vec_len(name));
8511     S; W;
8512     /* NOTREACHED */
8513     return 0;
8514 }
8515
8516 static int api_cop_interface_enable_disable (vat_main_t * vam)
8517 {
8518     unformat_input_t * line_input = vam->input;
8519     vl_api_cop_interface_enable_disable_t * mp;
8520     f64 timeout;
8521     u32 sw_if_index = ~0;
8522     u8 enable_disable = 1;
8523
8524     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8525         if (unformat (line_input, "disable"))
8526             enable_disable = 0;
8527         if (unformat (line_input, "enable"))
8528             enable_disable = 1;
8529         else if (unformat (line_input, "%U", unformat_sw_if_index,
8530                            vam, &sw_if_index))
8531             ;
8532         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8533             ;
8534         else
8535             break;
8536     }
8537         
8538     if (sw_if_index == ~0) {
8539         errmsg ("missing interface name or sw_if_index\n");
8540         return -99;
8541     }
8542
8543     /* Construct the API message */
8544     M(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable);
8545     mp->sw_if_index = ntohl(sw_if_index);
8546     mp->enable_disable = enable_disable;
8547
8548     /* send it... */
8549     S;
8550     /* Wait for the reply */
8551     W;
8552 }
8553
8554 static int api_cop_whitelist_enable_disable (vat_main_t * vam)
8555 {
8556     unformat_input_t * line_input = vam->input;
8557     vl_api_cop_whitelist_enable_disable_t * mp;
8558     f64 timeout;
8559     u32 sw_if_index = ~0;
8560     u8 ip4=0, ip6=0, default_cop=0;
8561     u32 fib_id;
8562
8563     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8564         if (unformat (line_input, "ip4"))
8565             ip4 = 1;
8566         else if (unformat (line_input, "ip6"))
8567             ip6 = 1;
8568         else if (unformat (line_input, "default"))
8569             default_cop = 1;
8570         else if (unformat (line_input, "%U", unformat_sw_if_index,
8571                            vam, &sw_if_index))
8572             ;
8573         else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
8574             ;
8575         else if (unformat (line_input, "fib-id %d", &fib_id))
8576             ;
8577         else
8578             break;
8579     }
8580         
8581     if (sw_if_index == ~0) {
8582         errmsg ("missing interface name or sw_if_index\n");
8583         return -99;
8584     }
8585
8586     /* Construct the API message */
8587     M(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable);
8588     mp->sw_if_index = ntohl(sw_if_index);
8589     mp->fib_id = ntohl(fib_id);
8590     mp->ip4 = ip4;
8591     mp->ip6 = ip6;
8592     mp->default_cop = default_cop;
8593
8594     /* send it... */
8595     S;
8596     /* Wait for the reply */
8597     W;
8598 }
8599
8600 static int api_get_node_graph (vat_main_t * vam)
8601 {
8602     vl_api_get_node_graph_t * mp;
8603     f64 timeout;
8604
8605     M(GET_NODE_GRAPH, get_node_graph);
8606
8607     /* send it... */
8608     S;
8609     /* Wait for the reply */
8610     W;
8611 }
8612
8613 static int q_or_quit (vat_main_t * vam)
8614 {
8615     longjmp (vam->jump_buf, 1);
8616     return 0; /* not so much */
8617 }
8618 static int q (vat_main_t * vam) {return q_or_quit (vam);}
8619 static int quit (vat_main_t * vam) {return q_or_quit (vam);}
8620
8621 static int comment (vat_main_t * vam)
8622 {
8623     return 0;
8624 }
8625
8626 static int cmd_cmp (void * a1, void * a2)
8627 {
8628   u8 ** c1 = a1;
8629   u8 ** c2 = a2;
8630
8631   return strcmp ((char *)(c1[0]), (char *)(c2[0]));
8632 }
8633
8634 static int help (vat_main_t * vam)
8635 {
8636     u8 ** cmds = 0;
8637     u8 * name = 0;
8638     hash_pair_t * p;
8639     unformat_input_t * i = vam->input;
8640     int j;
8641
8642     if (unformat (i, "%s", &name)) {
8643         uword *hs;
8644
8645         vec_add1(name, 0);
8646
8647         hs = hash_get_mem (vam->help_by_name, name);
8648         if (hs)
8649             fformat (vam->ofp, "usage: %s %s\n", name, hs[0]);
8650         else
8651             fformat (vam->ofp, "No such msg / command '%s'\n", name);
8652         vec_free(name);
8653         return 0;
8654     }
8655
8656     fformat(vam->ofp, "Help is available for the following:\n");
8657
8658     hash_foreach_pair (p, vam->function_by_name, 
8659     ({
8660         vec_add1 (cmds, (u8 *)(p->key));
8661     }));
8662
8663     vec_sort_with_function (cmds, cmd_cmp);
8664
8665     for (j = 0; j < vec_len(cmds); j++)
8666         fformat (vam->ofp, "%s\n", cmds[j]);
8667
8668     vec_free (cmds);
8669     return 0;
8670 }
8671
8672 static int set (vat_main_t * vam)
8673 {
8674     u8 * name = 0, * value = 0;
8675     unformat_input_t * i = vam->input;
8676
8677     if (unformat (i, "%s", &name)) {
8678         /* The input buffer is a vector, not a string. */
8679         value = vec_dup (i->buffer);
8680         vec_delete (value, i->index, 0);
8681         /* Almost certainly has a trailing newline */
8682         if (value[vec_len(value)-1] == '\n')
8683             value[vec_len(value)-1] = 0;
8684         /* Make sure it's a proper string, one way or the other */
8685         vec_add1 (value, 0);
8686         (void) clib_macro_set_value (&vam->macro_main, 
8687                                      (char *)name, (char *)value);
8688     }
8689     else
8690         errmsg ("usage: set <name> <value>\n");
8691
8692     vec_free (name);
8693     vec_free (value);
8694     return 0;
8695 }
8696
8697 static int unset (vat_main_t * vam)
8698 {
8699     u8 * name = 0;
8700
8701     if (unformat (vam->input, "%s", &name))
8702         if (clib_macro_unset (&vam->macro_main, (char *)name) == 1)
8703             errmsg ("unset: %s wasn't set\n", name);
8704     vec_free (name);
8705     return 0;
8706 }
8707
8708 typedef struct {
8709     u8 * name;
8710     u8 * value;
8711 } macro_sort_t;
8712
8713
8714 static int macro_sort_cmp (void * a1, void * a2)
8715 {
8716   macro_sort_t * s1 = a1;
8717   macro_sort_t * s2 = a2;
8718
8719   return strcmp ((char *)(s1->name), (char *)(s2->name));
8720 }
8721
8722 static int dump_macro_table (vat_main_t * vam)
8723 {
8724     macro_sort_t * sort_me = 0, * sm;    
8725     int i;
8726     hash_pair_t * p;
8727
8728     hash_foreach_pair (p, vam->macro_main.the_value_table_hash, 
8729     ({
8730         vec_add2 (sort_me, sm, 1);
8731         sm->name = (u8 *)(p->key);
8732         sm->value = (u8 *) (p->value[0]);
8733     }));
8734     
8735     vec_sort_with_function (sort_me, macro_sort_cmp);
8736
8737     if (vec_len(sort_me))
8738         fformat (vam->ofp, "%-15s%s\n", "Name", "Value");
8739     else
8740         fformat (vam->ofp, "The macro table is empty...\n");
8741
8742     for (i = 0; i < vec_len (sort_me); i++)
8743         fformat (vam->ofp, "%-15s%s\n", sort_me[i].name,
8744                  sort_me[i].value);
8745     return 0;
8746 }
8747
8748 static int dump_node_table (vat_main_t * vam)
8749 {
8750     int i, j;
8751     vlib_node_t * node, * next_node;
8752
8753     if (vec_len (vam->graph_nodes) == 0) {
8754         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
8755         return 0;
8756     }
8757
8758     for (i = 0; i < vec_len (vam->graph_nodes); i++) {
8759         node = vam->graph_nodes[i];
8760         fformat (vam->ofp, "[%d] %s\n", i, node->name);
8761         for (j = 0; j < vec_len (node->next_nodes); j++) {
8762             if (node->next_nodes[j] != ~0) {
8763                 next_node = vam->graph_nodes[node->next_nodes[j]];
8764                 fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
8765             }
8766         }
8767     }
8768     return 0;
8769 }
8770
8771 static int search_node_table (vat_main_t * vam)
8772 {
8773     unformat_input_t * line_input = vam->input;
8774     u8 * node_to_find;
8775     int j;
8776     vlib_node_t * node, * next_node;
8777     uword * p;
8778
8779     if (vam->graph_node_index_by_name == 0) {
8780         fformat (vam->ofp, "Node table empty, issue get_node_graph...\n");
8781         return 0;
8782     }
8783
8784     while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
8785         if (unformat (line_input, "%s", &node_to_find)) {
8786             vec_add1 (node_to_find, 0);
8787             p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
8788             if (p == 0) {
8789                 fformat (vam->ofp, "%s not found...\n", node_to_find);
8790                 goto out;
8791             }
8792             node = vam->graph_nodes[p[0]];
8793             fformat (vam->ofp, "[%d] %s\n", p[0], node->name);
8794             for (j = 0; j < vec_len (node->next_nodes); j++) {
8795                 if (node->next_nodes[j] != ~0) {
8796                     next_node = vam->graph_nodes[node->next_nodes[j]];
8797                     fformat (vam->ofp, "  [%d] %s\n", j, next_node->name);
8798                 }
8799             }
8800         }
8801             
8802         else {
8803             clib_warning ("parse error '%U'", format_unformat_error, 
8804                           line_input);
8805             return -99;
8806         }
8807
8808     out:
8809         vec_free(node_to_find);
8810         
8811     }
8812
8813     return 0;        
8814 }
8815
8816
8817 static int script (vat_main_t * vam)
8818 {
8819     u8 * s = 0;
8820     char * save_current_file;
8821     unformat_input_t save_input;
8822     jmp_buf save_jump_buf;
8823     u32 save_line_number;
8824
8825     FILE * new_fp, * save_ifp;
8826
8827     if (unformat (vam->input, "%s", &s)) {
8828         new_fp = fopen ((char *)s, "r");
8829         if (new_fp == 0) {
8830             errmsg ("Couldn't open script file %s\n", s);
8831             vec_free (s);
8832             return -99;
8833         }
8834     } else {
8835         errmsg ("Missing script name\n");
8836         return -99;
8837     }
8838
8839     memcpy (&save_input, &vam->input, sizeof (save_input));
8840     memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
8841     save_ifp = vam->ifp;
8842     save_line_number = vam->input_line_number;
8843     save_current_file = (char *) vam->current_file;
8844
8845     vam->input_line_number = 0;
8846     vam->ifp = new_fp;
8847     vam->current_file = s;
8848     do_one_file (vam);
8849
8850     memcpy (&vam->input, &save_input, sizeof (vam->input));
8851     memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
8852     vam->ifp = save_ifp;
8853     vam->input_line_number = save_line_number;
8854     vam->current_file = (u8 *) save_current_file;
8855     vec_free (s);
8856
8857     return 0;
8858 }
8859
8860 static int echo (vat_main_t * vam)
8861 {
8862     fformat (vam->ofp, "%v", vam->input->buffer);
8863     return 0;
8864 }
8865
8866 /* List of API message constructors, CLI names map to api_xxx */
8867 #define foreach_vpe_api_msg                                             \
8868 _(create_loopback,"[mac <mac-addr>]")                                   \
8869 _(sw_interface_dump,"")                                                 \
8870 _(sw_interface_set_flags,                                               \
8871   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
8872 _(sw_interface_add_del_address,                                         \
8873   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
8874 _(sw_interface_set_table,                                               \
8875   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
8876 _(sw_interface_set_vpath,                                               \
8877   "<intfc> | sw_if_index <id> enable | disable")                        \
8878 _(sw_interface_set_l2_xconnect,                                         \
8879   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8880   "enable | disable")                                                   \
8881 _(sw_interface_set_l2_bridge,                                           \
8882   "rx <intfc> | rx_sw_if_index <id> bd_id <bridge-domain-id>\n"         \
8883   "[shg <split-horizon-group>] [bvi]\n"                                 \
8884   "enable | disable")                                                   \
8885 _(bridge_domain_add_del,                                                \
8886   "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [del]\n")\
8887 _(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n")     \
8888 _(l2fib_add_del,                                                        \
8889   "mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi]\n") \
8890 _(l2_flags,                                                             \
8891   "sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood]\n")       \
8892 _(bridge_flags,                                                         \
8893   "bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
8894 _(tap_connect,                                                          \
8895   "tapname <name> mac <mac-addr> | random-mac")                         \
8896 _(tap_modify,                                                           \
8897   "<vpp-if-name> | sw_if_index <id> tapname <name> mac <mac-addr> | random-mac") \
8898 _(tap_delete,                                                           \
8899   "<vpp-if-name> | sw_if_index <id>")                                   \
8900 _(sw_interface_tap_dump, "")                                            \
8901 _(ip_add_del_route,                                                     \
8902   "<addr>/<mask> via <addr> [vrf <n>]\n"                                \
8903   "[<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"               \
8904   "[weight <n>] [drop] [local] [classify <n>] [del]\n"                  \
8905   "[multipath] [count <n>]")                                            \
8906 _(proxy_arp_add_del,                                                    \
8907   "<lo-ip4-addr> - <hi-ip4-addr> [vrf <n>] [del]")                      \
8908 _(proxy_arp_intfc_enable_disable,                                       \
8909   "<intfc> | sw_if_index <id> enable | disable")                        \
8910 _(mpls_add_del_encap,                                                   \
8911   "label <n> dst <ip4-addr> [vrf <n>] [del]")                           \
8912 _(mpls_add_del_decap,                                                   \
8913   "label <n> [rx_vrf_id <n>] [tx_vrf_id] [s-bit-clear][del]")           \
8914 _(mpls_gre_add_del_tunnel,                                              \
8915   "inner_vrf_id <n> outer_vrf_id <n> src <ip4-address> dst <ip4-address>\n" \
8916   "adj <ip4-address>/<mask-width> [del]")                               \
8917 _(sw_interface_set_unnumbered,                                          \
8918   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
8919 _(ip_neighbor_add_del,                                                  \
8920   "<intfc> | sw_if_index <id> dst <ip46-address> mac <mac-addr>")       \
8921 _(reset_vrf, "vrf <id> [ipv6]")                                         \
8922 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
8923 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
8924   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
8925   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
8926   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
8927 _(oam_add_del, "src <ip4-address> dst <ip4-address> [vrf <n>] [del]")   \
8928 _(reset_fib, "vrf <n> [ipv6]")                                          \
8929 _(dhcp_proxy_config,                                                    \
8930   "svr <v46-address> src <v46-address>\n"                               \
8931    "insert-cid <n> [del]")                                              \
8932 _(dhcp_proxy_config_2,                                                  \
8933   "svr <v46-address> src <v46-address>\n"                               \
8934    "rx_vrf_id <nn> server_vrf_id <nn> insert-cid <n> [del]")            \
8935 _(dhcp_proxy_set_vss,                                                   \
8936   "tbl_id <n> fib_id <n> oui <n> [ipv6] [del]")                         \
8937 _(dhcp_client_config,                                                   \
8938   "<intfc> | sw_if_index <id> [hostname <name>] [disable_event] [del]") \
8939 _(set_ip_flow_hash,                                                     \
8940   "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]")       \
8941 _(sw_interface_ip6_enable_disable,                                      \
8942   "<intfc> | sw_if_index <id> enable | disable")                        \
8943 _(sw_interface_ip6_set_link_local_address,                              \
8944   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>")              \
8945 _(sw_interface_ip6nd_ra_prefix,                                         \
8946   "<intfc> | sw_if_index <id> <ip6-address>/<mask-width>\n"             \
8947   "val_life <n> pref_life <n> [def] [noadv] [offl] [noauto]\n"          \
8948   "[nolink] [isno]")                                                    \
8949 _(sw_interface_ip6nd_ra_config,                                         \
8950   "<intfc> | sw_if_index <id> [maxint <n>] [minint <n>]\n"              \
8951   "[life <n>] [count <n>] [interval <n>] [surpress]\n"                  \
8952   "[managed] [other] [ll] [send] [cease] [isno] [def]")                 \
8953 _(set_arp_neighbor_limit, "arp_nbr_limit <n> [ipv6]")                   \
8954 _(l2_patch_add_del,                                                     \
8955   "rx <intfc> | rx_sw_if_index <id> tx <intfc> | tx_sw_if_index <id>\n" \
8956   "enable | disable")                                                   \
8957 _(mpls_ethernet_add_del_tunnel,                                         \
8958   "tx <intfc> | tx_sw_if_index <n> dst <mac-addr>\n"                    \
8959   "adj <ip4-addr>/<mw> dst <mac-addr> [del]")                           \
8960 _(mpls_ethernet_add_del_tunnel_2,                                       \
8961   "inner_vrf_id <n> outer_vrf_id <n> next-hop <ip4-addr>\n"             \
8962   "resolve-attempts <n> resolve-if-needed 0 | 1 [del]")                 \
8963 _(sr_tunnel_add_del,                                                    \
8964   "src <ip6-addr> dst <ip6-addr>/<mw> (next <ip6-addr>)+\n"             \
8965   " [tag <ip6-addr>]* [clean] [reroute]")                               \
8966 _(classify_add_del_table,                                               \
8967   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"      \
8968   "[del] mask <mask-value>\n"                                           \
8969   " [l2-miss-next | miss-next | acl-miss-next] <name|nn>")              \
8970 _(classify_add_del_session,                                             \
8971   "[hit-next|l2-hit-next|acl-hit-next] <name|nn> table-index <nn>\n"    \
8972   "skip_n <nn> match_n <nn> match [hex] [l2] [l3 [ip4|ip6]]")           \
8973 _(classify_set_interface_ip_table,                                      \
8974   "<intfc> | sw_if_index <nn> table <nn>")                              \
8975 _(classify_set_interface_l2_tables,                                     \
8976   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
8977   "  [other-table <nn>]")                                               \
8978 _(get_node_index, "node <node-name")                                    \
8979 _(add_node_next, "node <node-name> next <next-node-name>")              \
8980 _(l2tpv3_create_tunnel,                                                 \
8981   "client_address <ip6-addr> our_address <ip6-addr>\n"                  \
8982   "[local_session_id <nn>][remote_session_id <nn>][local_cookie <nn>]\n"\
8983   "[remote_cookie <nn>]\n[l2-sublayer-preset]\n")                       \
8984 _(l2tpv3_set_tunnel_cookies,                                            \
8985   "<intfc> | sw_if_index <nn> [new_local_cookie <nn>]\n"                \
8986   "[new_remote_cookie <nn>]\n")                                         \
8987 _(l2tpv3_interface_enable_disable,                                      \
8988   "<intfc> | sw_if_index <nn> enable | disable")                        \
8989 _(l2tpv3_set_lookup_key,                                                \
8990   "lookup_v6_src | lookup_v6_dst | lookup_session_id")                  \
8991 _(sw_if_l2tpv3_tunnel_dump, "")                                         \
8992 _(vxlan_add_del_tunnel,                                                 \
8993   "src <ip4-addr> dst <ip4-addr> vni [encap-vrf-id <nn>]\n"             \
8994   " [decap-next l2|ip4|ip6] [del]")                                     \
8995 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
8996 _(l2_fib_clear_table, "")                                               \
8997 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
8998 _(l2_interface_vlan_tag_rewrite,                                        \
8999   "<intfc> | sw_if_index <nn> \n"                                       \
9000   "[disable][push-[1|2]][pop-[1|2]][translate-1-[1|2]] \n"              \
9001   "[translate-2-[1|2]] [push_dot1q 0] tag1 <nn> tag2 <nn>")             \
9002 _(create_vhost_user_if,                                                 \
9003         "socket <filename> [server] [renumber <dev_instance>] "         \
9004         "[mac <mac_address>]")                                          \
9005 _(modify_vhost_user_if,                                                 \
9006         "<intfc> | sw_if_index <nn> socket <filename>\n"                \
9007         "[server] [renumber <dev_instance>]")                           \
9008 _(delete_vhost_user_if, "<intfc> | sw_if_index <nn>")                   \
9009 _(sw_interface_vhost_user_dump, "")                                     \
9010 _(show_version, "")                                                     \
9011 _(nsh_gre_add_del_tunnel,                                               \
9012   "src <ip4-addr> dst <ip4-addr>"                                       \
9013   "c1 <nn> c2 <nn> c3 <nn> c4 <nn> spi <nn> si <nn>\n"                  \
9014   "[encap-fib-id <nn>] [decap-fib-id <nn>] [o-bit <1|0>]\n"             \
9015   "[c-bit <1|0>] [md-type <nn>][next-ip4][next-ip6][next-ethernet]\n"   \
9016   "[tlv <xx>][del]")                                                    \
9017 _(nsh_vxlan_gpe_add_del_tunnel,                                         \
9018   "src <ip4-addr> dst <ip4-addr> vni <nn>\n"                            \
9019   "c1 <nn> c2 <nn> c3 <nn> c4 <nn> spi <nn> si <nn>\n"                  \
9020   "[encap-vrf-id <nn>] [decap-vrf-id <nn>] [o-bit <1|0>]\n"             \
9021   "[c-bit <1|0>] [md-type <nn>][next-ip4][next-ip6][next-ethernet]\n"   \
9022   "[tlv <xx>][del]")                                                    \
9023 _(l2_fib_table_dump, "bd_id <bridge-domain-id>")                        \
9024 _(lisp_gpe_add_del_tunnel,                                              \
9025   "src <ip4-addr> dst <ip4-addr> iid <nn>|iidx <0xnn>\n"                \
9026   "[encap-vrf-id <nn>] [decap-vrf-id <nn>]\n"                           \
9027   "[n-bit][l-bit][e-bit][v-bit][i-bit][p-bit][not-p-bit][o-bit]\n"      \
9028   "[next-ip4][next-ip6][next-ethernet][next-nsh]\n"                     \
9029   "[decap-next [ip4|ip6|ethernet|nsh-encap|<nn>]][del]")                \
9030 _(interface_name_renumber,                                              \
9031   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
9032 _(input_acl_set_interface,                                              \
9033   "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
9034   "  [l2-table <nn>] [del]")                                            \
9035 _(want_ip4_arp_events, "address <ip4-address> [del]")                   \
9036 _(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)")        \
9037 _(ip_dump, "ipv4 | ipv6")                                               \
9038 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
9039 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
9040   "  spid_id <n> ")                                                     \
9041 _(ipsec_sad_add_del_entry, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
9042   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
9043   "  integ_alg <alg> integ_key <hex>")                                  \
9044 _(ipsec_spd_add_del_entry, "spd_id <n> priority <n> action <action>\n"  \
9045   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
9046   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
9047   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" )\
9048 _(ipsec_sa_set_key, "sa_id <n> crypto_key <hex> integ_key <hex>")       \
9049 _(delete_loopback,"sw_if_index <nn>")                                   \
9050 _(bd_ip_mac_add_del, "bd_id <bridge-domain-id> <ip4/6-addr> <mac-addr> [del]") \
9051 _(map_add_domain,                                                       \
9052   "ip4-pfx <ip4pfx> ip6-pfx <ip6pfx> "                                  \
9053   "ip6-src <ip6addr> "                                                  \
9054   "ea-bits-len <n> psid-offset <n> psid-len <n>")                       \
9055 _(map_del_domain, "index <n>")                                          \
9056 _(map_add_del_rule,                                                     \
9057   "index <n> psid <n> dst <ip6addr> [del]")                             \
9058 _(map_domain_dump, "")                                                  \
9059 _(map_rule_dump, "index <map-domain>")                                  \
9060 _(want_interface_events,  "enable|disable")                             \
9061 _(want_stats,"enable|disable")                                          \
9062 _(get_first_msg_id, "client <name>")                                    \
9063 _(cop_interface_enable_disable, "<intfc> | sw_if_index <nn> [disable]") \
9064 _(cop_whitelist_enable_disable, "<intfc> | sw_if_index <nn>\n"          \
9065   "fib-id <nn> [ip4][ip6][default]")                                    \
9066 _(get_node_graph, " ")
9067
9068 /* List of command functions, CLI names map directly to functions */
9069 #define foreach_cli_function                                    \
9070 _(comment, "usage: comment <ignore-rest-of-line>")              \
9071 _(dump_interface_table, "usage: dump_interface_table")          \
9072 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
9073 _(dump_ipv4_table, "usage: dump_ipv4_table")                    \
9074 _(dump_ipv6_table, "usage: dump_ipv6_table")                    \
9075 _(dump_stats_table, "usage: dump_stats_table")                  \
9076 _(dump_macro_table, "usage: dump_macro_table ")                 \
9077 _(dump_node_table, "usage: dump_node_table")                    \
9078 _(echo, "usage: echo <message>")                                \
9079 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
9080 _(help, "usage: help")                                          \
9081 _(q, "usage: quit")                                             \
9082 _(quit, "usage: quit")                                          \
9083 _(search_node_table, "usage: search_node_table <name>...")      \
9084 _(set, "usage: set <variable-name> <value>")                    \
9085 _(script, "usage: script <file-name>")                          \
9086 _(unset, "usage: unset <variable-name>")
9087
9088 #define _(N,n)                                  \
9089     static void vl_api_##n##_t_handler_uni      \
9090     (vl_api_##n##_t * mp)                       \
9091     {                                           \
9092         vat_main_t * vam = &vat_main;           \
9093         if (vam->json_output) {                 \
9094             vl_api_##n##_t_handler_json(mp);    \
9095         } else {                                \
9096             vl_api_##n##_t_handler(mp);         \
9097         }                                       \
9098     }
9099 foreach_vpe_api_reply_msg;
9100 #undef _
9101
9102 void vat_api_hookup (vat_main_t *vam)
9103 {
9104 #define _(N,n)                                                  \
9105     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
9106                            vl_api_##n##_t_handler_uni,          \
9107                            vl_noop_handler,                     \
9108                            vl_api_##n##_t_endian,               \
9109                            vl_api_##n##_t_print,                \
9110                            sizeof(vl_api_##n##_t), 1); 
9111     foreach_vpe_api_reply_msg;
9112 #undef _
9113
9114     vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
9115
9116     vam->sw_if_index_by_interface_name = 
9117         hash_create_string (0, sizeof (uword));
9118
9119     vam->function_by_name = 
9120         hash_create_string (0, sizeof(uword));
9121
9122     vam->help_by_name = 
9123         hash_create_string (0, sizeof(uword));
9124
9125     /* API messages we can send */
9126 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
9127     foreach_vpe_api_msg;
9128 #undef _
9129
9130     /* Help strings */
9131 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
9132     foreach_vpe_api_msg;
9133 #undef _
9134
9135     /* CLI functions */
9136 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
9137     foreach_cli_function;
9138 #undef _
9139
9140     /* Help strings */
9141 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
9142     foreach_cli_function;
9143 #undef _
9144 }
9145
9146 #undef vl_api_version
9147 #define vl_api_version(n,v) static u32 vpe_api_version = v;
9148 #include <api/vpe.api.h>
9149 #undef vl_api_version
9150
9151 void vl_client_add_api_signatures (vl_api_memclnt_create_t *mp) 
9152 {
9153     /* 
9154      * Send the main API signature in slot 0. This bit of code must
9155      * match the checks in ../vpe/api/api.c: vl_msg_api_version_check().
9156      */
9157     mp->api_versions[0] = clib_host_to_net_u32 (vpe_api_version);
9158 }