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