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