ip: api cleanup
[vpp.git] / src / vat / api_format.c
1 /*
2  *------------------------------------------------------------------
3  * api_format.c
4  *
5  * Copyright (c) 2014-2020 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 <vlib/pci/pci.h>
22 #include <vpp/api/types.h>
23 #include <vppinfra/socket.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vnet/ip/ip.h>
27 #include <vnet/ip-neighbor/ip_neighbor.h>
28 #include <vnet/ip/ip_types_api.h>
29 #include <vnet/l2/l2_input.h>
30 #include <vnet/udp/udp_local.h>
31
32 #include <vpp/api/vpe_msg_enum.h>
33 #include <vnet/l2/l2_classify.h>
34 #include <vnet/l2/l2_vtr.h>
35 #include <vnet/classify/in_out_acl.h>
36 #include <vnet/classify/policer_classify.h>
37 #include <vnet/classify/flow_classify.h>
38 #include <vnet/mpls/mpls.h>
39 #include <vnet/ipsec/ipsec.h>
40 #include <inttypes.h>
41 #include <vnet/ip/ip6_hop_by_hop.h>
42 #include <vnet/ip/ip_source_and_port_range_check.h>
43 #include <vnet/policer/xlate.h>
44 #include <vnet/span/span.h>
45 #include <vnet/policer/policer.h>
46 #include <vnet/policer/police.h>
47 #include <vnet/mfib/mfib_types.h>
48 #include <vnet/bonding/node.h>
49 #include <vnet/qos/qos_types.h>
50 #include <vnet/ethernet/ethernet_types_api.h>
51 #include <vnet/ip/ip_types_api.h>
52 #include "vat/json_format.h"
53 #include <vnet/ip/ip_types_api.h>
54 #include <vnet/ethernet/ethernet_types_api.h>
55
56 #include <inttypes.h>
57 #include <sys/stat.h>
58
59 #define vl_typedefs             /* define message structures */
60 #include <vpp/api/vpe_all_api_h.h>
61 #undef vl_typedefs
62
63 /* declare message handlers for each api */
64
65 #define vl_endianfun            /* define message structures */
66 #include <vpp/api/vpe_all_api_h.h>
67 #undef vl_endianfun
68
69 /* instantiate all the print functions we know about */
70 #if VPP_API_TEST_BUILTIN == 0
71 #define vl_print(handle, ...)
72 #else
73 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
74 #endif
75 #define vl_printfun
76 #include <vpp/api/vpe_all_api_h.h>
77 #undef vl_printfun
78
79 #define __plugin_msg_base 0
80 #include <vlibapi/vat_helper_macros.h>
81
82 void vl_api_set_elog_main (elog_main_t * m);
83 int vl_api_set_elog_trace_api_messages (int enable);
84
85 #if VPP_API_TEST_BUILTIN == 0
86 #include <netdb.h>
87
88 u32
89 vl (void *p)
90 {
91   return vec_len (p);
92 }
93
94 int
95 vat_socket_connect (vat_main_t * vam)
96 {
97   int rv;
98   api_main_t *am = vlibapi_get_main ();
99   vam->socket_client_main = &socket_client_main;
100   if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
101                                       "vpp_api_test",
102                                       0 /* default socket rx, tx buffer */ )))
103     return rv;
104
105   /* vpp expects the client index in network order */
106   vam->my_client_index = htonl (socket_client_main.client_index);
107   am->my_client_index = vam->my_client_index;
108   return 0;
109 }
110 #else /* vpp built-in case, we don't do sockets... */
111 int
112 vat_socket_connect (vat_main_t * vam)
113 {
114   return 0;
115 }
116
117 int
118 vl_socket_client_read (int wait)
119 {
120   return -1;
121 };
122
123 int
124 vl_socket_client_write ()
125 {
126   return -1;
127 };
128
129 void *
130 vl_socket_client_msg_alloc (int nbytes)
131 {
132   return 0;
133 }
134 #endif
135
136
137 f64
138 vat_time_now (vat_main_t * vam)
139 {
140 #if VPP_API_TEST_BUILTIN
141   return vlib_time_now (vam->vlib_main);
142 #else
143   return clib_time_now (&vam->clib_time);
144 #endif
145 }
146
147 void
148 errmsg (char *fmt, ...)
149 {
150   vat_main_t *vam = &vat_main;
151   va_list va;
152   u8 *s;
153
154   va_start (va, fmt);
155   s = va_format (0, fmt, &va);
156   va_end (va);
157
158   vec_add1 (s, 0);
159
160 #if VPP_API_TEST_BUILTIN
161   vlib_cli_output (vam->vlib_main, (char *) s);
162 #else
163   {
164     if (vam->ifp != stdin)
165       fformat (vam->ofp, "%s(%d): \n", vam->current_file,
166                vam->input_line_number);
167     else
168       fformat (vam->ofp, "%s\n", (char *) s);
169     fflush (vam->ofp);
170   }
171 #endif
172
173   vec_free (s);
174 }
175
176 #if VPP_API_TEST_BUILTIN == 0
177 static uword
178 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
179 {
180   vat_main_t *vam = va_arg (*args, vat_main_t *);
181   u32 *result = va_arg (*args, u32 *);
182   u8 *if_name;
183   uword *p;
184
185   if (!unformat (input, "%s", &if_name))
186     return 0;
187
188   p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
189   if (p == 0)
190     return 0;
191   *result = p[0];
192   return 1;
193 }
194
195 /* Parse an IP4 address %d.%d.%d.%d. */
196 uword
197 unformat_ip4_address (unformat_input_t * input, va_list * args)
198 {
199   u8 *result = va_arg (*args, u8 *);
200   unsigned a[4];
201
202   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
203     return 0;
204
205   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
206     return 0;
207
208   result[0] = a[0];
209   result[1] = a[1];
210   result[2] = a[2];
211   result[3] = a[3];
212
213   return 1;
214 }
215
216 uword
217 unformat_ethernet_address (unformat_input_t * input, va_list * args)
218 {
219   u8 *result = va_arg (*args, u8 *);
220   u32 i, a[6];
221
222   if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
223                  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
224     return 0;
225
226   /* Check range. */
227   for (i = 0; i < 6; i++)
228     if (a[i] >= (1 << 8))
229       return 0;
230
231   for (i = 0; i < 6; i++)
232     result[i] = a[i];
233
234   return 1;
235 }
236
237 /* Returns ethernet type as an int in host byte order. */
238 uword
239 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
240                                         va_list * args)
241 {
242   u16 *result = va_arg (*args, u16 *);
243   int type;
244
245   /* Numeric type. */
246   if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
247     {
248       if (type >= (1 << 16))
249         return 0;
250       *result = type;
251       return 1;
252     }
253   return 0;
254 }
255
256 /* Parse an IP46 address. */
257 uword
258 unformat_ip46_address (unformat_input_t * input, va_list * args)
259 {
260   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
261   ip46_type_t type = va_arg (*args, ip46_type_t);
262   if ((type != IP46_TYPE_IP6) &&
263       unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
264     {
265       ip46_address_mask_ip4 (ip46);
266       return 1;
267     }
268   else if ((type != IP46_TYPE_IP4) &&
269            unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
270     {
271       return 1;
272     }
273   return 0;
274 }
275
276 /* Parse an IP6 address. */
277 uword
278 unformat_ip6_address (unformat_input_t * input, va_list * args)
279 {
280   ip6_address_t *result = va_arg (*args, ip6_address_t *);
281   u16 hex_quads[8];
282   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
283   uword c, n_colon, double_colon_index;
284
285   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
286   double_colon_index = ARRAY_LEN (hex_quads);
287   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
288     {
289       hex_digit = 16;
290       if (c >= '0' && c <= '9')
291         hex_digit = c - '0';
292       else if (c >= 'a' && c <= 'f')
293         hex_digit = c + 10 - 'a';
294       else if (c >= 'A' && c <= 'F')
295         hex_digit = c + 10 - 'A';
296       else if (c == ':' && n_colon < 2)
297         n_colon++;
298       else
299         {
300           unformat_put_input (input);
301           break;
302         }
303
304       /* Too many hex quads. */
305       if (n_hex_quads >= ARRAY_LEN (hex_quads))
306         return 0;
307
308       if (hex_digit < 16)
309         {
310           hex_quad = (hex_quad << 4) | hex_digit;
311
312           /* Hex quad must fit in 16 bits. */
313           if (n_hex_digits >= 4)
314             return 0;
315
316           n_colon = 0;
317           n_hex_digits++;
318         }
319
320       /* Save position of :: */
321       if (n_colon == 2)
322         {
323           /* More than one :: ? */
324           if (double_colon_index < ARRAY_LEN (hex_quads))
325             return 0;
326           double_colon_index = n_hex_quads;
327         }
328
329       if (n_colon > 0 && n_hex_digits > 0)
330         {
331           hex_quads[n_hex_quads++] = hex_quad;
332           hex_quad = 0;
333           n_hex_digits = 0;
334         }
335     }
336
337   if (n_hex_digits > 0)
338     hex_quads[n_hex_quads++] = hex_quad;
339
340   {
341     word i;
342
343     /* Expand :: to appropriate number of zero hex quads. */
344     if (double_colon_index < ARRAY_LEN (hex_quads))
345       {
346         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
347
348         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
349           hex_quads[n_zero + i] = hex_quads[i];
350
351         for (i = 0; i < n_zero; i++)
352           hex_quads[double_colon_index + i] = 0;
353
354         n_hex_quads = ARRAY_LEN (hex_quads);
355       }
356
357     /* Too few hex quads given. */
358     if (n_hex_quads < ARRAY_LEN (hex_quads))
359       return 0;
360
361     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
362       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
363
364     return 1;
365   }
366 }
367
368 uword
369 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
370 {
371   u32 *r = va_arg (*args, u32 *);
372
373   if (0);
374 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
375   foreach_ipsec_policy_action
376 #undef _
377     else
378     return 0;
379   return 1;
380 }
381
382 u8 *
383 format_ipsec_crypto_alg (u8 * s, va_list * args)
384 {
385   u32 i = va_arg (*args, u32);
386   u8 *t = 0;
387
388   switch (i)
389     {
390 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
391       foreach_ipsec_crypto_alg
392 #undef _
393     default:
394       return format (s, "unknown");
395     }
396   return format (s, "%s", t);
397 }
398
399 u8 *
400 format_ipsec_integ_alg (u8 * s, va_list * args)
401 {
402   u32 i = va_arg (*args, u32);
403   u8 *t = 0;
404
405   switch (i)
406     {
407 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
408       foreach_ipsec_integ_alg
409 #undef _
410     default:
411       return format (s, "unknown");
412     }
413   return format (s, "%s", t);
414 }
415
416 #else /* VPP_API_TEST_BUILTIN == 1 */
417 static uword
418 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
419 {
420   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
421   vnet_main_t *vnm = vnet_get_main ();
422   u32 *result = va_arg (*args, u32 *);
423
424   return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
425 }
426
427 #endif /* VPP_API_TEST_BUILTIN */
428
429 #if (VPP_API_TEST_BUILTIN==0)
430
431 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
432 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
433 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
434 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
435
436 uword
437 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
438 {
439   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
440   mfib_itf_attribute_t attr;
441
442   old = *iflags;
443   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
444   {
445     if (unformat (input, mfib_itf_flag_long_names[attr]))
446       *iflags |= (1 << attr);
447   }
448   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
449   {
450     if (unformat (input, mfib_itf_flag_names[attr]))
451       *iflags |= (1 << attr);
452   }
453
454   return (old == *iflags ? 0 : 1);
455 }
456
457 uword
458 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
459 {
460   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
461   mfib_entry_attribute_t attr;
462
463   old = *eflags;
464   FOR_EACH_MFIB_ATTRIBUTE (attr)
465   {
466     if (unformat (input, mfib_flag_long_names[attr]))
467       *eflags |= (1 << attr);
468   }
469   FOR_EACH_MFIB_ATTRIBUTE (attr)
470   {
471     if (unformat (input, mfib_flag_names[attr]))
472       *eflags |= (1 << attr);
473   }
474
475   return (old == *eflags ? 0 : 1);
476 }
477
478 u8 *
479 format_ip4_address (u8 * s, va_list * args)
480 {
481   u8 *a = va_arg (*args, u8 *);
482   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
483 }
484
485 u8 *
486 format_ip6_address (u8 * s, va_list * args)
487 {
488   ip6_address_t *a = va_arg (*args, ip6_address_t *);
489   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
490
491   i_max_n_zero = ARRAY_LEN (a->as_u16);
492   max_n_zeros = 0;
493   i_first_zero = i_max_n_zero;
494   n_zeros = 0;
495   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
496     {
497       u32 is_zero = a->as_u16[i] == 0;
498       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
499         {
500           i_first_zero = i;
501           n_zeros = 0;
502         }
503       n_zeros += is_zero;
504       if ((!is_zero && n_zeros > max_n_zeros)
505           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
506         {
507           i_max_n_zero = i_first_zero;
508           max_n_zeros = n_zeros;
509           i_first_zero = ARRAY_LEN (a->as_u16);
510           n_zeros = 0;
511         }
512     }
513
514   last_double_colon = 0;
515   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
516     {
517       if (i == i_max_n_zero && max_n_zeros > 1)
518         {
519           s = format (s, "::");
520           i += max_n_zeros - 1;
521           last_double_colon = 1;
522         }
523       else
524         {
525           s = format (s, "%s%x",
526                       (last_double_colon || i == 0) ? "" : ":",
527                       clib_net_to_host_u16 (a->as_u16[i]));
528           last_double_colon = 0;
529         }
530     }
531
532   return s;
533 }
534
535 /* Format an IP46 address. */
536 u8 *
537 format_ip46_address (u8 * s, va_list * args)
538 {
539   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
540   ip46_type_t type = va_arg (*args, ip46_type_t);
541   int is_ip4 = 1;
542
543   switch (type)
544     {
545     case IP46_TYPE_ANY:
546       is_ip4 = ip46_address_is_ip4 (ip46);
547       break;
548     case IP46_TYPE_IP4:
549       is_ip4 = 1;
550       break;
551     case IP46_TYPE_IP6:
552       is_ip4 = 0;
553       break;
554     }
555
556   return is_ip4 ?
557     format (s, "%U", format_ip4_address, &ip46->ip4) :
558     format (s, "%U", format_ip6_address, &ip46->ip6);
559 }
560
561 u8 *
562 format_ethernet_address (u8 * s, va_list * args)
563 {
564   u8 *a = va_arg (*args, u8 *);
565
566   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
567                  a[0], a[1], a[2], a[3], a[4], a[5]);
568 }
569 #endif
570
571 void
572 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
573 {
574   if (is_ip4)
575     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
576   else
577     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
578                       sizeof (ip6_address_t));
579 }
580
581
582 static void vl_api_create_loopback_reply_t_handler
583   (vl_api_create_loopback_reply_t * mp)
584 {
585   vat_main_t *vam = &vat_main;
586   i32 retval = ntohl (mp->retval);
587
588   vam->retval = retval;
589   vam->regenerate_interface_table = 1;
590   vam->sw_if_index = ntohl (mp->sw_if_index);
591   vam->result_ready = 1;
592 }
593
594 static void vl_api_create_loopback_reply_t_handler_json
595   (vl_api_create_loopback_reply_t * mp)
596 {
597   vat_main_t *vam = &vat_main;
598   vat_json_node_t node;
599
600   vat_json_init_object (&node);
601   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
602   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
603
604   vat_json_print (vam->ofp, &node);
605   vat_json_free (&node);
606   vam->retval = ntohl (mp->retval);
607   vam->result_ready = 1;
608 }
609
610 static void vl_api_create_loopback_instance_reply_t_handler
611   (vl_api_create_loopback_instance_reply_t * mp)
612 {
613   vat_main_t *vam = &vat_main;
614   i32 retval = ntohl (mp->retval);
615
616   vam->retval = retval;
617   vam->regenerate_interface_table = 1;
618   vam->sw_if_index = ntohl (mp->sw_if_index);
619   vam->result_ready = 1;
620 }
621
622 static void vl_api_create_loopback_instance_reply_t_handler_json
623   (vl_api_create_loopback_instance_reply_t * mp)
624 {
625   vat_main_t *vam = &vat_main;
626   vat_json_node_t node;
627
628   vat_json_init_object (&node);
629   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
630   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
631
632   vat_json_print (vam->ofp, &node);
633   vat_json_free (&node);
634   vam->retval = ntohl (mp->retval);
635   vam->result_ready = 1;
636 }
637
638 static void vl_api_create_vlan_subif_reply_t_handler
639   (vl_api_create_vlan_subif_reply_t * mp)
640 {
641   vat_main_t *vam = &vat_main;
642   i32 retval = ntohl (mp->retval);
643
644   vam->retval = retval;
645   vam->regenerate_interface_table = 1;
646   vam->sw_if_index = ntohl (mp->sw_if_index);
647   vam->result_ready = 1;
648 }
649
650 static void vl_api_create_vlan_subif_reply_t_handler_json
651   (vl_api_create_vlan_subif_reply_t * mp)
652 {
653   vat_main_t *vam = &vat_main;
654   vat_json_node_t node;
655
656   vat_json_init_object (&node);
657   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
658   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
659
660   vat_json_print (vam->ofp, &node);
661   vat_json_free (&node);
662
663   vam->retval = ntohl (mp->retval);
664   vam->result_ready = 1;
665 }
666
667 static void vl_api_create_subif_reply_t_handler
668   (vl_api_create_subif_reply_t * mp)
669 {
670   vat_main_t *vam = &vat_main;
671   i32 retval = ntohl (mp->retval);
672
673   vam->retval = retval;
674   vam->regenerate_interface_table = 1;
675   vam->sw_if_index = ntohl (mp->sw_if_index);
676   vam->result_ready = 1;
677 }
678
679 static void vl_api_create_subif_reply_t_handler_json
680   (vl_api_create_subif_reply_t * mp)
681 {
682   vat_main_t *vam = &vat_main;
683   vat_json_node_t node;
684
685   vat_json_init_object (&node);
686   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
687   vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
688
689   vat_json_print (vam->ofp, &node);
690   vat_json_free (&node);
691
692   vam->retval = ntohl (mp->retval);
693   vam->result_ready = 1;
694 }
695
696 static void vl_api_interface_name_renumber_reply_t_handler
697   (vl_api_interface_name_renumber_reply_t * mp)
698 {
699   vat_main_t *vam = &vat_main;
700   i32 retval = ntohl (mp->retval);
701
702   vam->retval = retval;
703   vam->regenerate_interface_table = 1;
704   vam->result_ready = 1;
705 }
706
707 static void vl_api_interface_name_renumber_reply_t_handler_json
708   (vl_api_interface_name_renumber_reply_t * mp)
709 {
710   vat_main_t *vam = &vat_main;
711   vat_json_node_t node;
712
713   vat_json_init_object (&node);
714   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
715
716   vat_json_print (vam->ofp, &node);
717   vat_json_free (&node);
718
719   vam->retval = ntohl (mp->retval);
720   vam->result_ready = 1;
721 }
722
723 /*
724  * Special-case: build the interface table, maintain
725  * the next loopback sw_if_index vbl.
726  */
727 static void vl_api_sw_interface_details_t_handler
728   (vl_api_sw_interface_details_t * mp)
729 {
730   vat_main_t *vam = &vat_main;
731   u8 *s = format (0, "%s%c", mp->interface_name, 0);
732
733   hash_set_mem (vam->sw_if_index_by_interface_name, s,
734                 ntohl (mp->sw_if_index));
735
736   /* In sub interface case, fill the sub interface table entry */
737   if (mp->sw_if_index != mp->sup_sw_if_index)
738     {
739       sw_interface_subif_t *sub = NULL;
740
741       vec_add2 (vam->sw_if_subif_table, sub, 1);
742
743       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
744       strncpy ((char *) sub->interface_name, (char *) s,
745                vec_len (sub->interface_name));
746       sub->sw_if_index = ntohl (mp->sw_if_index);
747       sub->sub_id = ntohl (mp->sub_id);
748
749       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
750
751       sub->sub_number_of_tags = mp->sub_number_of_tags;
752       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
753       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
754
755       /* vlan tag rewrite */
756       sub->vtr_op = ntohl (mp->vtr_op);
757       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
758       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
759       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
760     }
761 }
762
763 static void vl_api_sw_interface_details_t_handler_json
764   (vl_api_sw_interface_details_t * mp)
765 {
766   vat_main_t *vam = &vat_main;
767   vat_json_node_t *node = NULL;
768
769   if (VAT_JSON_ARRAY != vam->json_tree.type)
770     {
771       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
772       vat_json_init_array (&vam->json_tree);
773     }
774   node = vat_json_array_add (&vam->json_tree);
775
776   vat_json_init_object (node);
777   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
778   vat_json_object_add_uint (node, "sup_sw_if_index",
779                             ntohl (mp->sup_sw_if_index));
780   vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
781                              sizeof (mp->l2_address));
782   vat_json_object_add_string_copy (node, "interface_name",
783                                    mp->interface_name);
784   vat_json_object_add_string_copy (node, "interface_dev_type",
785                                    mp->interface_dev_type);
786   vat_json_object_add_uint (node, "flags", mp->flags);
787   vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
788   vat_json_object_add_uint (node, "link_speed", mp->link_speed);
789   vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
790   vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
791   vat_json_object_add_uint (node, "sub_number_of_tags",
792                             mp->sub_number_of_tags);
793   vat_json_object_add_uint (node, "sub_outer_vlan_id",
794                             ntohs (mp->sub_outer_vlan_id));
795   vat_json_object_add_uint (node, "sub_inner_vlan_id",
796                             ntohs (mp->sub_inner_vlan_id));
797   vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
798   vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
799   vat_json_object_add_uint (node, "vtr_push_dot1q",
800                             ntohl (mp->vtr_push_dot1q));
801   vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
802   vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
803   if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
804     {
805       vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
806                                        format (0, "%U",
807                                                format_ethernet_address,
808                                                &mp->b_dmac));
809       vat_json_object_add_string_copy (node, "pbb_vtr_smac",
810                                        format (0, "%U",
811                                                format_ethernet_address,
812                                                &mp->b_smac));
813       vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
814       vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
815     }
816 }
817
818 #if VPP_API_TEST_BUILTIN == 0
819 static void vl_api_sw_interface_event_t_handler
820   (vl_api_sw_interface_event_t * mp)
821 {
822   vat_main_t *vam = &vat_main;
823   if (vam->interface_event_display)
824     errmsg ("interface flags: sw_if_index %d %s %s",
825             ntohl (mp->sw_if_index),
826             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
827             "admin-up" : "admin-down",
828             ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
829             "link-up" : "link-down");
830 }
831 #endif
832
833 __clib_unused static void
834 vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
835 {
836   /* JSON output not supported */
837 }
838
839 static void
840 vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
841 {
842   vat_main_t *vam = &vat_main;
843   i32 retval = ntohl (mp->retval);
844
845   vam->retval = retval;
846   vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
847   vam->result_ready = 1;
848 }
849
850 static void
851 vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
852 {
853   vat_main_t *vam = &vat_main;
854   vat_json_node_t node;
855   void *oldheap;
856   u8 *reply;
857
858   vat_json_init_object (&node);
859   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
860   vat_json_object_add_uint (&node, "reply_in_shmem",
861                             ntohl (mp->reply_in_shmem));
862   /* Toss the shared-memory original... */
863   oldheap = vl_msg_push_heap ();
864
865   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
866   vec_free (reply);
867
868   vl_msg_pop_heap (oldheap);
869
870   vat_json_print (vam->ofp, &node);
871   vat_json_free (&node);
872
873   vam->retval = ntohl (mp->retval);
874   vam->result_ready = 1;
875 }
876
877 static void
878 vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
879 {
880   vat_main_t *vam = &vat_main;
881   i32 retval = ntohl (mp->retval);
882
883   vec_reset_length (vam->cmd_reply);
884
885   vam->retval = retval;
886   if (retval == 0)
887     vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
888   vam->result_ready = 1;
889 }
890
891 static void
892 vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
893 {
894   vat_main_t *vam = &vat_main;
895   vat_json_node_t node;
896   u8 *reply = 0;                /* reply vector */
897
898   reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
899   vec_reset_length (vam->cmd_reply);
900
901   vat_json_init_object (&node);
902   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
903   vat_json_object_add_string_copy (&node, "reply", reply);
904
905   vat_json_print (vam->ofp, &node);
906   vat_json_free (&node);
907   vec_free (reply);
908
909   vam->retval = ntohl (mp->retval);
910   vam->result_ready = 1;
911 }
912
913 static void vl_api_get_node_index_reply_t_handler
914   (vl_api_get_node_index_reply_t * mp)
915 {
916   vat_main_t *vam = &vat_main;
917   i32 retval = ntohl (mp->retval);
918   if (vam->async_mode)
919     {
920       vam->async_errors += (retval < 0);
921     }
922   else
923     {
924       vam->retval = retval;
925       if (retval == 0)
926         errmsg ("node index %d", ntohl (mp->node_index));
927       vam->result_ready = 1;
928     }
929 }
930
931 static void vl_api_get_node_index_reply_t_handler_json
932   (vl_api_get_node_index_reply_t * mp)
933 {
934   vat_main_t *vam = &vat_main;
935   vat_json_node_t node;
936
937   vat_json_init_object (&node);
938   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
939   vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
940
941   vat_json_print (vam->ofp, &node);
942   vat_json_free (&node);
943
944   vam->retval = ntohl (mp->retval);
945   vam->result_ready = 1;
946 }
947
948 static void vl_api_get_next_index_reply_t_handler
949   (vl_api_get_next_index_reply_t * mp)
950 {
951   vat_main_t *vam = &vat_main;
952   i32 retval = ntohl (mp->retval);
953   if (vam->async_mode)
954     {
955       vam->async_errors += (retval < 0);
956     }
957   else
958     {
959       vam->retval = retval;
960       if (retval == 0)
961         errmsg ("next node index %d", ntohl (mp->next_index));
962       vam->result_ready = 1;
963     }
964 }
965
966 static void vl_api_get_next_index_reply_t_handler_json
967   (vl_api_get_next_index_reply_t * mp)
968 {
969   vat_main_t *vam = &vat_main;
970   vat_json_node_t node;
971
972   vat_json_init_object (&node);
973   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
974   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
975
976   vat_json_print (vam->ofp, &node);
977   vat_json_free (&node);
978
979   vam->retval = ntohl (mp->retval);
980   vam->result_ready = 1;
981 }
982
983 static void vl_api_add_node_next_reply_t_handler
984   (vl_api_add_node_next_reply_t * mp)
985 {
986   vat_main_t *vam = &vat_main;
987   i32 retval = ntohl (mp->retval);
988   if (vam->async_mode)
989     {
990       vam->async_errors += (retval < 0);
991     }
992   else
993     {
994       vam->retval = retval;
995       if (retval == 0)
996         errmsg ("next index %d", ntohl (mp->next_index));
997       vam->result_ready = 1;
998     }
999 }
1000
1001 static void vl_api_add_node_next_reply_t_handler_json
1002   (vl_api_add_node_next_reply_t * mp)
1003 {
1004   vat_main_t *vam = &vat_main;
1005   vat_json_node_t node;
1006
1007   vat_json_init_object (&node);
1008   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1009   vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1010
1011   vat_json_print (vam->ofp, &node);
1012   vat_json_free (&node);
1013
1014   vam->retval = ntohl (mp->retval);
1015   vam->result_ready = 1;
1016 }
1017
1018 static void vl_api_show_version_reply_t_handler
1019   (vl_api_show_version_reply_t * mp)
1020 {
1021   vat_main_t *vam = &vat_main;
1022   i32 retval = ntohl (mp->retval);
1023
1024   if (retval >= 0)
1025     {
1026       errmsg ("        program: %s", mp->program);
1027       errmsg ("        version: %s", mp->version);
1028       errmsg ("     build date: %s", mp->build_date);
1029       errmsg ("build directory: %s", mp->build_directory);
1030     }
1031   vam->retval = retval;
1032   vam->result_ready = 1;
1033 }
1034
1035 static void vl_api_show_version_reply_t_handler_json
1036   (vl_api_show_version_reply_t * mp)
1037 {
1038   vat_main_t *vam = &vat_main;
1039   vat_json_node_t node;
1040
1041   vat_json_init_object (&node);
1042   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1043   vat_json_object_add_string_copy (&node, "program", mp->program);
1044   vat_json_object_add_string_copy (&node, "version", mp->version);
1045   vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
1046   vat_json_object_add_string_copy (&node, "build_directory",
1047                                    mp->build_directory);
1048
1049   vat_json_print (vam->ofp, &node);
1050   vat_json_free (&node);
1051
1052   vam->retval = ntohl (mp->retval);
1053   vam->result_ready = 1;
1054 }
1055
1056 static void vl_api_show_threads_reply_t_handler
1057   (vl_api_show_threads_reply_t * mp)
1058 {
1059   vat_main_t *vam = &vat_main;
1060   i32 retval = ntohl (mp->retval);
1061   int i, count = 0;
1062
1063   if (retval >= 0)
1064     count = ntohl (mp->count);
1065
1066   for (i = 0; i < count; i++)
1067     print (vam->ofp,
1068            "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1069            ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1070            mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1071            ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1072            ntohl (mp->thread_data[i].cpu_socket));
1073
1074   vam->retval = retval;
1075   vam->result_ready = 1;
1076 }
1077
1078 static void vl_api_show_threads_reply_t_handler_json
1079   (vl_api_show_threads_reply_t * mp)
1080 {
1081   vat_main_t *vam = &vat_main;
1082   vat_json_node_t node;
1083   vl_api_thread_data_t *td;
1084   i32 retval = ntohl (mp->retval);
1085   int i, count = 0;
1086
1087   if (retval >= 0)
1088     count = ntohl (mp->count);
1089
1090   vat_json_init_object (&node);
1091   vat_json_object_add_int (&node, "retval", retval);
1092   vat_json_object_add_uint (&node, "count", count);
1093
1094   for (i = 0; i < count; i++)
1095     {
1096       td = &mp->thread_data[i];
1097       vat_json_object_add_uint (&node, "id", ntohl (td->id));
1098       vat_json_object_add_string_copy (&node, "name", td->name);
1099       vat_json_object_add_string_copy (&node, "type", td->type);
1100       vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1101       vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1102       vat_json_object_add_int (&node, "core", ntohl (td->id));
1103       vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1104     }
1105
1106   vat_json_print (vam->ofp, &node);
1107   vat_json_free (&node);
1108
1109   vam->retval = retval;
1110   vam->result_ready = 1;
1111 }
1112
1113 static int
1114 api_show_threads (vat_main_t * vam)
1115 {
1116   vl_api_show_threads_t *mp;
1117   int ret;
1118
1119   print (vam->ofp,
1120          "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1121          "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1122
1123   M (SHOW_THREADS, mp);
1124
1125   S (mp);
1126   W (ret);
1127   return ret;
1128 }
1129
1130 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
1131 #define vl_api_bridge_domain_details_t_print vl_noop_handler
1132
1133 static void vl_api_control_ping_reply_t_handler
1134   (vl_api_control_ping_reply_t * mp)
1135 {
1136   vat_main_t *vam = &vat_main;
1137   i32 retval = ntohl (mp->retval);
1138   if (vam->async_mode)
1139     {
1140       vam->async_errors += (retval < 0);
1141     }
1142   else
1143     {
1144       vam->retval = retval;
1145       vam->result_ready = 1;
1146     }
1147   if (vam->socket_client_main)
1148     vam->socket_client_main->control_pings_outstanding--;
1149 }
1150
1151 static void vl_api_control_ping_reply_t_handler_json
1152   (vl_api_control_ping_reply_t * mp)
1153 {
1154   vat_main_t *vam = &vat_main;
1155   i32 retval = ntohl (mp->retval);
1156
1157   if (VAT_JSON_NONE != vam->json_tree.type)
1158     {
1159       vat_json_print (vam->ofp, &vam->json_tree);
1160       vat_json_free (&vam->json_tree);
1161       vam->json_tree.type = VAT_JSON_NONE;
1162     }
1163   else
1164     {
1165       /* just print [] */
1166       vat_json_init_array (&vam->json_tree);
1167       vat_json_print (vam->ofp, &vam->json_tree);
1168       vam->json_tree.type = VAT_JSON_NONE;
1169     }
1170
1171   vam->retval = retval;
1172   vam->result_ready = 1;
1173 }
1174
1175
1176 static void vl_api_get_first_msg_id_reply_t_handler
1177   (vl_api_get_first_msg_id_reply_t * mp)
1178 {
1179   vat_main_t *vam = &vat_main;
1180   i32 retval = ntohl (mp->retval);
1181
1182   if (vam->async_mode)
1183     {
1184       vam->async_errors += (retval < 0);
1185     }
1186   else
1187     {
1188       vam->retval = retval;
1189       vam->result_ready = 1;
1190     }
1191   if (retval >= 0)
1192     {
1193       errmsg ("first message id %d", ntohs (mp->first_msg_id));
1194     }
1195 }
1196
1197 static void vl_api_get_first_msg_id_reply_t_handler_json
1198   (vl_api_get_first_msg_id_reply_t * mp)
1199 {
1200   vat_main_t *vam = &vat_main;
1201   vat_json_node_t node;
1202
1203   vat_json_init_object (&node);
1204   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1205   vat_json_object_add_uint (&node, "first_msg_id",
1206                             (uint) ntohs (mp->first_msg_id));
1207
1208   vat_json_print (vam->ofp, &node);
1209   vat_json_free (&node);
1210
1211   vam->retval = ntohl (mp->retval);
1212   vam->result_ready = 1;
1213 }
1214
1215 static void vl_api_get_node_graph_reply_t_handler
1216   (vl_api_get_node_graph_reply_t * mp)
1217 {
1218   vat_main_t *vam = &vat_main;
1219   i32 retval = ntohl (mp->retval);
1220   u8 *pvt_copy, *reply;
1221   void *oldheap;
1222   vlib_node_t *node;
1223   int i;
1224
1225   if (vam->async_mode)
1226     {
1227       vam->async_errors += (retval < 0);
1228     }
1229   else
1230     {
1231       vam->retval = retval;
1232       vam->result_ready = 1;
1233     }
1234
1235   /* "Should never happen..." */
1236   if (retval != 0)
1237     return;
1238
1239   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1240   pvt_copy = vec_dup (reply);
1241
1242   /* Toss the shared-memory original... */
1243   oldheap = vl_msg_push_heap ();
1244
1245   vec_free (reply);
1246
1247   vl_msg_pop_heap (oldheap);
1248
1249   if (vam->graph_nodes)
1250     {
1251       hash_free (vam->graph_node_index_by_name);
1252
1253       for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1254         {
1255           node = vam->graph_nodes[0][i];
1256           vec_free (node->name);
1257           vec_free (node->next_nodes);
1258           vec_free (node);
1259         }
1260       vec_free (vam->graph_nodes[0]);
1261       vec_free (vam->graph_nodes);
1262     }
1263
1264   vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
1265   vam->graph_nodes = vlib_node_unserialize (pvt_copy);
1266   vec_free (pvt_copy);
1267
1268   for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
1269     {
1270       node = vam->graph_nodes[0][i];
1271       hash_set_mem (vam->graph_node_index_by_name, node->name, i);
1272     }
1273 }
1274
1275 static void vl_api_get_node_graph_reply_t_handler_json
1276   (vl_api_get_node_graph_reply_t * mp)
1277 {
1278   vat_main_t *vam = &vat_main;
1279   void *oldheap;
1280   vat_json_node_t node;
1281   u8 *reply;
1282
1283   /* $$$$ make this real? */
1284   vat_json_init_object (&node);
1285   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1286   vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
1287
1288   reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
1289
1290   /* Toss the shared-memory original... */
1291   oldheap = vl_msg_push_heap ();
1292
1293   vec_free (reply);
1294
1295   vl_msg_pop_heap (oldheap);
1296
1297   vat_json_print (vam->ofp, &node);
1298   vat_json_free (&node);
1299
1300   vam->retval = ntohl (mp->retval);
1301   vam->result_ready = 1;
1302 }
1303
1304 /* Format hex dump. */
1305 u8 *
1306 format_hex_bytes (u8 * s, va_list * va)
1307 {
1308   u8 *bytes = va_arg (*va, u8 *);
1309   int n_bytes = va_arg (*va, int);
1310   uword i;
1311
1312   /* Print short or long form depending on byte count. */
1313   uword short_form = n_bytes <= 32;
1314   u32 indent = format_get_indent (s);
1315
1316   if (n_bytes == 0)
1317     return s;
1318
1319   for (i = 0; i < n_bytes; i++)
1320     {
1321       if (!short_form && (i % 32) == 0)
1322         s = format (s, "%08x: ", i);
1323       s = format (s, "%02x", bytes[i]);
1324       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
1325         s = format (s, "\n%U", format_white_space, indent);
1326     }
1327
1328   return s;
1329 }
1330
1331 /*
1332  * Generate boilerplate reply handlers, which
1333  * dig the return value out of the xxx_reply_t API message,
1334  * stick it into vam->retval, and set vam->result_ready
1335  *
1336  * Could also do this by pointing N message decode slots at
1337  * a single function, but that could break in subtle ways.
1338  */
1339
1340 #define foreach_standard_reply_retval_handler                                 \
1341   _ (sw_interface_set_flags_reply)                                            \
1342   _ (sw_interface_add_del_address_reply)                                      \
1343   _ (sw_interface_set_rx_placement_reply)                                     \
1344   _ (sw_interface_set_unnumbered_reply)                                       \
1345   _ (sw_interface_set_table_reply)                                            \
1346   _ (delete_loopback_reply)                                                   \
1347   _ (want_interface_events_reply)                                             \
1348   _ (sw_interface_clear_stats_reply)                                          \
1349   _ (delete_subif_reply)                                                      \
1350   _ (sw_interface_tag_add_del_reply)                                          \
1351   _ (sw_interface_add_del_mac_address_reply)                                  \
1352   _ (hw_interface_set_mtu_reply)                                              \
1353   _ (session_rule_add_del_reply)
1354
1355 #define _(n)                                    \
1356     static void vl_api_##n##_t_handler          \
1357     (vl_api_##n##_t * mp)                       \
1358     {                                           \
1359         vat_main_t * vam = &vat_main;           \
1360         i32 retval = ntohl(mp->retval);         \
1361         if (vam->async_mode) {                  \
1362             vam->async_errors += (retval < 0);  \
1363         } else {                                \
1364             vam->retval = retval;               \
1365             vam->result_ready = 1;              \
1366         }                                       \
1367     }
1368 foreach_standard_reply_retval_handler;
1369 #undef _
1370
1371 #define _(n)                                    \
1372     static void vl_api_##n##_t_handler_json     \
1373     (vl_api_##n##_t * mp)                       \
1374     {                                           \
1375         vat_main_t * vam = &vat_main;           \
1376         vat_json_node_t node;                   \
1377         vat_json_init_object(&node);            \
1378         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
1379         vat_json_print(vam->ofp, &node);        \
1380         vam->retval = ntohl(mp->retval);        \
1381         vam->result_ready = 1;                  \
1382     }
1383 foreach_standard_reply_retval_handler;
1384 #undef _
1385
1386 /*
1387  * Table of message reply handlers, must include boilerplate handlers
1388  * we just generated
1389  */
1390
1391 #define foreach_vpe_api_reply_msg                                       \
1392 _(CREATE_LOOPBACK_REPLY, create_loopback_reply)                         \
1393 _(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply)       \
1394 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
1395 _(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply)           \
1396 _(CONTROL_PING_REPLY, control_ping_reply)                               \
1397 _(CLI_REPLY, cli_reply)                                                 \
1398 _(CLI_INBAND_REPLY, cli_inband_reply)                                   \
1399 _(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY,                                   \
1400   sw_interface_add_del_address_reply)                                   \
1401 _(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply)     \
1402 _(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
1403 _(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply)           \
1404 _(SW_INTERFACE_SET_UNNUMBERED_REPLY,                                    \
1405   sw_interface_set_unnumbered_reply)                                    \
1406 _(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply)                     \
1407 _(CREATE_SUBIF_REPLY, create_subif_reply)                               \
1408 _(GET_NODE_INDEX_REPLY, get_node_index_reply)                           \
1409 _(ADD_NODE_NEXT_REPLY, add_node_next_reply)                             \
1410 _(SHOW_VERSION_REPLY, show_version_reply)                               \
1411 _(SHOW_THREADS_REPLY, show_threads_reply)                               \
1412 _(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply)         \
1413 _(DELETE_LOOPBACK_REPLY, delete_loopback_reply)                         \
1414 _(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply)             \
1415 _(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                       \
1416 _(GET_NODE_GRAPH_REPLY, get_node_graph_reply)                           \
1417 _(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply)      \
1418 _(GET_NEXT_INDEX_REPLY, get_next_index_reply)                           \
1419 _(DELETE_SUBIF_REPLY, delete_subif_reply)                               \
1420 _(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply)       \
1421 _(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
1422 _(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply)               \
1423 _(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply)           \
1424 _(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)             \
1425 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)               \
1426 _(SESSION_RULES_DETAILS, session_rules_details)                         \
1427
1428 #define foreach_standalone_reply_msg                                    \
1429 _(SW_INTERFACE_EVENT, sw_interface_event)
1430
1431 typedef struct
1432 {
1433   u8 *name;
1434   u32 value;
1435 } name_sort_t;
1436
1437 #define STR_VTR_OP_CASE(op)     \
1438     case L2_VTR_ ## op:         \
1439         return "" # op;
1440
1441 static const char *
1442 str_vtr_op (u32 vtr_op)
1443 {
1444   switch (vtr_op)
1445     {
1446       STR_VTR_OP_CASE (DISABLED);
1447       STR_VTR_OP_CASE (PUSH_1);
1448       STR_VTR_OP_CASE (PUSH_2);
1449       STR_VTR_OP_CASE (POP_1);
1450       STR_VTR_OP_CASE (POP_2);
1451       STR_VTR_OP_CASE (TRANSLATE_1_1);
1452       STR_VTR_OP_CASE (TRANSLATE_1_2);
1453       STR_VTR_OP_CASE (TRANSLATE_2_1);
1454       STR_VTR_OP_CASE (TRANSLATE_2_2);
1455     }
1456
1457   return "UNKNOWN";
1458 }
1459
1460 static int
1461 dump_sub_interface_table (vat_main_t * vam)
1462 {
1463   const sw_interface_subif_t *sub = NULL;
1464
1465   if (vam->json_output)
1466     {
1467       clib_warning
1468         ("JSON output supported only for VPE API calls and dump_stats_table");
1469       return -99;
1470     }
1471
1472   print (vam->ofp,
1473          "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
1474          "Interface", "sw_if_index",
1475          "sub id", "dot1ad", "tags", "outer id",
1476          "inner id", "exact", "default", "outer any", "inner any");
1477
1478   vec_foreach (sub, vam->sw_if_subif_table)
1479   {
1480     print (vam->ofp,
1481            "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
1482            sub->interface_name,
1483            sub->sw_if_index,
1484            sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
1485            sub->sub_number_of_tags, sub->sub_outer_vlan_id,
1486            sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
1487            sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
1488     if (sub->vtr_op != L2_VTR_DISABLED)
1489       {
1490         print (vam->ofp,
1491                "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
1492                "tag1: %d tag2: %d ]",
1493                str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
1494                sub->vtr_tag1, sub->vtr_tag2);
1495       }
1496   }
1497
1498   return 0;
1499 }
1500
1501 static int
1502 name_sort_cmp (void *a1, void *a2)
1503 {
1504   name_sort_t *n1 = a1;
1505   name_sort_t *n2 = a2;
1506
1507   return strcmp ((char *) n1->name, (char *) n2->name);
1508 }
1509
1510 static int
1511 dump_interface_table (vat_main_t * vam)
1512 {
1513   hash_pair_t *p;
1514   name_sort_t *nses = 0, *ns;
1515
1516   if (vam->json_output)
1517     {
1518       clib_warning
1519         ("JSON output supported only for VPE API calls and dump_stats_table");
1520       return -99;
1521     }
1522
1523   /* *INDENT-OFF* */
1524   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1525   ({
1526     vec_add2 (nses, ns, 1);
1527     ns->name = (u8 *)(p->key);
1528     ns->value = (u32) p->value[0];
1529   }));
1530   /* *INDENT-ON* */
1531
1532   vec_sort_with_function (nses, name_sort_cmp);
1533
1534   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
1535   vec_foreach (ns, nses)
1536   {
1537     print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
1538   }
1539   vec_free (nses);
1540   return 0;
1541 }
1542
1543 /*
1544  * Pass CLI buffers directly in the CLI_INBAND API message,
1545  * instead of an additional shared memory area.
1546  */
1547 static int
1548 exec_inband (vat_main_t * vam)
1549 {
1550   vl_api_cli_inband_t *mp;
1551   unformat_input_t *i = vam->input;
1552   int ret;
1553
1554   if (vec_len (i->buffer) == 0)
1555     return -1;
1556
1557   if (vam->exec_mode == 0 && unformat (i, "mode"))
1558     {
1559       vam->exec_mode = 1;
1560       return 0;
1561     }
1562   if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
1563     {
1564       vam->exec_mode = 0;
1565       return 0;
1566     }
1567
1568   /*
1569    * In order for the CLI command to work, it
1570    * must be a vector ending in \n, not a C-string ending
1571    * in \n\0.
1572    */
1573   M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
1574   vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
1575
1576   S (mp);
1577   W (ret);
1578   /* json responses may or may not include a useful reply... */
1579   if (vec_len (vam->cmd_reply))
1580     print (vam->ofp, "%v", (char *) (vam->cmd_reply));
1581   return ret;
1582 }
1583
1584 int
1585 exec (vat_main_t * vam)
1586 {
1587   return exec_inband (vam);
1588 }
1589
1590 static int
1591 api_create_loopback (vat_main_t * vam)
1592 {
1593   unformat_input_t *i = vam->input;
1594   vl_api_create_loopback_t *mp;
1595   vl_api_create_loopback_instance_t *mp_lbi;
1596   u8 mac_address[6];
1597   u8 mac_set = 0;
1598   u8 is_specified = 0;
1599   u32 user_instance = 0;
1600   int ret;
1601
1602   clib_memset (mac_address, 0, sizeof (mac_address));
1603
1604   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1605     {
1606       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
1607         mac_set = 1;
1608       if (unformat (i, "instance %d", &user_instance))
1609         is_specified = 1;
1610       else
1611         break;
1612     }
1613
1614   if (is_specified)
1615     {
1616       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
1617       mp_lbi->is_specified = is_specified;
1618       if (is_specified)
1619         mp_lbi->user_instance = htonl (user_instance);
1620       if (mac_set)
1621         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
1622       S (mp_lbi);
1623     }
1624   else
1625     {
1626       /* Construct the API message */
1627       M (CREATE_LOOPBACK, mp);
1628       if (mac_set)
1629         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
1630       S (mp);
1631     }
1632
1633   W (ret);
1634   return ret;
1635 }
1636
1637 static int
1638 api_delete_loopback (vat_main_t * vam)
1639 {
1640   unformat_input_t *i = vam->input;
1641   vl_api_delete_loopback_t *mp;
1642   u32 sw_if_index = ~0;
1643   int ret;
1644
1645   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1646     {
1647       if (unformat (i, "sw_if_index %d", &sw_if_index))
1648         ;
1649       else
1650         break;
1651     }
1652
1653   if (sw_if_index == ~0)
1654     {
1655       errmsg ("missing sw_if_index");
1656       return -99;
1657     }
1658
1659   /* Construct the API message */
1660   M (DELETE_LOOPBACK, mp);
1661   mp->sw_if_index = ntohl (sw_if_index);
1662
1663   S (mp);
1664   W (ret);
1665   return ret;
1666 }
1667
1668 static int
1669 api_want_interface_events (vat_main_t * vam)
1670 {
1671   unformat_input_t *i = vam->input;
1672   vl_api_want_interface_events_t *mp;
1673   int enable = -1;
1674   int ret;
1675
1676   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1677     {
1678       if (unformat (i, "enable"))
1679         enable = 1;
1680       else if (unformat (i, "disable"))
1681         enable = 0;
1682       else
1683         break;
1684     }
1685
1686   if (enable == -1)
1687     {
1688       errmsg ("missing enable|disable");
1689       return -99;
1690     }
1691
1692   M (WANT_INTERFACE_EVENTS, mp);
1693   mp->enable_disable = enable;
1694
1695   vam->interface_event_display = enable;
1696
1697   S (mp);
1698   W (ret);
1699   return ret;
1700 }
1701
1702
1703 /* Note: non-static, called once to set up the initial intfc table */
1704 int
1705 api_sw_interface_dump (vat_main_t * vam)
1706 {
1707   vl_api_sw_interface_dump_t *mp;
1708   vl_api_control_ping_t *mp_ping;
1709   hash_pair_t *p;
1710   name_sort_t *nses = 0, *ns;
1711   sw_interface_subif_t *sub = NULL;
1712   int ret;
1713
1714   /* Toss the old name table */
1715   /* *INDENT-OFF* */
1716   hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1717   ({
1718     vec_add2 (nses, ns, 1);
1719     ns->name = (u8 *)(p->key);
1720     ns->value = (u32) p->value[0];
1721   }));
1722   /* *INDENT-ON* */
1723
1724   hash_free (vam->sw_if_index_by_interface_name);
1725
1726   vec_foreach (ns, nses) vec_free (ns->name);
1727
1728   vec_free (nses);
1729
1730   vec_foreach (sub, vam->sw_if_subif_table)
1731   {
1732     vec_free (sub->interface_name);
1733   }
1734   vec_free (vam->sw_if_subif_table);
1735
1736   /* recreate the interface name hash table */
1737   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
1738
1739   /*
1740    * Ask for all interface names. Otherwise, the epic catalog of
1741    * name filters becomes ridiculously long, and vat ends up needing
1742    * to be taught about new interface types.
1743    */
1744   M (SW_INTERFACE_DUMP, mp);
1745   S (mp);
1746
1747   /* Use a control ping for synchronization */
1748   MPING (CONTROL_PING, mp_ping);
1749   S (mp_ping);
1750
1751   W (ret);
1752   return ret;
1753 }
1754
1755 static int
1756 api_sw_interface_set_flags (vat_main_t * vam)
1757 {
1758   unformat_input_t *i = vam->input;
1759   vl_api_sw_interface_set_flags_t *mp;
1760   u32 sw_if_index;
1761   u8 sw_if_index_set = 0;
1762   u8 admin_up = 0;
1763   int ret;
1764
1765   /* Parse args required to build the message */
1766   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1767     {
1768       if (unformat (i, "admin-up"))
1769         admin_up = 1;
1770       else if (unformat (i, "admin-down"))
1771         admin_up = 0;
1772       else
1773         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1774         sw_if_index_set = 1;
1775       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1776         sw_if_index_set = 1;
1777       else
1778         break;
1779     }
1780
1781   if (sw_if_index_set == 0)
1782     {
1783       errmsg ("missing interface name or sw_if_index");
1784       return -99;
1785     }
1786
1787   /* Construct the API message */
1788   M (SW_INTERFACE_SET_FLAGS, mp);
1789   mp->sw_if_index = ntohl (sw_if_index);
1790   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
1791
1792   /* send it... */
1793   S (mp);
1794
1795   /* Wait for a reply, return the good/bad news... */
1796   W (ret);
1797   return ret;
1798 }
1799
1800 static int
1801 api_sw_interface_set_rx_placement (vat_main_t * vam)
1802 {
1803   unformat_input_t *i = vam->input;
1804   vl_api_sw_interface_set_rx_placement_t *mp;
1805   u32 sw_if_index;
1806   u8 sw_if_index_set = 0;
1807   int ret;
1808   u8 is_main = 0;
1809   u32 queue_id, thread_index;
1810
1811   /* Parse args required to build the message */
1812   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1813     {
1814       if (unformat (i, "queue %d", &queue_id))
1815         ;
1816       else if (unformat (i, "main"))
1817         is_main = 1;
1818       else if (unformat (i, "worker %d", &thread_index))
1819         ;
1820       else
1821         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1822         sw_if_index_set = 1;
1823       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1824         sw_if_index_set = 1;
1825       else
1826         break;
1827     }
1828
1829   if (sw_if_index_set == 0)
1830     {
1831       errmsg ("missing interface name or sw_if_index");
1832       return -99;
1833     }
1834
1835   if (is_main)
1836     thread_index = 0;
1837   /* Construct the API message */
1838   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
1839   mp->sw_if_index = ntohl (sw_if_index);
1840   mp->worker_id = ntohl (thread_index);
1841   mp->queue_id = ntohl (queue_id);
1842   mp->is_main = is_main;
1843
1844   /* send it... */
1845   S (mp);
1846   /* Wait for a reply, return the good/bad news... */
1847   W (ret);
1848   return ret;
1849 }
1850
1851 static void vl_api_sw_interface_rx_placement_details_t_handler
1852   (vl_api_sw_interface_rx_placement_details_t * mp)
1853 {
1854   vat_main_t *vam = &vat_main;
1855   u32 worker_id = ntohl (mp->worker_id);
1856
1857   print (vam->ofp,
1858          "\n%-11d %-11s %-6d %-5d %-9s",
1859          ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
1860          worker_id, ntohl (mp->queue_id),
1861          (mp->mode ==
1862           1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
1863 }
1864
1865 static void vl_api_sw_interface_rx_placement_details_t_handler_json
1866   (vl_api_sw_interface_rx_placement_details_t * mp)
1867 {
1868   vat_main_t *vam = &vat_main;
1869   vat_json_node_t *node = NULL;
1870
1871   if (VAT_JSON_ARRAY != vam->json_tree.type)
1872     {
1873       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1874       vat_json_init_array (&vam->json_tree);
1875     }
1876   node = vat_json_array_add (&vam->json_tree);
1877
1878   vat_json_init_object (node);
1879   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1880   vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
1881   vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
1882   vat_json_object_add_uint (node, "mode", mp->mode);
1883 }
1884
1885 static int
1886 api_sw_interface_rx_placement_dump (vat_main_t * vam)
1887 {
1888   unformat_input_t *i = vam->input;
1889   vl_api_sw_interface_rx_placement_dump_t *mp;
1890   vl_api_control_ping_t *mp_ping;
1891   int ret;
1892   u32 sw_if_index;
1893   u8 sw_if_index_set = 0;
1894
1895   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1896     {
1897       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1898         sw_if_index_set++;
1899       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1900         sw_if_index_set++;
1901       else
1902         break;
1903     }
1904
1905   print (vam->ofp,
1906          "\n%-11s %-11s %-6s %-5s %-4s",
1907          "sw_if_index", "main/worker", "thread", "queue", "mode");
1908
1909   /* Dump Interface rx placement */
1910   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
1911
1912   if (sw_if_index_set)
1913     mp->sw_if_index = htonl (sw_if_index);
1914   else
1915     mp->sw_if_index = ~0;
1916
1917   S (mp);
1918
1919   /* Use a control ping for synchronization */
1920   MPING (CONTROL_PING, mp_ping);
1921   S (mp_ping);
1922
1923   W (ret);
1924   return ret;
1925 }
1926
1927 static int
1928 api_sw_interface_clear_stats (vat_main_t * vam)
1929 {
1930   unformat_input_t *i = vam->input;
1931   vl_api_sw_interface_clear_stats_t *mp;
1932   u32 sw_if_index;
1933   u8 sw_if_index_set = 0;
1934   int ret;
1935
1936   /* Parse args required to build the message */
1937   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1938     {
1939       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1940         sw_if_index_set = 1;
1941       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1942         sw_if_index_set = 1;
1943       else
1944         break;
1945     }
1946
1947   /* Construct the API message */
1948   M (SW_INTERFACE_CLEAR_STATS, mp);
1949
1950   if (sw_if_index_set == 1)
1951     mp->sw_if_index = ntohl (sw_if_index);
1952   else
1953     mp->sw_if_index = ~0;
1954
1955   /* send it... */
1956   S (mp);
1957
1958   /* Wait for a reply, return the good/bad news... */
1959   W (ret);
1960   return ret;
1961 }
1962
1963 static int
1964 api_sw_interface_add_del_address (vat_main_t * vam)
1965 {
1966   unformat_input_t *i = vam->input;
1967   vl_api_sw_interface_add_del_address_t *mp;
1968   u32 sw_if_index;
1969   u8 sw_if_index_set = 0;
1970   u8 is_add = 1, del_all = 0;
1971   u32 address_length = 0;
1972   u8 v4_address_set = 0;
1973   u8 v6_address_set = 0;
1974   ip4_address_t v4address;
1975   ip6_address_t v6address;
1976   int ret;
1977
1978   /* Parse args required to build the message */
1979   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1980     {
1981       if (unformat (i, "del-all"))
1982         del_all = 1;
1983       else if (unformat (i, "del"))
1984         is_add = 0;
1985       else
1986         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1987         sw_if_index_set = 1;
1988       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1989         sw_if_index_set = 1;
1990       else if (unformat (i, "%U/%d",
1991                          unformat_ip4_address, &v4address, &address_length))
1992         v4_address_set = 1;
1993       else if (unformat (i, "%U/%d",
1994                          unformat_ip6_address, &v6address, &address_length))
1995         v6_address_set = 1;
1996       else
1997         break;
1998     }
1999
2000   if (sw_if_index_set == 0)
2001     {
2002       errmsg ("missing interface name or sw_if_index");
2003       return -99;
2004     }
2005   if (v4_address_set && v6_address_set)
2006     {
2007       errmsg ("both v4 and v6 addresses set");
2008       return -99;
2009     }
2010   if (!v4_address_set && !v6_address_set && !del_all)
2011     {
2012       errmsg ("no addresses set");
2013       return -99;
2014     }
2015
2016   /* Construct the API message */
2017   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
2018
2019   mp->sw_if_index = ntohl (sw_if_index);
2020   mp->is_add = is_add;
2021   mp->del_all = del_all;
2022   if (v6_address_set)
2023     {
2024       mp->prefix.address.af = ADDRESS_IP6;
2025       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
2026     }
2027   else
2028     {
2029       mp->prefix.address.af = ADDRESS_IP4;
2030       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
2031     }
2032   mp->prefix.len = address_length;
2033
2034   /* send it... */
2035   S (mp);
2036
2037   /* Wait for a reply, return good/bad news  */
2038   W (ret);
2039   return ret;
2040 }
2041
2042 static int
2043 api_sw_interface_set_table (vat_main_t * vam)
2044 {
2045   unformat_input_t *i = vam->input;
2046   vl_api_sw_interface_set_table_t *mp;
2047   u32 sw_if_index, vrf_id = 0;
2048   u8 sw_if_index_set = 0;
2049   u8 is_ipv6 = 0;
2050   int ret;
2051
2052   /* Parse args required to build the message */
2053   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2054     {
2055       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2056         sw_if_index_set = 1;
2057       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2058         sw_if_index_set = 1;
2059       else if (unformat (i, "vrf %d", &vrf_id))
2060         ;
2061       else if (unformat (i, "ipv6"))
2062         is_ipv6 = 1;
2063       else
2064         break;
2065     }
2066
2067   if (sw_if_index_set == 0)
2068     {
2069       errmsg ("missing interface name or sw_if_index");
2070       return -99;
2071     }
2072
2073   /* Construct the API message */
2074   M (SW_INTERFACE_SET_TABLE, mp);
2075
2076   mp->sw_if_index = ntohl (sw_if_index);
2077   mp->is_ipv6 = is_ipv6;
2078   mp->vrf_id = ntohl (vrf_id);
2079
2080   /* send it... */
2081   S (mp);
2082
2083   /* Wait for a reply... */
2084   W (ret);
2085   return ret;
2086 }
2087
2088 static void vl_api_sw_interface_get_table_reply_t_handler
2089   (vl_api_sw_interface_get_table_reply_t * mp)
2090 {
2091   vat_main_t *vam = &vat_main;
2092
2093   print (vam->ofp, "%d", ntohl (mp->vrf_id));
2094
2095   vam->retval = ntohl (mp->retval);
2096   vam->result_ready = 1;
2097
2098 }
2099
2100 static void vl_api_sw_interface_get_table_reply_t_handler_json
2101   (vl_api_sw_interface_get_table_reply_t * mp)
2102 {
2103   vat_main_t *vam = &vat_main;
2104   vat_json_node_t node;
2105
2106   vat_json_init_object (&node);
2107   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2108   vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
2109
2110   vat_json_print (vam->ofp, &node);
2111   vat_json_free (&node);
2112
2113   vam->retval = ntohl (mp->retval);
2114   vam->result_ready = 1;
2115 }
2116
2117 static int
2118 api_sw_interface_get_table (vat_main_t * vam)
2119 {
2120   unformat_input_t *i = vam->input;
2121   vl_api_sw_interface_get_table_t *mp;
2122   u32 sw_if_index;
2123   u8 sw_if_index_set = 0;
2124   u8 is_ipv6 = 0;
2125   int ret;
2126
2127   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2128     {
2129       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2130         sw_if_index_set = 1;
2131       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2132         sw_if_index_set = 1;
2133       else if (unformat (i, "ipv6"))
2134         is_ipv6 = 1;
2135       else
2136         break;
2137     }
2138
2139   if (sw_if_index_set == 0)
2140     {
2141       errmsg ("missing interface name or sw_if_index");
2142       return -99;
2143     }
2144
2145   M (SW_INTERFACE_GET_TABLE, mp);
2146   mp->sw_if_index = htonl (sw_if_index);
2147   mp->is_ipv6 = is_ipv6;
2148
2149   S (mp);
2150   W (ret);
2151   return ret;
2152 }
2153
2154 uword
2155 unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
2156 {
2157   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
2158   u32 x[4];
2159
2160   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
2161     return 0;
2162
2163   addr->domain = x[0];
2164   addr->bus = x[1];
2165   addr->slot = x[2];
2166   addr->function = x[3];
2167
2168   return 1;
2169 }
2170
2171 uword
2172 unformat_fib_path (unformat_input_t *input, va_list *args)
2173 {
2174   vat_main_t *vam = va_arg (*args, vat_main_t *);
2175   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
2176   u32 weight, preference;
2177   mpls_label_t out_label;
2178
2179   clib_memset (path, 0, sizeof (*path));
2180   path->weight = 1;
2181   path->sw_if_index = ~0;
2182   path->rpf_id = ~0;
2183   path->n_labels = 0;
2184
2185   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2186     {
2187       if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
2188                     &path->nh.address.ip4, api_unformat_sw_if_index, vam,
2189                     &path->sw_if_index))
2190         {
2191           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2192         }
2193       else if (unformat (input, "%U %U",
2194                          unformat_vl_api_ip6_address,
2195                          &path->nh.address.ip6,
2196                          api_unformat_sw_if_index, vam, &path->sw_if_index))
2197         {
2198           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2199         }
2200       else if (unformat (input, "weight %u", &weight))
2201         {
2202           path->weight = weight;
2203         }
2204       else if (unformat (input, "preference %u", &preference))
2205         {
2206           path->preference = preference;
2207         }
2208       else if (unformat (input, "%U next-hop-table %d",
2209                          unformat_vl_api_ip4_address,
2210                          &path->nh.address.ip4, &path->table_id))
2211         {
2212           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2213         }
2214       else if (unformat (input, "%U next-hop-table %d",
2215                          unformat_vl_api_ip6_address,
2216                          &path->nh.address.ip6, &path->table_id))
2217         {
2218           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2219         }
2220       else if (unformat (input, "%U",
2221                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
2222         {
2223           /*
2224            * the recursive next-hops are by default in the default table
2225            */
2226           path->table_id = 0;
2227           path->sw_if_index = ~0;
2228           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2229         }
2230       else if (unformat (input, "%U",
2231                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
2232         {
2233           /*
2234            * the recursive next-hops are by default in the default table
2235            */
2236           path->table_id = 0;
2237           path->sw_if_index = ~0;
2238           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2239         }
2240       else if (unformat (input, "resolve-via-host"))
2241         {
2242           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
2243         }
2244       else if (unformat (input, "resolve-via-attached"))
2245         {
2246           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
2247         }
2248       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
2249         {
2250           path->type = FIB_API_PATH_TYPE_LOCAL;
2251           path->sw_if_index = ~0;
2252           path->proto = FIB_API_PATH_NH_PROTO_IP4;
2253         }
2254       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
2255         {
2256           path->type = FIB_API_PATH_TYPE_LOCAL;
2257           path->sw_if_index = ~0;
2258           path->proto = FIB_API_PATH_NH_PROTO_IP6;
2259         }
2260       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
2261         ;
2262       else if (unformat (input, "via-label %d", &path->nh.via_label))
2263         {
2264           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
2265           path->sw_if_index = ~0;
2266         }
2267       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
2268         {
2269           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
2270           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
2271         }
2272       else if (unformat (input, "local"))
2273         {
2274           path->type = FIB_API_PATH_TYPE_LOCAL;
2275         }
2276       else if (unformat (input, "out-labels"))
2277         {
2278           while (unformat (input, "%d", &out_label))
2279             {
2280               path->label_stack[path->n_labels].label = out_label;
2281               path->label_stack[path->n_labels].is_uniform = 0;
2282               path->label_stack[path->n_labels].ttl = 64;
2283               path->n_labels++;
2284             }
2285         }
2286       else if (unformat (input, "via"))
2287         {
2288           /* new path, back up and return */
2289           unformat_put_input (input);
2290           unformat_put_input (input);
2291           unformat_put_input (input);
2292           unformat_put_input (input);
2293           break;
2294         }
2295       else
2296         {
2297           return (0);
2298         }
2299     }
2300
2301   path->proto = ntohl (path->proto);
2302   path->type = ntohl (path->type);
2303   path->flags = ntohl (path->flags);
2304   path->table_id = ntohl (path->table_id);
2305   path->sw_if_index = ntohl (path->sw_if_index);
2306
2307   return (1);
2308 }
2309
2310 static int
2311 api_sw_interface_set_unnumbered (vat_main_t *vam)
2312 {
2313   unformat_input_t *i = vam->input;
2314   vl_api_sw_interface_set_unnumbered_t *mp;
2315   u32 sw_if_index;
2316   u32 unnum_sw_index = ~0;
2317   u8 is_add = 1;
2318   u8 sw_if_index_set = 0;
2319   int ret;
2320
2321   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2322     {
2323       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2324         sw_if_index_set = 1;
2325       else if (unformat (i, "sw_if_index %d", &sw_if_index))
2326         sw_if_index_set = 1;
2327       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
2328         ;
2329       else if (unformat (i, "del"))
2330         is_add = 0;
2331       else
2332         {
2333           clib_warning ("parse error '%U'", format_unformat_error, i);
2334           return -99;
2335         }
2336     }
2337
2338   if (sw_if_index_set == 0)
2339     {
2340       errmsg ("missing interface name or sw_if_index");
2341       return -99;
2342     }
2343
2344   M (SW_INTERFACE_SET_UNNUMBERED, mp);
2345
2346   mp->sw_if_index = ntohl (sw_if_index);
2347   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
2348   mp->is_add = is_add;
2349
2350   S (mp);
2351   W (ret);
2352   return ret;
2353 }
2354
2355 static int
2356 api_create_vlan_subif (vat_main_t *vam)
2357 {
2358   unformat_input_t *i = vam->input;
2359   vl_api_create_vlan_subif_t *mp;
2360   u32 sw_if_index;
2361   u8 sw_if_index_set = 0;
2362   u32 vlan_id;
2363   u8 vlan_id_set = 0;
2364   int ret;
2365
2366   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2367     {
2368       if (unformat (i, "sw_if_index %d", &sw_if_index))
2369         sw_if_index_set = 1;
2370       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2371         sw_if_index_set = 1;
2372       else if (unformat (i, "vlan %d", &vlan_id))
2373         vlan_id_set = 1;
2374       else
2375         {
2376           clib_warning ("parse error '%U'", format_unformat_error, i);
2377           return -99;
2378         }
2379     }
2380
2381   if (sw_if_index_set == 0)
2382     {
2383       errmsg ("missing interface name or sw_if_index");
2384       return -99;
2385     }
2386
2387   if (vlan_id_set == 0)
2388     {
2389       errmsg ("missing vlan_id");
2390       return -99;
2391     }
2392   M (CREATE_VLAN_SUBIF, mp);
2393
2394   mp->sw_if_index = ntohl (sw_if_index);
2395   mp->vlan_id = ntohl (vlan_id);
2396
2397   S (mp);
2398   W (ret);
2399   return ret;
2400 }
2401
2402 #define foreach_create_subif_bit                \
2403 _(no_tags)                                      \
2404 _(one_tag)                                      \
2405 _(two_tags)                                     \
2406 _(dot1ad)                                       \
2407 _(exact_match)                                  \
2408 _(default_sub)                                  \
2409 _(outer_vlan_id_any)                            \
2410 _(inner_vlan_id_any)
2411
2412 #define foreach_create_subif_flag               \
2413 _(0, "no_tags")                                 \
2414 _(1, "one_tag")                                 \
2415 _(2, "two_tags")                                \
2416 _(3, "dot1ad")                                  \
2417 _(4, "exact_match")                             \
2418 _(5, "default_sub")                             \
2419 _(6, "outer_vlan_id_any")                       \
2420 _(7, "inner_vlan_id_any")
2421
2422 static int
2423 api_create_subif (vat_main_t * vam)
2424 {
2425   unformat_input_t *i = vam->input;
2426   vl_api_create_subif_t *mp;
2427   u32 sw_if_index;
2428   u8 sw_if_index_set = 0;
2429   u32 sub_id;
2430   u8 sub_id_set = 0;
2431   u32 __attribute__ ((unused)) no_tags = 0;
2432   u32 __attribute__ ((unused)) one_tag = 0;
2433   u32 __attribute__ ((unused)) two_tags = 0;
2434   u32 __attribute__ ((unused)) dot1ad = 0;
2435   u32 __attribute__ ((unused)) exact_match = 0;
2436   u32 __attribute__ ((unused)) default_sub = 0;
2437   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
2438   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
2439   u32 tmp;
2440   u16 outer_vlan_id = 0;
2441   u16 inner_vlan_id = 0;
2442   int ret;
2443
2444   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2445     {
2446       if (unformat (i, "sw_if_index %d", &sw_if_index))
2447         sw_if_index_set = 1;
2448       else
2449         if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2450         sw_if_index_set = 1;
2451       else if (unformat (i, "sub_id %d", &sub_id))
2452         sub_id_set = 1;
2453       else if (unformat (i, "outer_vlan_id %d", &tmp))
2454         outer_vlan_id = tmp;
2455       else if (unformat (i, "inner_vlan_id %d", &tmp))
2456         inner_vlan_id = tmp;
2457
2458 #define _(a) else if (unformat (i, #a)) a = 1 ;
2459       foreach_create_subif_bit
2460 #undef _
2461         else
2462         {
2463           clib_warning ("parse error '%U'", format_unformat_error, i);
2464           return -99;
2465         }
2466     }
2467
2468   if (sw_if_index_set == 0)
2469     {
2470       errmsg ("missing interface name or sw_if_index");
2471       return -99;
2472     }
2473
2474   if (sub_id_set == 0)
2475     {
2476       errmsg ("missing sub_id");
2477       return -99;
2478     }
2479   M (CREATE_SUBIF, mp);
2480
2481   mp->sw_if_index = ntohl (sw_if_index);
2482   mp->sub_id = ntohl (sub_id);
2483
2484 #define _(a,b) mp->sub_if_flags |= (1 << a);
2485   foreach_create_subif_flag;
2486 #undef _
2487
2488   mp->outer_vlan_id = ntohs (outer_vlan_id);
2489   mp->inner_vlan_id = ntohs (inner_vlan_id);
2490
2491   S (mp);
2492   W (ret);
2493   return ret;
2494 }
2495
2496 u8 is_del;
2497 u8 localsid_addr[16];
2498 u8 end_psp;
2499 u8 behavior;
2500 u32 sw_if_index;
2501 u32 vlan_index;
2502 u32 fib_table;
2503 u8 nh_addr[16];
2504
2505 #define foreach_tcp_proto_field                                               \
2506   _ (src_port)                                                                \
2507   _ (dst_port)
2508
2509 #define foreach_udp_proto_field                                               \
2510   _ (src_port)                                                                \
2511   _ (dst_port)
2512
2513 #define foreach_ip4_proto_field                                               \
2514   _ (src_address)                                                             \
2515   _ (dst_address)                                                             \
2516   _ (tos)                                                                     \
2517   _ (length)                                                                  \
2518   _ (fragment_id)                                                             \
2519   _ (ttl)                                                                     \
2520   _ (protocol)                                                                \
2521   _ (checksum)
2522
2523 typedef struct
2524 {
2525   u16 src_port, dst_port;
2526 } tcpudp_header_t;
2527
2528 #if VPP_API_TEST_BUILTIN == 0
2529 uword
2530 unformat_tcp_mask (unformat_input_t *input, va_list *args)
2531 {
2532   u8 **maskp = va_arg (*args, u8 **);
2533   u8 *mask = 0;
2534   u8 found_something = 0;
2535   tcp_header_t *tcp;
2536
2537 #define _(a) u8 a = 0;
2538   foreach_tcp_proto_field;
2539 #undef _
2540
2541   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2542     {
2543       if (0)
2544         ;
2545 #define _(a) else if (unformat (input, #a)) a = 1;
2546       foreach_tcp_proto_field
2547 #undef _
2548         else break;
2549     }
2550
2551 #define _(a) found_something += a;
2552   foreach_tcp_proto_field;
2553 #undef _
2554
2555   if (found_something == 0)
2556     return 0;
2557
2558   vec_validate (mask, sizeof (*tcp) - 1);
2559
2560   tcp = (tcp_header_t *) mask;
2561
2562 #define _(a)                                                                  \
2563   if (a)                                                                      \
2564     clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
2565   foreach_tcp_proto_field;
2566 #undef _
2567
2568   *maskp = mask;
2569   return 1;
2570 }
2571
2572 uword
2573 unformat_udp_mask (unformat_input_t *input, va_list *args)
2574 {
2575   u8 **maskp = va_arg (*args, u8 **);
2576   u8 *mask = 0;
2577   u8 found_something = 0;
2578   udp_header_t *udp;
2579
2580 #define _(a) u8 a = 0;
2581   foreach_udp_proto_field;
2582 #undef _
2583
2584   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2585     {
2586       if (0)
2587         ;
2588 #define _(a) else if (unformat (input, #a)) a = 1;
2589       foreach_udp_proto_field
2590 #undef _
2591         else break;
2592     }
2593
2594 #define _(a) found_something += a;
2595   foreach_udp_proto_field;
2596 #undef _
2597
2598   if (found_something == 0)
2599     return 0;
2600
2601   vec_validate (mask, sizeof (*udp) - 1);
2602
2603   udp = (udp_header_t *) mask;
2604
2605 #define _(a)                                                                  \
2606   if (a)                                                                      \
2607     clib_memset (&udp->a, 0xff, sizeof (udp->a));
2608   foreach_udp_proto_field;
2609 #undef _
2610
2611   *maskp = mask;
2612   return 1;
2613 }
2614
2615 uword
2616 unformat_l4_mask (unformat_input_t *input, va_list *args)
2617 {
2618   u8 **maskp = va_arg (*args, u8 **);
2619   u16 src_port = 0, dst_port = 0;
2620   tcpudp_header_t *tcpudp;
2621
2622   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2623     {
2624       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
2625         return 1;
2626       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
2627         return 1;
2628       else if (unformat (input, "src_port"))
2629         src_port = 0xFFFF;
2630       else if (unformat (input, "dst_port"))
2631         dst_port = 0xFFFF;
2632       else
2633         return 0;
2634     }
2635
2636   if (!src_port && !dst_port)
2637     return 0;
2638
2639   u8 *mask = 0;
2640   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
2641
2642   tcpudp = (tcpudp_header_t *) mask;
2643   tcpudp->src_port = src_port;
2644   tcpudp->dst_port = dst_port;
2645
2646   *maskp = mask;
2647
2648   return 1;
2649 }
2650
2651 uword
2652 unformat_ip4_mask (unformat_input_t * input, va_list * args)
2653 {
2654   u8 **maskp = va_arg (*args, u8 **);
2655   u8 *mask = 0;
2656   u8 found_something = 0;
2657   ip4_header_t *ip;
2658
2659 #define _(a) u8 a=0;
2660   foreach_ip4_proto_field;
2661 #undef _
2662   u8 version = 0;
2663   u8 hdr_length = 0;
2664
2665
2666   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2667     {
2668       if (unformat (input, "version"))
2669         version = 1;
2670       else if (unformat (input, "hdr_length"))
2671         hdr_length = 1;
2672       else if (unformat (input, "src"))
2673         src_address = 1;
2674       else if (unformat (input, "dst"))
2675         dst_address = 1;
2676       else if (unformat (input, "proto"))
2677         protocol = 1;
2678
2679 #define _(a) else if (unformat (input, #a)) a=1;
2680       foreach_ip4_proto_field
2681 #undef _
2682         else
2683         break;
2684     }
2685
2686 #define _(a) found_something += a;
2687   foreach_ip4_proto_field;
2688 #undef _
2689
2690   if (found_something == 0)
2691     return 0;
2692
2693   vec_validate (mask, sizeof (*ip) - 1);
2694
2695   ip = (ip4_header_t *) mask;
2696
2697 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
2698   foreach_ip4_proto_field;
2699 #undef _
2700
2701   ip->ip_version_and_header_length = 0;
2702
2703   if (version)
2704     ip->ip_version_and_header_length |= 0xF0;
2705
2706   if (hdr_length)
2707     ip->ip_version_and_header_length |= 0x0F;
2708
2709   *maskp = mask;
2710   return 1;
2711 }
2712
2713 #define foreach_ip6_proto_field                 \
2714 _(src_address)                                  \
2715 _(dst_address)                                  \
2716 _(payload_length)                               \
2717 _(hop_limit)                                    \
2718 _(protocol)
2719
2720 uword
2721 unformat_ip6_mask (unformat_input_t * input, va_list * args)
2722 {
2723   u8 **maskp = va_arg (*args, u8 **);
2724   u8 *mask = 0;
2725   u8 found_something = 0;
2726   ip6_header_t *ip;
2727   u32 ip_version_traffic_class_and_flow_label;
2728
2729 #define _(a) u8 a=0;
2730   foreach_ip6_proto_field;
2731 #undef _
2732   u8 version = 0;
2733   u8 traffic_class = 0;
2734   u8 flow_label = 0;
2735
2736   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2737     {
2738       if (unformat (input, "version"))
2739         version = 1;
2740       else if (unformat (input, "traffic-class"))
2741         traffic_class = 1;
2742       else if (unformat (input, "flow-label"))
2743         flow_label = 1;
2744       else if (unformat (input, "src"))
2745         src_address = 1;
2746       else if (unformat (input, "dst"))
2747         dst_address = 1;
2748       else if (unformat (input, "proto"))
2749         protocol = 1;
2750
2751 #define _(a) else if (unformat (input, #a)) a=1;
2752       foreach_ip6_proto_field
2753 #undef _
2754         else
2755         break;
2756     }
2757
2758 #define _(a) found_something += a;
2759   foreach_ip6_proto_field;
2760 #undef _
2761
2762   if (found_something == 0)
2763     return 0;
2764
2765   vec_validate (mask, sizeof (*ip) - 1);
2766
2767   ip = (ip6_header_t *) mask;
2768
2769 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
2770   foreach_ip6_proto_field;
2771 #undef _
2772
2773   ip_version_traffic_class_and_flow_label = 0;
2774
2775   if (version)
2776     ip_version_traffic_class_and_flow_label |= 0xF0000000;
2777
2778   if (traffic_class)
2779     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
2780
2781   if (flow_label)
2782     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
2783
2784   ip->ip_version_traffic_class_and_flow_label =
2785     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
2786
2787   *maskp = mask;
2788   return 1;
2789 }
2790
2791 uword
2792 unformat_l3_mask (unformat_input_t * input, va_list * args)
2793 {
2794   u8 **maskp = va_arg (*args, u8 **);
2795
2796   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2797     {
2798       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
2799         return 1;
2800       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
2801         return 1;
2802       else
2803         break;
2804     }
2805   return 0;
2806 }
2807
2808 uword
2809 unformat_l2_mask (unformat_input_t * input, va_list * args)
2810 {
2811   u8 **maskp = va_arg (*args, u8 **);
2812   u8 *mask = 0;
2813   u8 src = 0;
2814   u8 dst = 0;
2815   u8 proto = 0;
2816   u8 tag1 = 0;
2817   u8 tag2 = 0;
2818   u8 ignore_tag1 = 0;
2819   u8 ignore_tag2 = 0;
2820   u8 cos1 = 0;
2821   u8 cos2 = 0;
2822   u8 dot1q = 0;
2823   u8 dot1ad = 0;
2824   int len = 14;
2825
2826   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2827     {
2828       if (unformat (input, "src"))
2829         src = 1;
2830       else if (unformat (input, "dst"))
2831         dst = 1;
2832       else if (unformat (input, "proto"))
2833         proto = 1;
2834       else if (unformat (input, "tag1"))
2835         tag1 = 1;
2836       else if (unformat (input, "tag2"))
2837         tag2 = 1;
2838       else if (unformat (input, "ignore-tag1"))
2839         ignore_tag1 = 1;
2840       else if (unformat (input, "ignore-tag2"))
2841         ignore_tag2 = 1;
2842       else if (unformat (input, "cos1"))
2843         cos1 = 1;
2844       else if (unformat (input, "cos2"))
2845         cos2 = 1;
2846       else if (unformat (input, "dot1q"))
2847         dot1q = 1;
2848       else if (unformat (input, "dot1ad"))
2849         dot1ad = 1;
2850       else
2851         break;
2852     }
2853   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
2854        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
2855     return 0;
2856
2857   if (tag1 || ignore_tag1 || cos1 || dot1q)
2858     len = 18;
2859   if (tag2 || ignore_tag2 || cos2 || dot1ad)
2860     len = 22;
2861
2862   vec_validate (mask, len - 1);
2863
2864   if (dst)
2865     clib_memset (mask, 0xff, 6);
2866
2867   if (src)
2868     clib_memset (mask + 6, 0xff, 6);
2869
2870   if (tag2 || dot1ad)
2871     {
2872       /* inner vlan tag */
2873       if (tag2)
2874         {
2875           mask[19] = 0xff;
2876           mask[18] = 0x0f;
2877         }
2878       if (cos2)
2879         mask[18] |= 0xe0;
2880       if (proto)
2881         mask[21] = mask[20] = 0xff;
2882       if (tag1)
2883         {
2884           mask[15] = 0xff;
2885           mask[14] = 0x0f;
2886         }
2887       if (cos1)
2888         mask[14] |= 0xe0;
2889       *maskp = mask;
2890       return 1;
2891     }
2892   if (tag1 | dot1q)
2893     {
2894       if (tag1)
2895         {
2896           mask[15] = 0xff;
2897           mask[14] = 0x0f;
2898         }
2899       if (cos1)
2900         mask[14] |= 0xe0;
2901       if (proto)
2902         mask[16] = mask[17] = 0xff;
2903
2904       *maskp = mask;
2905       return 1;
2906     }
2907   if (cos2)
2908     mask[18] |= 0xe0;
2909   if (cos1)
2910     mask[14] |= 0xe0;
2911   if (proto)
2912     mask[12] = mask[13] = 0xff;
2913
2914   *maskp = mask;
2915   return 1;
2916 }
2917
2918 uword
2919 unformat_classify_mask (unformat_input_t * input, va_list * args)
2920 {
2921   u8 **maskp = va_arg (*args, u8 **);
2922   u32 *skipp = va_arg (*args, u32 *);
2923   u32 *matchp = va_arg (*args, u32 *);
2924   u32 match;
2925   u8 *mask = 0;
2926   u8 *l2 = 0;
2927   u8 *l3 = 0;
2928   u8 *l4 = 0;
2929   int i;
2930
2931   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2932     {
2933       if (unformat (input, "hex %U", unformat_hex_string, &mask))
2934         ;
2935       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
2936         ;
2937       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
2938         ;
2939       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
2940         ;
2941       else
2942         break;
2943     }
2944
2945   if (l4 && !l3)
2946     {
2947       vec_free (mask);
2948       vec_free (l2);
2949       vec_free (l4);
2950       return 0;
2951     }
2952
2953   if (mask || l2 || l3 || l4)
2954     {
2955       if (l2 || l3 || l4)
2956         {
2957           /* "With a free Ethernet header in every package" */
2958           if (l2 == 0)
2959             vec_validate (l2, 13);
2960           mask = l2;
2961           if (vec_len (l3))
2962             {
2963               vec_append (mask, l3);
2964               vec_free (l3);
2965             }
2966           if (vec_len (l4))
2967             {
2968               vec_append (mask, l4);
2969               vec_free (l4);
2970             }
2971         }
2972
2973       /* Scan forward looking for the first significant mask octet */
2974       for (i = 0; i < vec_len (mask); i++)
2975         if (mask[i])
2976           break;
2977
2978       /* compute (skip, match) params */
2979       *skipp = i / sizeof (u32x4);
2980       vec_delete (mask, *skipp * sizeof (u32x4), 0);
2981
2982       /* Pad mask to an even multiple of the vector size */
2983       while (vec_len (mask) % sizeof (u32x4))
2984         vec_add1 (mask, 0);
2985
2986       match = vec_len (mask) / sizeof (u32x4);
2987
2988       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
2989         {
2990           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
2991           if (*tmp || *(tmp + 1))
2992             break;
2993           match--;
2994         }
2995       if (match == 0)
2996         clib_warning ("BUG: match 0");
2997
2998       _vec_len (mask) = match * sizeof (u32x4);
2999
3000       *matchp = match;
3001       *maskp = mask;
3002
3003       return 1;
3004     }
3005
3006   return 0;
3007 }
3008 #endif /* VPP_API_TEST_BUILTIN */
3009
3010 #define foreach_l2_next                         \
3011 _(drop, DROP)                                   \
3012 _(ethernet, ETHERNET_INPUT)                     \
3013 _(ip4, IP4_INPUT)                               \
3014 _(ip6, IP6_INPUT)
3015
3016 uword
3017 unformat_l2_next_index (unformat_input_t * input, va_list * args)
3018 {
3019   u32 *miss_next_indexp = va_arg (*args, u32 *);
3020   u32 next_index = 0;
3021   u32 tmp;
3022
3023 #define _(n,N) \
3024   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
3025   foreach_l2_next;
3026 #undef _
3027
3028   if (unformat (input, "%d", &tmp))
3029     {
3030       next_index = tmp;
3031       goto out;
3032     }
3033
3034   return 0;
3035
3036 out:
3037   *miss_next_indexp = next_index;
3038   return 1;
3039 }
3040
3041 #define foreach_ip_next                         \
3042 _(drop, DROP)                                   \
3043 _(local, LOCAL)                                 \
3044 _(rewrite, REWRITE)
3045
3046 uword
3047 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
3048 {
3049   u32 *miss_next_indexp = va_arg (*args, u32 *);
3050   u32 next_index = 0;
3051   u32 tmp;
3052
3053 #define _(n,N) \
3054   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
3055   foreach_ip_next;
3056 #undef _
3057
3058   if (unformat (input, "%d", &tmp))
3059     {
3060       next_index = tmp;
3061       goto out;
3062     }
3063
3064   return 0;
3065
3066 out:
3067   *miss_next_indexp = next_index;
3068   return 1;
3069 }
3070
3071 #define foreach_acl_next                        \
3072 _(deny, DENY)
3073
3074 uword
3075 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
3076 {
3077   u32 *miss_next_indexp = va_arg (*args, u32 *);
3078   u32 next_index = 0;
3079   u32 tmp;
3080
3081 #define _(n,N) \
3082   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
3083   foreach_acl_next;
3084 #undef _
3085
3086   if (unformat (input, "permit"))
3087     {
3088       next_index = ~0;
3089       goto out;
3090     }
3091   else if (unformat (input, "%d", &tmp))
3092     {
3093       next_index = tmp;
3094       goto out;
3095     }
3096
3097   return 0;
3098
3099 out:
3100   *miss_next_indexp = next_index;
3101   return 1;
3102 }
3103
3104 uword
3105 unformat_policer_precolor (unformat_input_t * input, va_list * args)
3106 {
3107   u32 *r = va_arg (*args, u32 *);
3108
3109   if (unformat (input, "conform-color"))
3110     *r = POLICE_CONFORM;
3111   else if (unformat (input, "exceed-color"))
3112     *r = POLICE_EXCEED;
3113   else
3114     return 0;
3115
3116   return 1;
3117 }
3118
3119 #if VPP_API_TEST_BUILTIN == 0
3120 uword
3121 unformat_l4_match (unformat_input_t * input, va_list * args)
3122 {
3123   u8 **matchp = va_arg (*args, u8 **);
3124
3125   u8 *proto_header = 0;
3126   int src_port = 0;
3127   int dst_port = 0;
3128
3129   tcpudp_header_t h;
3130
3131   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3132     {
3133       if (unformat (input, "src_port %d", &src_port))
3134         ;
3135       else if (unformat (input, "dst_port %d", &dst_port))
3136         ;
3137       else
3138         return 0;
3139     }
3140
3141   h.src_port = clib_host_to_net_u16 (src_port);
3142   h.dst_port = clib_host_to_net_u16 (dst_port);
3143   vec_validate (proto_header, sizeof (h) - 1);
3144   memcpy (proto_header, &h, sizeof (h));
3145
3146   *matchp = proto_header;
3147
3148   return 1;
3149 }
3150
3151 uword
3152 unformat_ip4_match (unformat_input_t * input, va_list * args)
3153 {
3154   u8 **matchp = va_arg (*args, u8 **);
3155   u8 *match = 0;
3156   ip4_header_t *ip;
3157   int version = 0;
3158   u32 version_val;
3159   int hdr_length = 0;
3160   u32 hdr_length_val;
3161   int src = 0, dst = 0;
3162   ip4_address_t src_val, dst_val;
3163   int proto = 0;
3164   u32 proto_val;
3165   int tos = 0;
3166   u32 tos_val;
3167   int length = 0;
3168   u32 length_val;
3169   int fragment_id = 0;
3170   u32 fragment_id_val;
3171   int ttl = 0;
3172   int ttl_val;
3173   int checksum = 0;
3174   u32 checksum_val;
3175
3176   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3177     {
3178       if (unformat (input, "version %d", &version_val))
3179         version = 1;
3180       else if (unformat (input, "hdr_length %d", &hdr_length_val))
3181         hdr_length = 1;
3182       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
3183         src = 1;
3184       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
3185         dst = 1;
3186       else if (unformat (input, "proto %d", &proto_val))
3187         proto = 1;
3188       else if (unformat (input, "tos %d", &tos_val))
3189         tos = 1;
3190       else if (unformat (input, "length %d", &length_val))
3191         length = 1;
3192       else if (unformat (input, "fragment_id %d", &fragment_id_val))
3193         fragment_id = 1;
3194       else if (unformat (input, "ttl %d", &ttl_val))
3195         ttl = 1;
3196       else if (unformat (input, "checksum %d", &checksum_val))
3197         checksum = 1;
3198       else
3199         break;
3200     }
3201
3202   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
3203       + ttl + checksum == 0)
3204     return 0;
3205
3206   /*
3207    * Aligned because we use the real comparison functions
3208    */
3209   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
3210
3211   ip = (ip4_header_t *) match;
3212
3213   /* These are realistically matched in practice */
3214   if (src)
3215     ip->src_address.as_u32 = src_val.as_u32;
3216
3217   if (dst)
3218     ip->dst_address.as_u32 = dst_val.as_u32;
3219
3220   if (proto)
3221     ip->protocol = proto_val;
3222
3223
3224   /* These are not, but they're included for completeness */
3225   if (version)
3226     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
3227
3228   if (hdr_length)
3229     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
3230
3231   if (tos)
3232     ip->tos = tos_val;
3233
3234   if (length)
3235     ip->length = clib_host_to_net_u16 (length_val);
3236
3237   if (ttl)
3238     ip->ttl = ttl_val;
3239
3240   if (checksum)
3241     ip->checksum = clib_host_to_net_u16 (checksum_val);
3242
3243   *matchp = match;
3244   return 1;
3245 }
3246
3247 uword
3248 unformat_ip6_match (unformat_input_t * input, va_list * args)
3249 {
3250   u8 **matchp = va_arg (*args, u8 **);
3251   u8 *match = 0;
3252   ip6_header_t *ip;
3253   int version = 0;
3254   u32 version_val;
3255   u8 traffic_class = 0;
3256   u32 traffic_class_val = 0;
3257   u8 flow_label = 0;
3258   u8 flow_label_val;
3259   int src = 0, dst = 0;
3260   ip6_address_t src_val, dst_val;
3261   int proto = 0;
3262   u32 proto_val;
3263   int payload_length = 0;
3264   u32 payload_length_val;
3265   int hop_limit = 0;
3266   int hop_limit_val;
3267   u32 ip_version_traffic_class_and_flow_label;
3268
3269   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3270     {
3271       if (unformat (input, "version %d", &version_val))
3272         version = 1;
3273       else if (unformat (input, "traffic_class %d", &traffic_class_val))
3274         traffic_class = 1;
3275       else if (unformat (input, "flow_label %d", &flow_label_val))
3276         flow_label = 1;
3277       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
3278         src = 1;
3279       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
3280         dst = 1;
3281       else if (unformat (input, "proto %d", &proto_val))
3282         proto = 1;
3283       else if (unformat (input, "payload_length %d", &payload_length_val))
3284         payload_length = 1;
3285       else if (unformat (input, "hop_limit %d", &hop_limit_val))
3286         hop_limit = 1;
3287       else
3288         break;
3289     }
3290
3291   if (version + traffic_class + flow_label + src + dst + proto +
3292       payload_length + hop_limit == 0)
3293     return 0;
3294
3295   /*
3296    * Aligned because we use the real comparison functions
3297    */
3298   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
3299
3300   ip = (ip6_header_t *) match;
3301
3302   if (src)
3303     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
3304
3305   if (dst)
3306     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
3307
3308   if (proto)
3309     ip->protocol = proto_val;
3310
3311   ip_version_traffic_class_and_flow_label = 0;
3312
3313   if (version)
3314     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
3315
3316   if (traffic_class)
3317     ip_version_traffic_class_and_flow_label |=
3318       (traffic_class_val & 0xFF) << 20;
3319
3320   if (flow_label)
3321     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
3322
3323   ip->ip_version_traffic_class_and_flow_label =
3324     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
3325
3326   if (payload_length)
3327     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
3328
3329   if (hop_limit)
3330     ip->hop_limit = hop_limit_val;
3331
3332   *matchp = match;
3333   return 1;
3334 }
3335
3336 uword
3337 unformat_l3_match (unformat_input_t * input, va_list * args)
3338 {
3339   u8 **matchp = va_arg (*args, u8 **);
3340
3341   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3342     {
3343       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
3344         return 1;
3345       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
3346         return 1;
3347       else
3348         break;
3349     }
3350   return 0;
3351 }
3352
3353 uword
3354 unformat_vlan_tag (unformat_input_t * input, va_list * args)
3355 {
3356   u8 *tagp = va_arg (*args, u8 *);
3357   u32 tag;
3358
3359   if (unformat (input, "%d", &tag))
3360     {
3361       tagp[0] = (tag >> 8) & 0x0F;
3362       tagp[1] = tag & 0xFF;
3363       return 1;
3364     }
3365
3366   return 0;
3367 }
3368
3369 uword
3370 unformat_l2_match (unformat_input_t * input, va_list * args)
3371 {
3372   u8 **matchp = va_arg (*args, u8 **);
3373   u8 *match = 0;
3374   u8 src = 0;
3375   u8 src_val[6];
3376   u8 dst = 0;
3377   u8 dst_val[6];
3378   u8 proto = 0;
3379   u16 proto_val;
3380   u8 tag1 = 0;
3381   u8 tag1_val[2];
3382   u8 tag2 = 0;
3383   u8 tag2_val[2];
3384   int len = 14;
3385   u8 ignore_tag1 = 0;
3386   u8 ignore_tag2 = 0;
3387   u8 cos1 = 0;
3388   u8 cos2 = 0;
3389   u32 cos1_val = 0;
3390   u32 cos2_val = 0;
3391
3392   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3393     {
3394       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
3395         src = 1;
3396       else
3397         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
3398         dst = 1;
3399       else if (unformat (input, "proto %U",
3400                          unformat_ethernet_type_host_byte_order, &proto_val))
3401         proto = 1;
3402       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
3403         tag1 = 1;
3404       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
3405         tag2 = 1;
3406       else if (unformat (input, "ignore-tag1"))
3407         ignore_tag1 = 1;
3408       else if (unformat (input, "ignore-tag2"))
3409         ignore_tag2 = 1;
3410       else if (unformat (input, "cos1 %d", &cos1_val))
3411         cos1 = 1;
3412       else if (unformat (input, "cos2 %d", &cos2_val))
3413         cos2 = 1;
3414       else
3415         break;
3416     }
3417   if ((src + dst + proto + tag1 + tag2 +
3418        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
3419     return 0;
3420
3421   if (tag1 || ignore_tag1 || cos1)
3422     len = 18;
3423   if (tag2 || ignore_tag2 || cos2)
3424     len = 22;
3425
3426   vec_validate_aligned (match, len - 1, sizeof (u32x4));
3427
3428   if (dst)
3429     clib_memcpy (match, dst_val, 6);
3430
3431   if (src)
3432     clib_memcpy (match + 6, src_val, 6);
3433
3434   if (tag2)
3435     {
3436       /* inner vlan tag */
3437       match[19] = tag2_val[1];
3438       match[18] = tag2_val[0];
3439       if (cos2)
3440         match[18] |= (cos2_val & 0x7) << 5;
3441       if (proto)
3442         {
3443           match[21] = proto_val & 0xff;
3444           match[20] = proto_val >> 8;
3445         }
3446       if (tag1)
3447         {
3448           match[15] = tag1_val[1];
3449           match[14] = tag1_val[0];
3450         }
3451       if (cos1)
3452         match[14] |= (cos1_val & 0x7) << 5;
3453       *matchp = match;
3454       return 1;
3455     }
3456   if (tag1)
3457     {
3458       match[15] = tag1_val[1];
3459       match[14] = tag1_val[0];
3460       if (proto)
3461         {
3462           match[17] = proto_val & 0xff;
3463           match[16] = proto_val >> 8;
3464         }
3465       if (cos1)
3466         match[14] |= (cos1_val & 0x7) << 5;
3467
3468       *matchp = match;
3469       return 1;
3470     }
3471   if (cos2)
3472     match[18] |= (cos2_val & 0x7) << 5;
3473   if (cos1)
3474     match[14] |= (cos1_val & 0x7) << 5;
3475   if (proto)
3476     {
3477       match[13] = proto_val & 0xff;
3478       match[12] = proto_val >> 8;
3479     }
3480
3481   *matchp = match;
3482   return 1;
3483 }
3484
3485 uword
3486 unformat_qos_source (unformat_input_t * input, va_list * args)
3487 {
3488   int *qs = va_arg (*args, int *);
3489
3490   if (unformat (input, "ip"))
3491     *qs = QOS_SOURCE_IP;
3492   else if (unformat (input, "mpls"))
3493     *qs = QOS_SOURCE_MPLS;
3494   else if (unformat (input, "ext"))
3495     *qs = QOS_SOURCE_EXT;
3496   else if (unformat (input, "vlan"))
3497     *qs = QOS_SOURCE_VLAN;
3498   else
3499     return 0;
3500
3501   return 1;
3502 }
3503 #endif
3504
3505 uword
3506 api_unformat_classify_match (unformat_input_t * input, va_list * args)
3507 {
3508   u8 **matchp = va_arg (*args, u8 **);
3509   u32 skip_n_vectors = va_arg (*args, u32);
3510   u32 match_n_vectors = va_arg (*args, u32);
3511
3512   u8 *match = 0;
3513   u8 *l2 = 0;
3514   u8 *l3 = 0;
3515   u8 *l4 = 0;
3516
3517   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3518     {
3519       if (unformat (input, "hex %U", unformat_hex_string, &match))
3520         ;
3521       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
3522         ;
3523       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
3524         ;
3525       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
3526         ;
3527       else
3528         break;
3529     }
3530
3531   if (l4 && !l3)
3532     {
3533       vec_free (match);
3534       vec_free (l2);
3535       vec_free (l4);
3536       return 0;
3537     }
3538
3539   if (match || l2 || l3 || l4)
3540     {
3541       if (l2 || l3 || l4)
3542         {
3543           /* "Win a free Ethernet header in every packet" */
3544           if (l2 == 0)
3545             vec_validate_aligned (l2, 13, sizeof (u32x4));
3546           match = l2;
3547           if (vec_len (l3))
3548             {
3549               vec_append_aligned (match, l3, sizeof (u32x4));
3550               vec_free (l3);
3551             }
3552           if (vec_len (l4))
3553             {
3554               vec_append_aligned (match, l4, sizeof (u32x4));
3555               vec_free (l4);
3556             }
3557         }
3558
3559       /* Make sure the vector is big enough even if key is all 0's */
3560       vec_validate_aligned
3561         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
3562          sizeof (u32x4));
3563
3564       /* Set size, include skipped vectors */
3565       _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
3566
3567       *matchp = match;
3568
3569       return 1;
3570     }
3571
3572   return 0;
3573 }
3574
3575 static int
3576 api_get_node_index (vat_main_t *vam)
3577 {
3578   unformat_input_t *i = vam->input;
3579   vl_api_get_node_index_t *mp;
3580   u8 *name = 0;
3581   int ret;
3582
3583   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3584     {
3585       if (unformat (i, "node %s", &name))
3586         ;
3587       else
3588         break;
3589     }
3590   if (name == 0)
3591     {
3592       errmsg ("node name required");
3593       return -99;
3594     }
3595   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
3596     {
3597       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
3598       return -99;
3599     }
3600
3601   M (GET_NODE_INDEX, mp);
3602   clib_memcpy (mp->node_name, name, vec_len (name));
3603   vec_free (name);
3604
3605   S (mp);
3606   W (ret);
3607   return ret;
3608 }
3609
3610 static int
3611 api_get_next_index (vat_main_t *vam)
3612 {
3613   unformat_input_t *i = vam->input;
3614   vl_api_get_next_index_t *mp;
3615   u8 *node_name = 0, *next_node_name = 0;
3616   int ret;
3617
3618   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3619     {
3620       if (unformat (i, "node-name %s", &node_name))
3621         ;
3622       else if (unformat (i, "next-node-name %s", &next_node_name))
3623         break;
3624     }
3625
3626   if (node_name == 0)
3627     {
3628       errmsg ("node name required");
3629       return -99;
3630     }
3631   if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
3632     {
3633       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
3634       return -99;
3635     }
3636
3637   if (next_node_name == 0)
3638     {
3639       errmsg ("next node name required");
3640       return -99;
3641     }
3642   if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
3643     {
3644       errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
3645       return -99;
3646     }
3647
3648   M (GET_NEXT_INDEX, mp);
3649   clib_memcpy (mp->node_name, node_name, vec_len (node_name));
3650   clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
3651   vec_free (node_name);
3652   vec_free (next_node_name);
3653
3654   S (mp);
3655   W (ret);
3656   return ret;
3657 }
3658
3659 static int
3660 api_add_node_next (vat_main_t *vam)
3661 {
3662   unformat_input_t *i = vam->input;
3663   vl_api_add_node_next_t *mp;
3664   u8 *name = 0;
3665   u8 *next = 0;
3666   int ret;
3667
3668   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3669     {
3670       if (unformat (i, "node %s", &name))
3671         ;
3672       else if (unformat (i, "next %s", &next))
3673         ;
3674       else
3675         break;
3676     }
3677   if (name == 0)
3678     {
3679       errmsg ("node name required");
3680       return -99;
3681     }
3682   if (vec_len (name) >= ARRAY_LEN (mp->node_name))
3683     {
3684       errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
3685       return -99;
3686     }
3687   if (next == 0)
3688     {
3689       errmsg ("next node required");
3690       return -99;
3691     }
3692   if (vec_len (next) >= ARRAY_LEN (mp->next_name))
3693     {
3694       errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
3695       return -99;
3696     }
3697
3698   M (ADD_NODE_NEXT, mp);
3699   clib_memcpy (mp->node_name, name, vec_len (name));
3700   clib_memcpy (mp->next_name, next, vec_len (next));
3701   vec_free (name);
3702   vec_free (next);
3703
3704   S (mp);
3705   W (ret);
3706   return ret;
3707 }
3708
3709 #define foreach_vtr_op                                                        \
3710   _ ("disable", L2_VTR_DISABLED)                                              \
3711   _ ("push-1", L2_VTR_PUSH_1)                                                 \
3712   _ ("push-2", L2_VTR_PUSH_2)                                                 \
3713   _ ("pop-1", L2_VTR_POP_1)                                                   \
3714   _ ("pop-2", L2_VTR_POP_2)                                                   \
3715   _ ("translate-1-1", L2_VTR_TRANSLATE_1_1)                                   \
3716   _ ("translate-1-2", L2_VTR_TRANSLATE_1_2)                                   \
3717   _ ("translate-2-1", L2_VTR_TRANSLATE_2_1)                                   \
3718   _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
3719
3720 static int
3721 api_show_version (vat_main_t *vam)
3722 {
3723   vl_api_show_version_t *mp;
3724   int ret;
3725
3726   M (SHOW_VERSION, mp);
3727
3728   S (mp);
3729   W (ret);
3730   return ret;
3731 }
3732
3733 static int
3734 api_interface_name_renumber (vat_main_t *vam)
3735 {
3736   unformat_input_t *line_input = vam->input;
3737   vl_api_interface_name_renumber_t *mp;
3738   u32 sw_if_index = ~0;
3739   u32 new_show_dev_instance = ~0;
3740   int ret;
3741
3742   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3743     {
3744       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
3745                     &sw_if_index))
3746         ;
3747       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
3748         ;
3749       else if (unformat (line_input, "new_show_dev_instance %d",
3750                          &new_show_dev_instance))
3751         ;
3752       else
3753         break;
3754     }
3755
3756   if (sw_if_index == ~0)
3757     {
3758       errmsg ("missing interface name or sw_if_index");
3759       return -99;
3760     }
3761
3762   if (new_show_dev_instance == ~0)
3763     {
3764       errmsg ("missing new_show_dev_instance");
3765       return -99;
3766     }
3767
3768   M (INTERFACE_NAME_RENUMBER, mp);
3769
3770   mp->sw_if_index = ntohl (sw_if_index);
3771   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
3772
3773   S (mp);
3774   W (ret);
3775   return ret;
3776 }
3777
3778 static int
3779 api_get_first_msg_id (vat_main_t *vam)
3780 {
3781   vl_api_get_first_msg_id_t *mp;
3782   unformat_input_t *i = vam->input;
3783   u8 *name;
3784   u8 name_set = 0;
3785   int ret;
3786
3787   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3788     {
3789       if (unformat (i, "client %s", &name))
3790         name_set = 1;
3791       else
3792         break;
3793     }
3794
3795   if (name_set == 0)
3796     {
3797       errmsg ("missing client name");
3798       return -99;
3799     }
3800   vec_add1 (name, 0);
3801
3802   if (vec_len (name) > 63)
3803     {
3804       errmsg ("client name too long");
3805       return -99;
3806     }
3807
3808   M (GET_FIRST_MSG_ID, mp);
3809   clib_memcpy (mp->name, name, vec_len (name));
3810   S (mp);
3811   W (ret);
3812   return ret;
3813 }
3814
3815 static int
3816 api_get_node_graph (vat_main_t *vam)
3817 {
3818   vl_api_get_node_graph_t *mp;
3819   int ret;
3820
3821   M (GET_NODE_GRAPH, mp);
3822
3823   /* send it... */
3824   S (mp);
3825   /* Wait for the reply */
3826   W (ret);
3827   return ret;
3828 }
3829
3830 static int
3831 api_delete_subif (vat_main_t * vam)
3832 {
3833   unformat_input_t *i = vam->input;
3834   vl_api_delete_subif_t *mp;
3835   u32 sw_if_index = ~0;
3836   int ret;
3837
3838   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3839     {
3840       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3841         ;
3842       if (unformat (i, "sw_if_index %d", &sw_if_index))
3843         ;
3844       else
3845         break;
3846     }
3847
3848   if (sw_if_index == ~0)
3849     {
3850       errmsg ("missing sw_if_index");
3851       return -99;
3852     }
3853
3854   /* Construct the API message */
3855   M (DELETE_SUBIF, mp);
3856   mp->sw_if_index = ntohl (sw_if_index);
3857
3858   S (mp);
3859   W (ret);
3860   return ret;
3861 }
3862
3863 #define foreach_pbb_vtr_op      \
3864 _("disable",  L2_VTR_DISABLED)  \
3865 _("pop",  L2_VTR_POP_2)         \
3866 _("push",  L2_VTR_PUSH_2)
3867
3868
3869 static int
3870 api_sw_interface_tag_add_del (vat_main_t * vam)
3871 {
3872   unformat_input_t *i = vam->input;
3873   vl_api_sw_interface_tag_add_del_t *mp;
3874   u32 sw_if_index = ~0;
3875   u8 *tag = 0;
3876   u8 enable = 1;
3877   int ret;
3878
3879   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3880     {
3881       if (unformat (i, "tag %s", &tag))
3882         ;
3883       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3884         ;
3885       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3886         ;
3887       else if (unformat (i, "del"))
3888         enable = 0;
3889       else
3890         break;
3891     }
3892
3893   if (sw_if_index == ~0)
3894     {
3895       errmsg ("missing interface name or sw_if_index");
3896       return -99;
3897     }
3898
3899   if (enable && (tag == 0))
3900     {
3901       errmsg ("no tag specified");
3902       return -99;
3903     }
3904
3905   /* Construct the API message */
3906   M (SW_INTERFACE_TAG_ADD_DEL, mp);
3907   mp->sw_if_index = ntohl (sw_if_index);
3908   mp->is_add = enable;
3909   if (enable)
3910     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
3911   vec_free (tag);
3912
3913   S (mp);
3914   W (ret);
3915   return ret;
3916 }
3917
3918 static int
3919 api_sw_interface_add_del_mac_address (vat_main_t * vam)
3920 {
3921   unformat_input_t *i = vam->input;
3922   vl_api_mac_address_t mac = { 0 };
3923   vl_api_sw_interface_add_del_mac_address_t *mp;
3924   u32 sw_if_index = ~0;
3925   u8 is_add = 1;
3926   u8 mac_set = 0;
3927   int ret;
3928
3929   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3930     {
3931       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3932         ;
3933       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3934         ;
3935       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
3936         mac_set++;
3937       else if (unformat (i, "del"))
3938         is_add = 0;
3939       else
3940         break;
3941     }
3942
3943   if (sw_if_index == ~0)
3944     {
3945       errmsg ("missing interface name or sw_if_index");
3946       return -99;
3947     }
3948
3949   if (!mac_set)
3950     {
3951       errmsg ("missing MAC address");
3952       return -99;
3953     }
3954
3955   /* Construct the API message */
3956   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
3957   mp->sw_if_index = ntohl (sw_if_index);
3958   mp->is_add = is_add;
3959   clib_memcpy (&mp->addr, &mac, sizeof (mac));
3960
3961   S (mp);
3962   W (ret);
3963   return ret;
3964 }
3965
3966 static int
3967 api_hw_interface_set_mtu (vat_main_t * vam)
3968 {
3969   unformat_input_t *i = vam->input;
3970   vl_api_hw_interface_set_mtu_t *mp;
3971   u32 sw_if_index = ~0;
3972   u32 mtu = 0;
3973   int ret;
3974
3975   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3976     {
3977       if (unformat (i, "mtu %d", &mtu))
3978         ;
3979       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3980         ;
3981       else if (unformat (i, "sw_if_index %d", &sw_if_index))
3982         ;
3983       else
3984         break;
3985     }
3986
3987   if (sw_if_index == ~0)
3988     {
3989       errmsg ("missing interface name or sw_if_index");
3990       return -99;
3991     }
3992
3993   if (mtu == 0)
3994     {
3995       errmsg ("no mtu specified");
3996       return -99;
3997     }
3998
3999   /* Construct the API message */
4000   M (HW_INTERFACE_SET_MTU, mp);
4001   mp->sw_if_index = ntohl (sw_if_index);
4002   mp->mtu = ntohs ((u16) mtu);
4003
4004   S (mp);
4005   W (ret);
4006   return ret;
4007 }
4008
4009 static void vl_api_app_namespace_add_del_reply_t_handler
4010   (vl_api_app_namespace_add_del_reply_t * mp)
4011 {
4012   vat_main_t *vam = &vat_main;
4013   i32 retval = ntohl (mp->retval);
4014   if (vam->async_mode)
4015     {
4016       vam->async_errors += (retval < 0);
4017     }
4018   else
4019     {
4020       vam->retval = retval;
4021       if (retval == 0)
4022         errmsg ("app ns index %d\n", ntohl (mp->appns_index));
4023       vam->result_ready = 1;
4024     }
4025 }
4026
4027 static void vl_api_app_namespace_add_del_reply_t_handler_json
4028   (vl_api_app_namespace_add_del_reply_t * mp)
4029 {
4030   vat_main_t *vam = &vat_main;
4031   vat_json_node_t node;
4032
4033   vat_json_init_object (&node);
4034   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
4035   vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
4036
4037   vat_json_print (vam->ofp, &node);
4038   vat_json_free (&node);
4039
4040   vam->retval = ntohl (mp->retval);
4041   vam->result_ready = 1;
4042 }
4043
4044 static int
4045 api_app_namespace_add_del (vat_main_t * vam)
4046 {
4047   vl_api_app_namespace_add_del_t *mp;
4048   unformat_input_t *i = vam->input;
4049   u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
4050   u32 sw_if_index, ip4_fib_id, ip6_fib_id;
4051   u64 secret;
4052   int ret;
4053
4054   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4055     {
4056       if (unformat (i, "id %_%v%_", &ns_id))
4057         ;
4058       else if (unformat (i, "secret %lu", &secret))
4059         secret_set = 1;
4060       else if (unformat (i, "sw_if_index %d", &sw_if_index))
4061         sw_if_index_set = 1;
4062       else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
4063         ;
4064       else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
4065         ;
4066       else
4067         break;
4068     }
4069   if (!ns_id || !secret_set || !sw_if_index_set)
4070     {
4071       errmsg ("namespace id, secret and sw_if_index must be set");
4072       return -99;
4073     }
4074   if (vec_len (ns_id) > 64)
4075     {
4076       errmsg ("namespace id too long");
4077       return -99;
4078     }
4079   M (APP_NAMESPACE_ADD_DEL, mp);
4080
4081   vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
4082   mp->secret = clib_host_to_net_u64 (secret);
4083   mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
4084   mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
4085   mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
4086   vec_free (ns_id);
4087   S (mp);
4088   W (ret);
4089   return ret;
4090 }
4091
4092 static int
4093 api_sock_init_shm (vat_main_t * vam)
4094 {
4095 #if VPP_API_TEST_BUILTIN == 0
4096   unformat_input_t *i = vam->input;
4097   vl_api_shm_elem_config_t *config = 0;
4098   u64 size = 64 << 20;
4099   int rv;
4100
4101   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4102     {
4103       if (unformat (i, "size %U", unformat_memory_size, &size))
4104         ;
4105       else
4106         break;
4107     }
4108
4109   /*
4110    * Canned custom ring allocator config.
4111    * Should probably parse all of this
4112    */
4113   vec_validate (config, 6);
4114   config[0].type = VL_API_VLIB_RING;
4115   config[0].size = 256;
4116   config[0].count = 32;
4117
4118   config[1].type = VL_API_VLIB_RING;
4119   config[1].size = 1024;
4120   config[1].count = 16;
4121
4122   config[2].type = VL_API_VLIB_RING;
4123   config[2].size = 4096;
4124   config[2].count = 2;
4125
4126   config[3].type = VL_API_CLIENT_RING;
4127   config[3].size = 256;
4128   config[3].count = 32;
4129
4130   config[4].type = VL_API_CLIENT_RING;
4131   config[4].size = 1024;
4132   config[4].count = 16;
4133
4134   config[5].type = VL_API_CLIENT_RING;
4135   config[5].size = 4096;
4136   config[5].count = 2;
4137
4138   config[6].type = VL_API_QUEUE;
4139   config[6].count = 128;
4140   config[6].size = sizeof (uword);
4141
4142   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
4143   if (!rv)
4144     vam->client_index_invalid = 1;
4145   return rv;
4146 #else
4147   return -99;
4148 #endif
4149 }
4150
4151 static void
4152 vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
4153 {
4154   vat_main_t *vam = &vat_main;
4155   fib_prefix_t lcl, rmt;
4156
4157   ip_prefix_decode (&mp->lcl, &lcl);
4158   ip_prefix_decode (&mp->rmt, &rmt);
4159
4160   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
4161     {
4162       print (vam->ofp,
4163              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
4164              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
4165              mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
4166              clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
4167              &rmt.fp_addr.ip4, rmt.fp_len,
4168              clib_net_to_host_u16 (mp->rmt_port),
4169              clib_net_to_host_u32 (mp->action_index), mp->tag);
4170     }
4171   else
4172     {
4173       print (vam->ofp,
4174              "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
4175              clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
4176              mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
4177              clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
4178              &rmt.fp_addr.ip6, rmt.fp_len,
4179              clib_net_to_host_u16 (mp->rmt_port),
4180              clib_net_to_host_u32 (mp->action_index), mp->tag);
4181     }
4182 }
4183
4184 static void
4185 vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
4186                                              mp)
4187 {
4188   vat_main_t *vam = &vat_main;
4189   vat_json_node_t *node = NULL;
4190   struct in6_addr ip6;
4191   struct in_addr ip4;
4192
4193   fib_prefix_t lcl, rmt;
4194
4195   ip_prefix_decode (&mp->lcl, &lcl);
4196   ip_prefix_decode (&mp->rmt, &rmt);
4197
4198   if (VAT_JSON_ARRAY != vam->json_tree.type)
4199     {
4200       ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4201       vat_json_init_array (&vam->json_tree);
4202     }
4203   node = vat_json_array_add (&vam->json_tree);
4204   vat_json_init_object (node);
4205
4206   vat_json_object_add_uint (node, "appns_index",
4207                             clib_net_to_host_u32 (mp->appns_index));
4208   vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
4209   vat_json_object_add_uint (node, "scope", mp->scope);
4210   vat_json_object_add_uint (node, "action_index",
4211                             clib_net_to_host_u32 (mp->action_index));
4212   vat_json_object_add_uint (node, "lcl_port",
4213                             clib_net_to_host_u16 (mp->lcl_port));
4214   vat_json_object_add_uint (node, "rmt_port",
4215                             clib_net_to_host_u16 (mp->rmt_port));
4216   vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
4217   vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
4218   vat_json_object_add_string_copy (node, "tag", mp->tag);
4219   if (lcl.fp_proto == FIB_PROTOCOL_IP4)
4220     {
4221       clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
4222       vat_json_object_add_ip4 (node, "lcl_ip", ip4);
4223       clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
4224       vat_json_object_add_ip4 (node, "rmt_ip", ip4);
4225     }
4226   else
4227     {
4228       clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
4229       vat_json_object_add_ip6 (node, "lcl_ip", ip6);
4230       clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
4231       vat_json_object_add_ip6 (node, "rmt_ip", ip6);
4232     }
4233 }
4234
4235 static int
4236 api_session_rule_add_del (vat_main_t * vam)
4237 {
4238   vl_api_session_rule_add_del_t *mp;
4239   unformat_input_t *i = vam->input;
4240   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
4241   u32 appns_index = 0, scope = 0;
4242   ip4_address_t lcl_ip4, rmt_ip4;
4243   ip6_address_t lcl_ip6, rmt_ip6;
4244   u8 is_ip4 = 1, conn_set = 0;
4245   u8 is_add = 1, *tag = 0;
4246   int ret;
4247   fib_prefix_t lcl, rmt;
4248
4249   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4250     {
4251       if (unformat (i, "del"))
4252         is_add = 0;
4253       else if (unformat (i, "add"))
4254         ;
4255       else if (unformat (i, "proto tcp"))
4256         proto = 0;
4257       else if (unformat (i, "proto udp"))
4258         proto = 1;
4259       else if (unformat (i, "appns %d", &appns_index))
4260         ;
4261       else if (unformat (i, "scope %d", &scope))
4262         ;
4263       else if (unformat (i, "tag %_%v%_", &tag))
4264         ;
4265       else
4266         if (unformat
4267             (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
4268              &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
4269              &rmt_port))
4270         {
4271           is_ip4 = 1;
4272           conn_set = 1;
4273         }
4274       else
4275         if (unformat
4276             (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
4277              &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
4278              &rmt_port))
4279         {
4280           is_ip4 = 0;
4281           conn_set = 1;
4282         }
4283       else if (unformat (i, "action %d", &action))
4284         ;
4285       else
4286         break;
4287     }
4288   if (proto == ~0 || !conn_set || action == ~0)
4289     {
4290       errmsg ("transport proto, connection and action must be set");
4291       return -99;
4292     }
4293
4294   if (scope > 3)
4295     {
4296       errmsg ("scope should be 0-3");
4297       return -99;
4298     }
4299
4300   M (SESSION_RULE_ADD_DEL, mp);
4301
4302   clib_memset (&lcl, 0, sizeof (lcl));
4303   clib_memset (&rmt, 0, sizeof (rmt));
4304   if (is_ip4)
4305     {
4306       ip_set (&lcl.fp_addr, &lcl_ip4, 1);
4307       ip_set (&rmt.fp_addr, &rmt_ip4, 1);
4308       lcl.fp_len = lcl_plen;
4309       rmt.fp_len = rmt_plen;
4310     }
4311   else
4312     {
4313       ip_set (&lcl.fp_addr, &lcl_ip6, 0);
4314       ip_set (&rmt.fp_addr, &rmt_ip6, 0);
4315       lcl.fp_len = lcl_plen;
4316       rmt.fp_len = rmt_plen;
4317     }
4318
4319
4320   ip_prefix_encode (&lcl, &mp->lcl);
4321   ip_prefix_encode (&rmt, &mp->rmt);
4322   mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
4323   mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
4324   mp->transport_proto =
4325     proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
4326   mp->action_index = clib_host_to_net_u32 (action);
4327   mp->appns_index = clib_host_to_net_u32 (appns_index);
4328   mp->scope = scope;
4329   mp->is_add = is_add;
4330   if (tag)
4331     {
4332       clib_memcpy (mp->tag, tag, vec_len (tag));
4333       vec_free (tag);
4334     }
4335
4336   S (mp);
4337   W (ret);
4338   return ret;
4339 }
4340
4341 static int
4342 api_session_rules_dump (vat_main_t * vam)
4343 {
4344   vl_api_session_rules_dump_t *mp;
4345   vl_api_control_ping_t *mp_ping;
4346   int ret;
4347
4348   if (!vam->json_output)
4349     {
4350       print (vam->ofp, "%=20s", "Session Rules");
4351     }
4352
4353   M (SESSION_RULES_DUMP, mp);
4354   /* send it... */
4355   S (mp);
4356
4357   /* Use a control ping for synchronization */
4358   MPING (CONTROL_PING, mp_ping);
4359   S (mp_ping);
4360
4361   /* Wait for a reply... */
4362   W (ret);
4363   return ret;
4364 }
4365
4366 static int
4367 q_or_quit (vat_main_t * vam)
4368 {
4369 #if VPP_API_TEST_BUILTIN == 0
4370   longjmp (vam->jump_buf, 1);
4371 #endif
4372   return 0;                     /* not so much */
4373 }
4374
4375 static int
4376 q (vat_main_t * vam)
4377 {
4378   return q_or_quit (vam);
4379 }
4380
4381 static int
4382 quit (vat_main_t * vam)
4383 {
4384   return q_or_quit (vam);
4385 }
4386
4387 static int
4388 comment (vat_main_t * vam)
4389 {
4390   return 0;
4391 }
4392
4393 static int
4394 elog_save (vat_main_t * vam)
4395 {
4396 #if VPP_API_TEST_BUILTIN == 0
4397   elog_main_t *em = &vam->elog_main;
4398   unformat_input_t *i = vam->input;
4399   char *file, *chroot_file;
4400   clib_error_t *error;
4401
4402   if (!unformat (i, "%s", &file))
4403     {
4404       errmsg ("expected file name, got `%U'", format_unformat_error, i);
4405       return 0;
4406     }
4407
4408   /* It's fairly hard to get "../oopsie" through unformat; just in case */
4409   if (strstr (file, "..") || index (file, '/'))
4410     {
4411       errmsg ("illegal characters in filename '%s'", file);
4412       return 0;
4413     }
4414
4415   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
4416
4417   vec_free (file);
4418
4419   errmsg ("Saving %wd of %wd events to %s",
4420           elog_n_events_in_buffer (em),
4421           elog_buffer_capacity (em), chroot_file);
4422
4423   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
4424   vec_free (chroot_file);
4425
4426   if (error)
4427     clib_error_report (error);
4428 #else
4429   errmsg ("Use the vpp event loger...");
4430 #endif
4431
4432   return 0;
4433 }
4434
4435 static int
4436 elog_setup (vat_main_t * vam)
4437 {
4438 #if VPP_API_TEST_BUILTIN == 0
4439   elog_main_t *em = &vam->elog_main;
4440   unformat_input_t *i = vam->input;
4441   u32 nevents = 128 << 10;
4442
4443   (void) unformat (i, "nevents %d", &nevents);
4444
4445   elog_init (em, nevents);
4446   vl_api_set_elog_main (em);
4447   vl_api_set_elog_trace_api_messages (1);
4448   errmsg ("Event logger initialized with %u events", nevents);
4449 #else
4450   errmsg ("Use the vpp event loger...");
4451 #endif
4452   return 0;
4453 }
4454
4455 static int
4456 elog_enable (vat_main_t * vam)
4457 {
4458 #if VPP_API_TEST_BUILTIN == 0
4459   elog_main_t *em = &vam->elog_main;
4460
4461   elog_enable_disable (em, 1 /* enable */ );
4462   vl_api_set_elog_trace_api_messages (1);
4463   errmsg ("Event logger enabled...");
4464 #else
4465   errmsg ("Use the vpp event loger...");
4466 #endif
4467   return 0;
4468 }
4469
4470 static int
4471 elog_disable (vat_main_t * vam)
4472 {
4473 #if VPP_API_TEST_BUILTIN == 0
4474   elog_main_t *em = &vam->elog_main;
4475
4476   elog_enable_disable (em, 0 /* enable */ );
4477   vl_api_set_elog_trace_api_messages (1);
4478   errmsg ("Event logger disabled...");
4479 #else
4480   errmsg ("Use the vpp event loger...");
4481 #endif
4482   return 0;
4483 }
4484
4485 static int
4486 statseg (vat_main_t * vam)
4487 {
4488   ssvm_private_t *ssvmp = &vam->stat_segment;
4489   ssvm_shared_header_t *shared_header = ssvmp->sh;
4490   vlib_counter_t **counters;
4491   u64 thread0_index1_packets;
4492   u64 thread0_index1_bytes;
4493   f64 vector_rate, input_rate;
4494   uword *p;
4495
4496   uword *counter_vector_by_name;
4497   if (vam->stat_segment_lockp == 0)
4498     {
4499       errmsg ("Stat segment not mapped...");
4500       return -99;
4501     }
4502
4503   /* look up "/if/rx for sw_if_index 1 as a test */
4504
4505   clib_spinlock_lock (vam->stat_segment_lockp);
4506
4507   counter_vector_by_name = (uword *) shared_header->opaque[1];
4508
4509   p = hash_get_mem (counter_vector_by_name, "/if/rx");
4510   if (p == 0)
4511     {
4512       clib_spinlock_unlock (vam->stat_segment_lockp);
4513       errmsg ("/if/tx not found?");
4514       return -99;
4515     }
4516
4517   /* Fish per-thread vector of combined counters from shared memory */
4518   counters = (vlib_counter_t **) p[0];
4519
4520   if (vec_len (counters[0]) < 2)
4521     {
4522       clib_spinlock_unlock (vam->stat_segment_lockp);
4523       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
4524       return -99;
4525     }
4526
4527   /* Read thread 0 sw_if_index 1 counter */
4528   thread0_index1_packets = counters[0][1].packets;
4529   thread0_index1_bytes = counters[0][1].bytes;
4530
4531   p = hash_get_mem (counter_vector_by_name, "vector_rate");
4532   if (p == 0)
4533     {
4534       clib_spinlock_unlock (vam->stat_segment_lockp);
4535       errmsg ("vector_rate not found?");
4536       return -99;
4537     }
4538
4539   vector_rate = *(f64 *) (p[0]);
4540   p = hash_get_mem (counter_vector_by_name, "input_rate");
4541   if (p == 0)
4542     {
4543       clib_spinlock_unlock (vam->stat_segment_lockp);
4544       errmsg ("input_rate not found?");
4545       return -99;
4546     }
4547   input_rate = *(f64 *) (p[0]);
4548
4549   clib_spinlock_unlock (vam->stat_segment_lockp);
4550
4551   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
4552          vector_rate, input_rate);
4553   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
4554          thread0_index1_packets, thread0_index1_bytes);
4555
4556   return 0;
4557 }
4558
4559 static int
4560 cmd_cmp (void *a1, void *a2)
4561 {
4562   u8 **c1 = a1;
4563   u8 **c2 = a2;
4564
4565   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
4566 }
4567
4568 static int
4569 help (vat_main_t * vam)
4570 {
4571   u8 **cmds = 0;
4572   u8 *name = 0;
4573   hash_pair_t *p;
4574   unformat_input_t *i = vam->input;
4575   int j;
4576
4577   if (unformat (i, "%s", &name))
4578     {
4579       uword *hs;
4580
4581       vec_add1 (name, 0);
4582
4583       hs = hash_get_mem (vam->help_by_name, name);
4584       if (hs)
4585         print (vam->ofp, "usage: %s %s", name, hs[0]);
4586       else
4587         print (vam->ofp, "No such msg / command '%s'", name);
4588       vec_free (name);
4589       return 0;
4590     }
4591
4592   print (vam->ofp, "Help is available for the following:");
4593
4594     /* *INDENT-OFF* */
4595     hash_foreach_pair (p, vam->function_by_name,
4596     ({
4597       vec_add1 (cmds, (u8 *)(p->key));
4598     }));
4599     /* *INDENT-ON* */
4600
4601   vec_sort_with_function (cmds, cmd_cmp);
4602
4603   for (j = 0; j < vec_len (cmds); j++)
4604     print (vam->ofp, "%s", cmds[j]);
4605
4606   vec_free (cmds);
4607   return 0;
4608 }
4609
4610 static int
4611 set (vat_main_t * vam)
4612 {
4613   u8 *name = 0, *value = 0;
4614   unformat_input_t *i = vam->input;
4615
4616   if (unformat (i, "%s", &name))
4617     {
4618       /* The input buffer is a vector, not a string. */
4619       value = vec_dup (i->buffer);
4620       vec_delete (value, i->index, 0);
4621       /* Almost certainly has a trailing newline */
4622       if (value[vec_len (value) - 1] == '\n')
4623         value[vec_len (value) - 1] = 0;
4624       /* Make sure it's a proper string, one way or the other */
4625       vec_add1 (value, 0);
4626       (void) clib_macro_set_value (&vam->macro_main,
4627                                    (char *) name, (char *) value);
4628     }
4629   else
4630     errmsg ("usage: set <name> <value>");
4631
4632   vec_free (name);
4633   vec_free (value);
4634   return 0;
4635 }
4636
4637 static int
4638 unset (vat_main_t * vam)
4639 {
4640   u8 *name = 0;
4641
4642   if (unformat (vam->input, "%s", &name))
4643     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
4644       errmsg ("unset: %s wasn't set", name);
4645   vec_free (name);
4646   return 0;
4647 }
4648
4649 typedef struct
4650 {
4651   u8 *name;
4652   u8 *value;
4653 } macro_sort_t;
4654
4655
4656 static int
4657 macro_sort_cmp (void *a1, void *a2)
4658 {
4659   macro_sort_t *s1 = a1;
4660   macro_sort_t *s2 = a2;
4661
4662   return strcmp ((char *) (s1->name), (char *) (s2->name));
4663 }
4664
4665 static int
4666 dump_macro_table (vat_main_t * vam)
4667 {
4668   macro_sort_t *sort_me = 0, *sm;
4669   int i;
4670   hash_pair_t *p;
4671
4672     /* *INDENT-OFF* */
4673     hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
4674     ({
4675       vec_add2 (sort_me, sm, 1);
4676       sm->name = (u8 *)(p->key);
4677       sm->value = (u8 *) (p->value[0]);
4678     }));
4679     /* *INDENT-ON* */
4680
4681   vec_sort_with_function (sort_me, macro_sort_cmp);
4682
4683   if (vec_len (sort_me))
4684     print (vam->ofp, "%-15s%s", "Name", "Value");
4685   else
4686     print (vam->ofp, "The macro table is empty...");
4687
4688   for (i = 0; i < vec_len (sort_me); i++)
4689     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
4690   return 0;
4691 }
4692
4693 static int
4694 value_sort_cmp (void *a1, void *a2)
4695 {
4696   name_sort_t *n1 = a1;
4697   name_sort_t *n2 = a2;
4698
4699   if (n1->value < n2->value)
4700     return -1;
4701   if (n1->value > n2->value)
4702     return 1;
4703   return 0;
4704 }
4705
4706
4707 static int
4708 dump_msg_api_table (vat_main_t * vam)
4709 {
4710   api_main_t *am = vlibapi_get_main ();
4711   name_sort_t *nses = 0, *ns;
4712   hash_pair_t *hp;
4713   int i;
4714
4715   /* *INDENT-OFF* */
4716   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
4717   ({
4718     vec_add2 (nses, ns, 1);
4719     ns->name = (u8 *)(hp->key);
4720     ns->value = (u32) hp->value[0];
4721   }));
4722   /* *INDENT-ON* */
4723
4724   vec_sort_with_function (nses, value_sort_cmp);
4725
4726   for (i = 0; i < vec_len (nses); i++)
4727     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
4728   vec_free (nses);
4729   return 0;
4730 }
4731
4732 static int
4733 get_msg_id (vat_main_t * vam)
4734 {
4735   u8 *name_and_crc;
4736   u32 message_index;
4737
4738   if (unformat (vam->input, "%s", &name_and_crc))
4739     {
4740       message_index = vl_msg_api_get_msg_index (name_and_crc);
4741       if (message_index == ~0)
4742         {
4743           print (vam->ofp, " '%s' not found", name_and_crc);
4744           return 0;
4745         }
4746       print (vam->ofp, " '%s' has message index %d",
4747              name_and_crc, message_index);
4748       return 0;
4749     }
4750   errmsg ("name_and_crc required...");
4751   return 0;
4752 }
4753
4754 static int
4755 search_node_table (vat_main_t * vam)
4756 {
4757   unformat_input_t *line_input = vam->input;
4758   u8 *node_to_find;
4759   int j;
4760   vlib_node_t *node, *next_node;
4761   uword *p;
4762
4763   if (vam->graph_node_index_by_name == 0)
4764     {
4765       print (vam->ofp, "Node table empty, issue get_node_graph...");
4766       return 0;
4767     }
4768
4769   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
4770     {
4771       if (unformat (line_input, "%s", &node_to_find))
4772         {
4773           vec_add1 (node_to_find, 0);
4774           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
4775           if (p == 0)
4776             {
4777               print (vam->ofp, "%s not found...", node_to_find);
4778               goto out;
4779             }
4780           node = vam->graph_nodes[0][p[0]];
4781           print (vam->ofp, "[%d] %s", p[0], node->name);
4782           for (j = 0; j < vec_len (node->next_nodes); j++)
4783             {
4784               if (node->next_nodes[j] != ~0)
4785                 {
4786                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
4787                   print (vam->ofp, "  [%d] %s", j, next_node->name);
4788                 }
4789             }
4790         }
4791
4792       else
4793         {
4794           clib_warning ("parse error '%U'", format_unformat_error,
4795                         line_input);
4796           return -99;
4797         }
4798
4799     out:
4800       vec_free (node_to_find);
4801
4802     }
4803
4804   return 0;
4805 }
4806
4807
4808 static int
4809 script (vat_main_t * vam)
4810 {
4811 #if (VPP_API_TEST_BUILTIN==0)
4812   u8 *s = 0;
4813   char *save_current_file;
4814   unformat_input_t save_input;
4815   jmp_buf save_jump_buf;
4816   u32 save_line_number;
4817
4818   FILE *new_fp, *save_ifp;
4819
4820   if (unformat (vam->input, "%s", &s))
4821     {
4822       new_fp = fopen ((char *) s, "r");
4823       if (new_fp == 0)
4824         {
4825           errmsg ("Couldn't open script file %s", s);
4826           vec_free (s);
4827           return -99;
4828         }
4829     }
4830   else
4831     {
4832       errmsg ("Missing script name");
4833       return -99;
4834     }
4835
4836   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
4837   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
4838   save_ifp = vam->ifp;
4839   save_line_number = vam->input_line_number;
4840   save_current_file = (char *) vam->current_file;
4841
4842   vam->input_line_number = 0;
4843   vam->ifp = new_fp;
4844   vam->current_file = s;
4845   do_one_file (vam);
4846
4847   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
4848   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
4849   vam->ifp = save_ifp;
4850   vam->input_line_number = save_line_number;
4851   vam->current_file = (u8 *) save_current_file;
4852   vec_free (s);
4853
4854   return 0;
4855 #else
4856   clib_warning ("use the exec command...");
4857   return -99;
4858 #endif
4859 }
4860
4861 static int
4862 echo (vat_main_t * vam)
4863 {
4864   print (vam->ofp, "%v", vam->input->buffer);
4865   return 0;
4866 }
4867
4868 /* List of API message constructors, CLI names map to api_xxx */
4869 #define foreach_vpe_api_msg                                             \
4870 _(create_loopback,"[mac <mac-addr>] [instance <instance>]")             \
4871 _(sw_interface_dump,"")                                                 \
4872 _(sw_interface_set_flags,                                               \
4873   "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
4874 _(sw_interface_add_del_address,                                         \
4875   "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
4876 _(sw_interface_set_rx_placement,                                        \
4877   "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]")       \
4878 _(sw_interface_rx_placement_dump,                                       \
4879   "[<intfc> | sw_if_index <id>]")                                         \
4880 _(sw_interface_set_table,                                               \
4881   "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]")                   \
4882 _(sw_interface_set_unnumbered,                                          \
4883   "<intfc> | sw_if_index <id> unnum_if_index <id> [del]")               \
4884 _(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>")             \
4885 _(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n"               \
4886   "[outer_vlan_id <n>][inner_vlan_id <n>]\n"                            \
4887   "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n"    \
4888   "[outer_vlan_id_any][inner_vlan_id_any]")                             \
4889 _(get_node_index, "node <node-name")                                    \
4890 _(add_node_next, "node <node-name> next <next-node-name>")              \
4891 _(show_version, "")                                                     \
4892 _(show_threads, "")                                                     \
4893 _(interface_name_renumber,                                              \
4894   "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>")              \
4895 _(delete_loopback,"sw_if_index <nn>")                                   \
4896 _(want_interface_events,  "enable|disable")                             \
4897 _(get_first_msg_id, "client <name>")                                    \
4898 _(get_node_graph, " ")                                                  \
4899 _(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>")                \
4900 _(get_next_index, "node-name <node-name> next-node-name <node-name>")   \
4901 _(delete_subif,"<intfc> | sw_if_index <nn>")                            \
4902 _(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>"     \
4903 "[disable]")                                                            \
4904 _(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> "       \
4905   "mac <mac-address> [del]")                                            \
4906 _(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>")        \
4907 _(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]")          \
4908 _(sock_init_shm, "size <nnn>")                                          \
4909 _(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
4910 _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
4911   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                  \
4912 _(session_rules_dump, "")                                               \
4913
4914 /* List of command functions, CLI names map directly to functions */
4915 #define foreach_cli_function                                    \
4916 _(comment, "usage: comment <ignore-rest-of-line>")              \
4917 _(dump_interface_table, "usage: dump_interface_table")          \
4918 _(dump_sub_interface_table, "usage: dump_sub_interface_table")  \
4919 _(dump_macro_table, "usage: dump_macro_table ")                 \
4920 _(dump_msg_api_table, "usage: dump_msg_api_table")              \
4921 _(elog_setup, "usage: elog_setup [nevents, default 128K]")      \
4922 _(elog_disable, "usage: elog_disable")                          \
4923 _(elog_enable, "usage: elog_enable")                            \
4924 _(elog_save, "usage: elog_save <filename>")                     \
4925 _(get_msg_id, "usage: get_msg_id name_and_crc")                 \
4926 _(echo, "usage: echo <message>")                                \
4927 _(exec, "usage: exec <vpe-debug-CLI-command>")                  \
4928 _(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>")    \
4929 _(help, "usage: help")                                          \
4930 _(q, "usage: quit")                                             \
4931 _(quit, "usage: quit")                                          \
4932 _(search_node_table, "usage: search_node_table <name>...")      \
4933 _(set, "usage: set <variable-name> <value>")                    \
4934 _(script, "usage: script <file-name>")                          \
4935 _(statseg, "usage: statseg")                                    \
4936 _(unset, "usage: unset <variable-name>")
4937
4938 #define _(N,n)                                  \
4939     static void vl_api_##n##_t_handler_uni      \
4940     (vl_api_##n##_t * mp)                       \
4941     {                                           \
4942         vat_main_t * vam = &vat_main;           \
4943         if (vam->json_output) {                 \
4944             vl_api_##n##_t_handler_json(mp);    \
4945         } else {                                \
4946             vl_api_##n##_t_handler(mp);         \
4947         }                                       \
4948     }
4949 foreach_vpe_api_reply_msg;
4950 #if VPP_API_TEST_BUILTIN == 0
4951 foreach_standalone_reply_msg;
4952 #endif
4953 #undef _
4954
4955 void
4956 vat_api_hookup (vat_main_t * vam)
4957 {
4958 #define _(N,n)                                                  \
4959     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
4960                            vl_api_##n##_t_handler_uni,          \
4961                            vl_noop_handler,                     \
4962                            vl_api_##n##_t_endian,               \
4963                            vl_api_##n##_t_print,                \
4964                            sizeof(vl_api_##n##_t), 1);
4965   foreach_vpe_api_reply_msg;
4966 #if VPP_API_TEST_BUILTIN == 0
4967   foreach_standalone_reply_msg;
4968 #endif
4969 #undef _
4970
4971 #if (VPP_API_TEST_BUILTIN==0)
4972   vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
4973
4974   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
4975
4976   vam->function_by_name = hash_create_string (0, sizeof (uword));
4977
4978   vam->help_by_name = hash_create_string (0, sizeof (uword));
4979 #endif
4980
4981   /* API messages we can send */
4982 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
4983   foreach_vpe_api_msg;
4984 #undef _
4985
4986   /* Help strings */
4987 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
4988   foreach_vpe_api_msg;
4989 #undef _
4990
4991   /* CLI functions */
4992 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
4993   foreach_cli_function;
4994 #undef _
4995
4996   /* Help strings */
4997 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
4998   foreach_cli_function;
4999 #undef _
5000 }
5001
5002 #if VPP_API_TEST_BUILTIN
5003 static clib_error_t *
5004 vat_api_hookup_shim (vlib_main_t * vm)
5005 {
5006   vat_api_hookup (&vat_main);
5007   return 0;
5008 }
5009
5010 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
5011 #endif
5012
5013 /*
5014  * fd.io coding-style-patch-verification: ON
5015  *
5016  * Local Variables:
5017  * eval: (c-set-style "gnu")
5018  * End:
5019  */