Line data Source code
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 <vnet/l2/l2_classify.h>
33 : #include <vnet/l2/l2_vtr.h>
34 : #include <vnet/classify/in_out_acl.h>
35 : #include <vnet/classify/policer_classify.h>
36 : #include <vnet/classify/flow_classify.h>
37 : #include <vnet/mpls/mpls.h>
38 : #include <vnet/ipsec/ipsec.h>
39 : #include <inttypes.h>
40 : #include <vnet/ip/ip6_hop_by_hop.h>
41 : #include <vnet/ip/ip_source_and_port_range_check.h>
42 : #include <vnet/policer/xlate.h>
43 : #include <vnet/span/span.h>
44 : #include <vnet/policer/policer.h>
45 : #include <vnet/policer/police.h>
46 : #include <vnet/mfib/mfib_types.h>
47 : #include <vnet/bonding/node.h>
48 : #include <vnet/qos/qos_types.h>
49 : #include <vnet/ethernet/ethernet_types_api.h>
50 : #include <vnet/ip/ip_types_api.h>
51 : #include "vat/json_format.h"
52 : #include <vnet/ip/ip_types_api.h>
53 : #include <vnet/ethernet/ethernet_types_api.h>
54 :
55 : #include <inttypes.h>
56 : #include <sys/stat.h>
57 :
58 : #include <vlibmemory/memclnt.api_enum.h>
59 : #include <vlibmemory/memclnt.api_types.h>
60 : #include <vlibmemory/memclnt.api_tojson.h>
61 : #include <vlibmemory/memclnt.api_fromjson.h>
62 :
63 : #define vl_endianfun /* define message structures */
64 : #include <vlibmemory/memclnt.api.h>
65 : #undef vl_endianfun
66 :
67 : #define vl_calcsizefun
68 : #include <vlibmemory/memclnt.api.h>
69 : #undef vl_calcsizefun
70 :
71 : /* instantiate all the print functions we know about */
72 : #define vl_printfun
73 : #include <vlibmemory/memclnt.api.h>
74 : #undef vl_printfun
75 :
76 : #define __plugin_msg_base 0
77 : #include <vlibapi/vat_helper_macros.h>
78 :
79 : void vl_api_set_elog_main (elog_main_t * m);
80 : int vl_api_set_elog_trace_api_messages (int enable);
81 :
82 : #if VPP_API_TEST_BUILTIN == 0
83 : #include <netdb.h>
84 :
85 : u32
86 : vl (void *p)
87 : {
88 : return vec_len (p);
89 : }
90 :
91 : int
92 : vat_socket_connect (vat_main_t * vam)
93 : {
94 : int rv;
95 : api_main_t *am = vlibapi_get_main ();
96 : vam->socket_client_main = &socket_client_main;
97 : if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
98 : "vpp_api_test",
99 : 0 /* default socket rx, tx buffer */ )))
100 : return rv;
101 :
102 : /* vpp expects the client index in network order */
103 : vam->my_client_index = htonl (socket_client_main.client_index);
104 : am->my_client_index = vam->my_client_index;
105 : return 0;
106 : }
107 : #else /* vpp built-in case, we don't do sockets... */
108 : int
109 0 : vat_socket_connect (vat_main_t * vam)
110 : {
111 0 : return 0;
112 : }
113 :
114 : int
115 0 : vl_socket_client_read (int wait)
116 : {
117 0 : return -1;
118 : };
119 :
120 : int
121 0 : vl_socket_client_write ()
122 : {
123 0 : return -1;
124 : };
125 :
126 : void *
127 0 : vl_socket_client_msg_alloc (int nbytes)
128 : {
129 0 : return 0;
130 : }
131 : #endif
132 :
133 :
134 : f64
135 785397 : vat_time_now (vat_main_t * vam)
136 : {
137 : #if VPP_API_TEST_BUILTIN
138 785397 : return vlib_time_now (vam->vlib_main);
139 : #else
140 : return clib_time_now (&vam->clib_time);
141 : #endif
142 : }
143 :
144 : void
145 2 : errmsg (char *fmt, ...)
146 : {
147 2 : vat_main_t *vam = &vat_main;
148 : va_list va;
149 : u8 *s;
150 :
151 2 : va_start (va, fmt);
152 2 : s = va_format (0, fmt, &va);
153 2 : va_end (va);
154 :
155 2 : vec_add1 (s, 0);
156 :
157 : #if VPP_API_TEST_BUILTIN
158 2 : vlib_cli_output (vam->vlib_main, (char *) s);
159 : #else
160 : {
161 : if (vam->ifp != stdin)
162 : fformat (vam->ofp, "%s(%d): \n", vam->current_file,
163 : vam->input_line_number);
164 : else
165 : fformat (vam->ofp, "%s\n", (char *) s);
166 : fflush (vam->ofp);
167 : }
168 : #endif
169 :
170 2 : vec_free (s);
171 2 : }
172 :
173 : #if VPP_API_TEST_BUILTIN == 0
174 :
175 : /* Parse an IP4 address %d.%d.%d.%d. */
176 : uword
177 : unformat_ip4_address (unformat_input_t * input, va_list * args)
178 : {
179 : u8 *result = va_arg (*args, u8 *);
180 : unsigned a[4];
181 :
182 : if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
183 : return 0;
184 :
185 : if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
186 : return 0;
187 :
188 : result[0] = a[0];
189 : result[1] = a[1];
190 : result[2] = a[2];
191 : result[3] = a[3];
192 :
193 : return 1;
194 : }
195 :
196 : uword
197 : unformat_ethernet_address (unformat_input_t * input, va_list * args)
198 : {
199 : u8 *result = va_arg (*args, u8 *);
200 : u32 i, a[6];
201 :
202 : if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
203 : &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
204 : return 0;
205 :
206 : /* Check range. */
207 : for (i = 0; i < 6; i++)
208 : if (a[i] >= (1 << 8))
209 : return 0;
210 :
211 : for (i = 0; i < 6; i++)
212 : result[i] = a[i];
213 :
214 : return 1;
215 : }
216 :
217 : /* Returns ethernet type as an int in host byte order. */
218 : uword
219 : unformat_ethernet_type_host_byte_order (unformat_input_t * input,
220 : va_list * args)
221 : {
222 : u16 *result = va_arg (*args, u16 *);
223 : int type;
224 :
225 : /* Numeric type. */
226 : if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
227 : {
228 : if (type >= (1 << 16))
229 : return 0;
230 : *result = type;
231 : return 1;
232 : }
233 : return 0;
234 : }
235 :
236 : /* Parse an IP46 address. */
237 : uword
238 : unformat_ip46_address (unformat_input_t * input, va_list * args)
239 : {
240 : ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
241 : ip46_type_t type = va_arg (*args, ip46_type_t);
242 : if ((type != IP46_TYPE_IP6) &&
243 : unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
244 : {
245 : ip46_address_mask_ip4 (ip46);
246 : return 1;
247 : }
248 : else if ((type != IP46_TYPE_IP4) &&
249 : unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
250 : {
251 : return 1;
252 : }
253 : return 0;
254 : }
255 :
256 : /* Parse an IP6 address. */
257 : uword
258 : unformat_ip6_address (unformat_input_t * input, va_list * args)
259 : {
260 : ip6_address_t *result = va_arg (*args, ip6_address_t *);
261 : u16 hex_quads[8];
262 : uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
263 : uword c, n_colon, double_colon_index;
264 :
265 : n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
266 : double_colon_index = ARRAY_LEN (hex_quads);
267 : while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
268 : {
269 : hex_digit = 16;
270 : if (c >= '0' && c <= '9')
271 : hex_digit = c - '0';
272 : else if (c >= 'a' && c <= 'f')
273 : hex_digit = c + 10 - 'a';
274 : else if (c >= 'A' && c <= 'F')
275 : hex_digit = c + 10 - 'A';
276 : else if (c == ':' && n_colon < 2)
277 : n_colon++;
278 : else
279 : {
280 : unformat_put_input (input);
281 : break;
282 : }
283 :
284 : /* Too many hex quads. */
285 : if (n_hex_quads >= ARRAY_LEN (hex_quads))
286 : return 0;
287 :
288 : if (hex_digit < 16)
289 : {
290 : hex_quad = (hex_quad << 4) | hex_digit;
291 :
292 : /* Hex quad must fit in 16 bits. */
293 : if (n_hex_digits >= 4)
294 : return 0;
295 :
296 : n_colon = 0;
297 : n_hex_digits++;
298 : }
299 :
300 : /* Save position of :: */
301 : if (n_colon == 2)
302 : {
303 : /* More than one :: ? */
304 : if (double_colon_index < ARRAY_LEN (hex_quads))
305 : return 0;
306 : double_colon_index = n_hex_quads;
307 : }
308 :
309 : if (n_colon > 0 && n_hex_digits > 0)
310 : {
311 : hex_quads[n_hex_quads++] = hex_quad;
312 : hex_quad = 0;
313 : n_hex_digits = 0;
314 : }
315 : }
316 :
317 : if (n_hex_digits > 0)
318 : hex_quads[n_hex_quads++] = hex_quad;
319 :
320 : {
321 : word i;
322 :
323 : /* Expand :: to appropriate number of zero hex quads. */
324 : if (double_colon_index < ARRAY_LEN (hex_quads))
325 : {
326 : word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
327 :
328 : for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
329 : hex_quads[n_zero + i] = hex_quads[i];
330 :
331 : for (i = 0; i < n_zero; i++)
332 : hex_quads[double_colon_index + i] = 0;
333 :
334 : n_hex_quads = ARRAY_LEN (hex_quads);
335 : }
336 :
337 : /* Too few hex quads given. */
338 : if (n_hex_quads < ARRAY_LEN (hex_quads))
339 : return 0;
340 :
341 : for (i = 0; i < ARRAY_LEN (hex_quads); i++)
342 : result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
343 :
344 : return 1;
345 : }
346 : }
347 :
348 : uword
349 : unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
350 : {
351 : u32 *r = va_arg (*args, u32 *);
352 :
353 : if (0);
354 : #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
355 : foreach_ipsec_policy_action
356 : #undef _
357 : else
358 : return 0;
359 : return 1;
360 : }
361 :
362 : u8 *
363 : format_ipsec_crypto_alg (u8 * s, va_list * args)
364 : {
365 : u32 i = va_arg (*args, u32);
366 : u8 *t = 0;
367 :
368 : switch (i)
369 : {
370 : #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
371 : foreach_ipsec_crypto_alg
372 : #undef _
373 : default:
374 : return format (s, "unknown");
375 : }
376 : return format (s, "%s", t);
377 : }
378 :
379 : u8 *
380 : format_ipsec_integ_alg (u8 * s, va_list * args)
381 : {
382 : u32 i = va_arg (*args, u32);
383 : u8 *t = 0;
384 :
385 : switch (i)
386 : {
387 : #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
388 : foreach_ipsec_integ_alg
389 : #undef _
390 : default:
391 : return format (s, "unknown");
392 : }
393 : return format (s, "%s", t);
394 : }
395 :
396 : #else /* VPP_API_TEST_BUILTIN == 1 */
397 : static uword
398 0 : api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
399 : {
400 0 : vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
401 0 : vnet_main_t *vnm = vnet_get_main ();
402 0 : u32 *result = va_arg (*args, u32 *);
403 :
404 0 : return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
405 : }
406 :
407 : #endif /* VPP_API_TEST_BUILTIN */
408 :
409 : #if (VPP_API_TEST_BUILTIN==0)
410 :
411 : static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
412 : static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
413 : static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
414 : static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
415 :
416 : uword
417 : unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
418 : {
419 : mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
420 : mfib_itf_attribute_t attr;
421 :
422 : old = *iflags;
423 : FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
424 : {
425 : if (unformat (input, mfib_itf_flag_long_names[attr]))
426 : *iflags |= (1 << attr);
427 : }
428 : FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
429 : {
430 : if (unformat (input, mfib_itf_flag_names[attr]))
431 : *iflags |= (1 << attr);
432 : }
433 :
434 : return (old == *iflags ? 0 : 1);
435 : }
436 :
437 : uword
438 : unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
439 : {
440 : mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
441 : mfib_entry_attribute_t attr;
442 :
443 : old = *eflags;
444 : FOR_EACH_MFIB_ATTRIBUTE (attr)
445 : {
446 : if (unformat (input, mfib_flag_long_names[attr]))
447 : *eflags |= (1 << attr);
448 : }
449 : FOR_EACH_MFIB_ATTRIBUTE (attr)
450 : {
451 : if (unformat (input, mfib_flag_names[attr]))
452 : *eflags |= (1 << attr);
453 : }
454 :
455 : return (old == *eflags ? 0 : 1);
456 : }
457 :
458 : u8 *
459 : format_ip4_address (u8 * s, va_list * args)
460 : {
461 : u8 *a = va_arg (*args, u8 *);
462 : return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
463 : }
464 :
465 : u8 *
466 : format_ip6_address (u8 * s, va_list * args)
467 : {
468 : ip6_address_t *a = va_arg (*args, ip6_address_t *);
469 : u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
470 :
471 : i_max_n_zero = ARRAY_LEN (a->as_u16);
472 : max_n_zeros = 0;
473 : i_first_zero = i_max_n_zero;
474 : n_zeros = 0;
475 : for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
476 : {
477 : u32 is_zero = a->as_u16[i] == 0;
478 : if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
479 : {
480 : i_first_zero = i;
481 : n_zeros = 0;
482 : }
483 : n_zeros += is_zero;
484 : if ((!is_zero && n_zeros > max_n_zeros)
485 : || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
486 : {
487 : i_max_n_zero = i_first_zero;
488 : max_n_zeros = n_zeros;
489 : i_first_zero = ARRAY_LEN (a->as_u16);
490 : n_zeros = 0;
491 : }
492 : }
493 :
494 : last_double_colon = 0;
495 : for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
496 : {
497 : if (i == i_max_n_zero && max_n_zeros > 1)
498 : {
499 : s = format (s, "::");
500 : i += max_n_zeros - 1;
501 : last_double_colon = 1;
502 : }
503 : else
504 : {
505 : s = format (s, "%s%x",
506 : (last_double_colon || i == 0) ? "" : ":",
507 : clib_net_to_host_u16 (a->as_u16[i]));
508 : last_double_colon = 0;
509 : }
510 : }
511 :
512 : return s;
513 : }
514 :
515 : /* Format an IP46 address. */
516 : u8 *
517 : format_ip46_address (u8 * s, va_list * args)
518 : {
519 : ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
520 : ip46_type_t type = va_arg (*args, ip46_type_t);
521 : int is_ip4 = 1;
522 :
523 : switch (type)
524 : {
525 : case IP46_TYPE_ANY:
526 : is_ip4 = ip46_address_is_ip4 (ip46);
527 : break;
528 : case IP46_TYPE_IP4:
529 : is_ip4 = 1;
530 : break;
531 : case IP46_TYPE_IP6:
532 : is_ip4 = 0;
533 : break;
534 : }
535 :
536 : return is_ip4 ?
537 : format (s, "%U", format_ip4_address, &ip46->ip4) :
538 : format (s, "%U", format_ip6_address, &ip46->ip6);
539 : }
540 :
541 : u8 *
542 : format_ethernet_address (u8 * s, va_list * args)
543 : {
544 : u8 *a = va_arg (*args, u8 *);
545 :
546 : return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
547 : a[0], a[1], a[2], a[3], a[4], a[5]);
548 : }
549 : #endif
550 :
551 : void
552 130444 : ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
553 : {
554 130444 : if (is_ip4)
555 125522 : dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
556 : else
557 4922 : clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
558 : sizeof (ip6_address_t));
559 130444 : }
560 :
561 :
562 0 : static void vl_api_get_first_msg_id_reply_t_handler
563 : (vl_api_get_first_msg_id_reply_t * mp)
564 : {
565 0 : vat_main_t *vam = &vat_main;
566 0 : i32 retval = ntohl (mp->retval);
567 :
568 0 : if (vam->async_mode)
569 : {
570 0 : vam->async_errors += (retval < 0);
571 : }
572 : else
573 : {
574 0 : vam->retval = retval;
575 0 : vam->result_ready = 1;
576 : }
577 0 : if (retval >= 0)
578 : {
579 0 : errmsg ("first message id %d", ntohs (mp->first_msg_id));
580 : }
581 0 : }
582 :
583 0 : static void vl_api_get_first_msg_id_reply_t_handler_json
584 : (vl_api_get_first_msg_id_reply_t * mp)
585 : {
586 0 : vat_main_t *vam = &vat_main;
587 : vat_json_node_t node;
588 :
589 0 : vat_json_init_object (&node);
590 0 : vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
591 0 : vat_json_object_add_uint (&node, "first_msg_id",
592 0 : (uint) ntohs (mp->first_msg_id));
593 :
594 0 : vat_json_print (vam->ofp, &node);
595 0 : vat_json_free (&node);
596 :
597 0 : vam->retval = ntohl (mp->retval);
598 0 : vam->result_ready = 1;
599 0 : }
600 :
601 : /* Format hex dump. */
602 : u8 *
603 1133310 : format_hex_bytes (u8 * s, va_list * va)
604 : {
605 1133310 : u8 *bytes = va_arg (*va, u8 *);
606 1133310 : int n_bytes = va_arg (*va, int);
607 : uword i;
608 :
609 : /* Print short or long form depending on byte count. */
610 1133310 : uword short_form = n_bytes <= 32;
611 1133310 : u32 indent = format_get_indent (s);
612 :
613 1133310 : if (n_bytes == 0)
614 0 : return s;
615 :
616 83164000 : for (i = 0; i < n_bytes; i++)
617 : {
618 82030700 : if (!short_form && (i % 32) == 0)
619 2451700 : s = format (s, "%08x: ", i);
620 82030700 : s = format (s, "%02x", bytes[i]);
621 82030700 : if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
622 1702000 : s = format (s, "\n%U", format_white_space, indent);
623 : }
624 :
625 1133310 : return s;
626 : }
627 :
628 : static void
629 2 : vl_api_control_ping_reply_t_handler (vl_api_control_ping_reply_t *mp)
630 : {
631 2 : vat_main_t *vam = &vat_main;
632 2 : i32 retval = ntohl (mp->retval);
633 2 : if (vam->async_mode)
634 : {
635 0 : vam->async_errors += (retval < 0);
636 : }
637 : else
638 : {
639 2 : vam->retval = retval;
640 2 : vam->result_ready = 1;
641 : }
642 2 : if (vam->socket_client_main)
643 0 : vam->socket_client_main->control_pings_outstanding--;
644 2 : }
645 :
646 : static void
647 0 : vl_api_control_ping_reply_t_handler_json (vl_api_control_ping_reply_t *mp)
648 : {
649 0 : vat_main_t *vam = &vat_main;
650 0 : i32 retval = ntohl (mp->retval);
651 :
652 0 : if (VAT_JSON_NONE != vam->json_tree.type)
653 : {
654 0 : vat_json_print (vam->ofp, &vam->json_tree);
655 0 : vat_json_free (&vam->json_tree);
656 0 : vam->json_tree.type = VAT_JSON_NONE;
657 : }
658 : else
659 : {
660 : /* just print [] */
661 0 : vat_json_init_array (&vam->json_tree);
662 0 : vat_json_print (vam->ofp, &vam->json_tree);
663 0 : vam->json_tree.type = VAT_JSON_NONE;
664 : }
665 :
666 0 : vam->retval = retval;
667 0 : vam->result_ready = 1;
668 0 : }
669 :
670 : /*
671 : * Generate boilerplate reply handlers, which
672 : * dig the return value out of the xxx_reply_t API message,
673 : * stick it into vam->retval, and set vam->result_ready
674 : *
675 : * Could also do this by pointing N message decode slots at
676 : * a single function, but that could break in subtle ways.
677 : */
678 :
679 : #define foreach_standard_reply_retval_handler
680 :
681 : #define _(n) \
682 : static void vl_api_##n##_t_handler \
683 : (vl_api_##n##_t * mp) \
684 : { \
685 : vat_main_t * vam = &vat_main; \
686 : i32 retval = ntohl(mp->retval); \
687 : if (vam->async_mode) { \
688 : vam->async_errors += (retval < 0); \
689 : } else { \
690 : vam->retval = retval; \
691 : vam->result_ready = 1; \
692 : } \
693 : }
694 : foreach_standard_reply_retval_handler;
695 : #undef _
696 :
697 : #define _(n) \
698 : static void vl_api_##n##_t_handler_json \
699 : (vl_api_##n##_t * mp) \
700 : { \
701 : vat_main_t * vam = &vat_main; \
702 : vat_json_node_t node; \
703 : vat_json_init_object(&node); \
704 : vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
705 : vat_json_print(vam->ofp, &node); \
706 : vam->retval = ntohl(mp->retval); \
707 : vam->result_ready = 1; \
708 : }
709 : foreach_standard_reply_retval_handler;
710 : #undef _
711 :
712 : /*
713 : * Table of message reply handlers, must include boilerplate handlers
714 : * we just generated
715 : */
716 :
717 : #define foreach_vpe_api_reply_msg \
718 : _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
719 : _ (CONTROL_PING_REPLY, control_ping_reply)
720 :
721 : #define foreach_standalone_reply_msg \
722 :
723 : typedef struct
724 : {
725 : u8 *name;
726 : u32 value;
727 : } name_sort_t;
728 :
729 : #define STR_VTR_OP_CASE(op) \
730 : case L2_VTR_ ## op: \
731 : return "" # op;
732 :
733 : static const char *
734 0 : str_vtr_op (u32 vtr_op)
735 : {
736 0 : switch (vtr_op)
737 : {
738 0 : STR_VTR_OP_CASE (DISABLED);
739 0 : STR_VTR_OP_CASE (PUSH_1);
740 0 : STR_VTR_OP_CASE (PUSH_2);
741 0 : STR_VTR_OP_CASE (POP_1);
742 0 : STR_VTR_OP_CASE (POP_2);
743 0 : STR_VTR_OP_CASE (TRANSLATE_1_1);
744 0 : STR_VTR_OP_CASE (TRANSLATE_1_2);
745 0 : STR_VTR_OP_CASE (TRANSLATE_2_1);
746 0 : STR_VTR_OP_CASE (TRANSLATE_2_2);
747 : }
748 :
749 0 : return "UNKNOWN";
750 : }
751 :
752 : uword
753 170775 : unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
754 : {
755 170775 : vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
756 : u32 x[4];
757 :
758 170775 : if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
759 0 : return 0;
760 :
761 170775 : addr->domain = x[0];
762 170775 : addr->bus = x[1];
763 170775 : addr->slot = x[2];
764 170775 : addr->function = x[3];
765 :
766 170775 : return 1;
767 : }
768 :
769 : uword
770 0 : unformat_fib_path (unformat_input_t *input, va_list *args)
771 : {
772 0 : vat_main_t *vam = va_arg (*args, vat_main_t *);
773 0 : vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
774 : u32 weight, preference;
775 : mpls_label_t out_label;
776 :
777 0 : clib_memset (path, 0, sizeof (*path));
778 0 : path->weight = 1;
779 0 : path->sw_if_index = ~0;
780 0 : path->rpf_id = ~0;
781 0 : path->n_labels = 0;
782 :
783 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
784 : {
785 0 : if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
786 : &path->nh.address.ip4, api_unformat_sw_if_index, vam,
787 : &path->sw_if_index))
788 : {
789 0 : path->proto = FIB_API_PATH_NH_PROTO_IP4;
790 : }
791 0 : else if (unformat (input, "%U %U",
792 : unformat_vl_api_ip6_address,
793 : &path->nh.address.ip6,
794 : api_unformat_sw_if_index, vam, &path->sw_if_index))
795 : {
796 0 : path->proto = FIB_API_PATH_NH_PROTO_IP6;
797 : }
798 0 : else if (unformat (input, "weight %u", &weight))
799 : {
800 0 : path->weight = weight;
801 : }
802 0 : else if (unformat (input, "preference %u", &preference))
803 : {
804 0 : path->preference = preference;
805 : }
806 0 : else if (unformat (input, "%U next-hop-table %d",
807 : unformat_vl_api_ip4_address,
808 : &path->nh.address.ip4, &path->table_id))
809 : {
810 0 : path->proto = FIB_API_PATH_NH_PROTO_IP4;
811 : }
812 0 : else if (unformat (input, "%U next-hop-table %d",
813 : unformat_vl_api_ip6_address,
814 : &path->nh.address.ip6, &path->table_id))
815 : {
816 0 : path->proto = FIB_API_PATH_NH_PROTO_IP6;
817 : }
818 0 : else if (unformat (input, "%U",
819 : unformat_vl_api_ip4_address, &path->nh.address.ip4))
820 : {
821 : /*
822 : * the recursive next-hops are by default in the default table
823 : */
824 0 : path->table_id = 0;
825 0 : path->sw_if_index = ~0;
826 0 : path->proto = FIB_API_PATH_NH_PROTO_IP4;
827 : }
828 0 : else if (unformat (input, "%U",
829 : unformat_vl_api_ip6_address, &path->nh.address.ip6))
830 : {
831 : /*
832 : * the recursive next-hops are by default in the default table
833 : */
834 0 : path->table_id = 0;
835 0 : path->sw_if_index = ~0;
836 0 : path->proto = FIB_API_PATH_NH_PROTO_IP6;
837 : }
838 0 : else if (unformat (input, "resolve-via-host"))
839 : {
840 0 : path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
841 : }
842 0 : else if (unformat (input, "resolve-via-attached"))
843 : {
844 0 : path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
845 : }
846 0 : else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
847 : {
848 0 : path->type = FIB_API_PATH_TYPE_LOCAL;
849 0 : path->sw_if_index = ~0;
850 0 : path->proto = FIB_API_PATH_NH_PROTO_IP4;
851 : }
852 0 : else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
853 : {
854 0 : path->type = FIB_API_PATH_TYPE_LOCAL;
855 0 : path->sw_if_index = ~0;
856 0 : path->proto = FIB_API_PATH_NH_PROTO_IP6;
857 : }
858 0 : else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
859 : ;
860 0 : else if (unformat (input, "via-label %d", &path->nh.via_label))
861 : {
862 0 : path->proto = FIB_API_PATH_NH_PROTO_MPLS;
863 0 : path->sw_if_index = ~0;
864 : }
865 0 : else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
866 : {
867 0 : path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
868 0 : path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
869 : }
870 0 : else if (unformat (input, "local"))
871 : {
872 0 : path->type = FIB_API_PATH_TYPE_LOCAL;
873 : }
874 0 : else if (unformat (input, "out-labels"))
875 : {
876 0 : while (unformat (input, "%d", &out_label))
877 : {
878 0 : path->label_stack[path->n_labels].label = out_label;
879 0 : path->label_stack[path->n_labels].is_uniform = 0;
880 0 : path->label_stack[path->n_labels].ttl = 64;
881 0 : path->n_labels++;
882 : }
883 : }
884 0 : else if (unformat (input, "via"))
885 : {
886 : /* new path, back up and return */
887 0 : unformat_put_input (input);
888 0 : unformat_put_input (input);
889 0 : unformat_put_input (input);
890 0 : unformat_put_input (input);
891 0 : break;
892 : }
893 : else
894 : {
895 0 : return (0);
896 : }
897 : }
898 :
899 0 : path->proto = ntohl (path->proto);
900 0 : path->type = ntohl (path->type);
901 0 : path->flags = ntohl (path->flags);
902 0 : path->table_id = ntohl (path->table_id);
903 0 : path->sw_if_index = ntohl (path->sw_if_index);
904 :
905 0 : return (1);
906 : }
907 :
908 : #define foreach_create_subif_bit \
909 : _(no_tags) \
910 : _(one_tag) \
911 : _(two_tags) \
912 : _(dot1ad) \
913 : _(exact_match) \
914 : _(default_sub) \
915 : _(outer_vlan_id_any) \
916 : _(inner_vlan_id_any)
917 :
918 : #define foreach_create_subif_flag \
919 : _(0, "no_tags") \
920 : _(1, "one_tag") \
921 : _(2, "two_tags") \
922 : _(3, "dot1ad") \
923 : _(4, "exact_match") \
924 : _(5, "default_sub") \
925 : _(6, "outer_vlan_id_any") \
926 : _(7, "inner_vlan_id_any")
927 :
928 :
929 : #define foreach_tcp_proto_field \
930 : _ (src_port) \
931 : _ (dst_port)
932 :
933 : #define foreach_udp_proto_field \
934 : _ (src_port) \
935 : _ (dst_port)
936 :
937 : #define foreach_ip4_proto_field \
938 : _ (src_address) \
939 : _ (dst_address) \
940 : _ (tos) \
941 : _ (length) \
942 : _ (fragment_id) \
943 : _ (ttl) \
944 : _ (protocol) \
945 : _ (checksum)
946 :
947 : typedef struct
948 : {
949 : u16 src_port, dst_port;
950 : } tcpudp_header_t;
951 :
952 : #if VPP_API_TEST_BUILTIN == 0
953 : uword
954 : unformat_tcp_mask (unformat_input_t *input, va_list *args)
955 : {
956 : u8 **maskp = va_arg (*args, u8 **);
957 : u8 *mask = 0;
958 : u8 found_something = 0;
959 : tcp_header_t *tcp;
960 :
961 : #define _(a) u8 a = 0;
962 : foreach_tcp_proto_field;
963 : #undef _
964 :
965 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
966 : {
967 : if (0)
968 : ;
969 : #define _(a) else if (unformat (input, #a)) a = 1;
970 : foreach_tcp_proto_field
971 : #undef _
972 : else break;
973 : }
974 :
975 : #define _(a) found_something += a;
976 : foreach_tcp_proto_field;
977 : #undef _
978 :
979 : if (found_something == 0)
980 : return 0;
981 :
982 : vec_validate (mask, sizeof (*tcp) - 1);
983 :
984 : tcp = (tcp_header_t *) mask;
985 :
986 : #define _(a) \
987 : if (a) \
988 : clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
989 : foreach_tcp_proto_field;
990 : #undef _
991 :
992 : *maskp = mask;
993 : return 1;
994 : }
995 :
996 : uword
997 : unformat_udp_mask (unformat_input_t *input, va_list *args)
998 : {
999 : u8 **maskp = va_arg (*args, u8 **);
1000 : u8 *mask = 0;
1001 : u8 found_something = 0;
1002 : udp_header_t *udp;
1003 :
1004 : #define _(a) u8 a = 0;
1005 : foreach_udp_proto_field;
1006 : #undef _
1007 :
1008 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1009 : {
1010 : if (0)
1011 : ;
1012 : #define _(a) else if (unformat (input, #a)) a = 1;
1013 : foreach_udp_proto_field
1014 : #undef _
1015 : else break;
1016 : }
1017 :
1018 : #define _(a) found_something += a;
1019 : foreach_udp_proto_field;
1020 : #undef _
1021 :
1022 : if (found_something == 0)
1023 : return 0;
1024 :
1025 : vec_validate (mask, sizeof (*udp) - 1);
1026 :
1027 : udp = (udp_header_t *) mask;
1028 :
1029 : #define _(a) \
1030 : if (a) \
1031 : clib_memset (&udp->a, 0xff, sizeof (udp->a));
1032 : foreach_udp_proto_field;
1033 : #undef _
1034 :
1035 : *maskp = mask;
1036 : return 1;
1037 : }
1038 :
1039 : uword
1040 : unformat_l4_mask (unformat_input_t *input, va_list *args)
1041 : {
1042 : u8 **maskp = va_arg (*args, u8 **);
1043 : u16 src_port = 0, dst_port = 0;
1044 : tcpudp_header_t *tcpudp;
1045 :
1046 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1047 : {
1048 : if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
1049 : return 1;
1050 : else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
1051 : return 1;
1052 : else if (unformat (input, "src_port"))
1053 : src_port = 0xFFFF;
1054 : else if (unformat (input, "dst_port"))
1055 : dst_port = 0xFFFF;
1056 : else
1057 : return 0;
1058 : }
1059 :
1060 : if (!src_port && !dst_port)
1061 : return 0;
1062 :
1063 : u8 *mask = 0;
1064 : vec_validate (mask, sizeof (tcpudp_header_t) - 1);
1065 :
1066 : tcpudp = (tcpudp_header_t *) mask;
1067 : tcpudp->src_port = src_port;
1068 : tcpudp->dst_port = dst_port;
1069 :
1070 : *maskp = mask;
1071 :
1072 : return 1;
1073 : }
1074 :
1075 : uword
1076 : unformat_ip4_mask (unformat_input_t * input, va_list * args)
1077 : {
1078 : u8 **maskp = va_arg (*args, u8 **);
1079 : u8 *mask = 0;
1080 : u8 found_something = 0;
1081 : ip4_header_t *ip;
1082 :
1083 : #define _(a) u8 a=0;
1084 : foreach_ip4_proto_field;
1085 : #undef _
1086 : u8 version = 0;
1087 : u8 hdr_length = 0;
1088 :
1089 :
1090 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1091 : {
1092 : if (unformat (input, "version"))
1093 : version = 1;
1094 : else if (unformat (input, "hdr_length"))
1095 : hdr_length = 1;
1096 : else if (unformat (input, "src"))
1097 : src_address = 1;
1098 : else if (unformat (input, "dst"))
1099 : dst_address = 1;
1100 : else if (unformat (input, "proto"))
1101 : protocol = 1;
1102 :
1103 : #define _(a) else if (unformat (input, #a)) a=1;
1104 : foreach_ip4_proto_field
1105 : #undef _
1106 : else
1107 : break;
1108 : }
1109 :
1110 : #define _(a) found_something += a;
1111 : foreach_ip4_proto_field;
1112 : #undef _
1113 :
1114 : if (found_something == 0)
1115 : return 0;
1116 :
1117 : vec_validate (mask, sizeof (*ip) - 1);
1118 :
1119 : ip = (ip4_header_t *) mask;
1120 :
1121 : #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
1122 : foreach_ip4_proto_field;
1123 : #undef _
1124 :
1125 : ip->ip_version_and_header_length = 0;
1126 :
1127 : if (version)
1128 : ip->ip_version_and_header_length |= 0xF0;
1129 :
1130 : if (hdr_length)
1131 : ip->ip_version_and_header_length |= 0x0F;
1132 :
1133 : *maskp = mask;
1134 : return 1;
1135 : }
1136 :
1137 : #define foreach_ip6_proto_field \
1138 : _(src_address) \
1139 : _(dst_address) \
1140 : _(payload_length) \
1141 : _(hop_limit) \
1142 : _(protocol)
1143 :
1144 : uword
1145 : unformat_ip6_mask (unformat_input_t * input, va_list * args)
1146 : {
1147 : u8 **maskp = va_arg (*args, u8 **);
1148 : u8 *mask = 0;
1149 : u8 found_something = 0;
1150 : ip6_header_t *ip;
1151 : u32 ip_version_traffic_class_and_flow_label;
1152 :
1153 : #define _(a) u8 a=0;
1154 : foreach_ip6_proto_field;
1155 : #undef _
1156 : u8 version = 0;
1157 : u8 traffic_class = 0;
1158 : u8 flow_label = 0;
1159 :
1160 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1161 : {
1162 : if (unformat (input, "version"))
1163 : version = 1;
1164 : else if (unformat (input, "traffic-class"))
1165 : traffic_class = 1;
1166 : else if (unformat (input, "flow-label"))
1167 : flow_label = 1;
1168 : else if (unformat (input, "src"))
1169 : src_address = 1;
1170 : else if (unformat (input, "dst"))
1171 : dst_address = 1;
1172 : else if (unformat (input, "proto"))
1173 : protocol = 1;
1174 :
1175 : #define _(a) else if (unformat (input, #a)) a=1;
1176 : foreach_ip6_proto_field
1177 : #undef _
1178 : else
1179 : break;
1180 : }
1181 :
1182 : #define _(a) found_something += a;
1183 : foreach_ip6_proto_field;
1184 : #undef _
1185 :
1186 : if (found_something == 0)
1187 : return 0;
1188 :
1189 : vec_validate (mask, sizeof (*ip) - 1);
1190 :
1191 : ip = (ip6_header_t *) mask;
1192 :
1193 : #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
1194 : foreach_ip6_proto_field;
1195 : #undef _
1196 :
1197 : ip_version_traffic_class_and_flow_label = 0;
1198 :
1199 : if (version)
1200 : ip_version_traffic_class_and_flow_label |= 0xF0000000;
1201 :
1202 : if (traffic_class)
1203 : ip_version_traffic_class_and_flow_label |= 0x0FF00000;
1204 :
1205 : if (flow_label)
1206 : ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
1207 :
1208 : ip->ip_version_traffic_class_and_flow_label =
1209 : clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1210 :
1211 : *maskp = mask;
1212 : return 1;
1213 : }
1214 :
1215 : uword
1216 : unformat_l3_mask (unformat_input_t * input, va_list * args)
1217 : {
1218 : u8 **maskp = va_arg (*args, u8 **);
1219 :
1220 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1221 : {
1222 : if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
1223 : return 1;
1224 : else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
1225 : return 1;
1226 : else
1227 : break;
1228 : }
1229 : return 0;
1230 : }
1231 :
1232 : uword
1233 : unformat_l2_mask (unformat_input_t * input, va_list * args)
1234 : {
1235 : u8 **maskp = va_arg (*args, u8 **);
1236 : u8 *mask = 0;
1237 : u8 src = 0;
1238 : u8 dst = 0;
1239 : u8 proto = 0;
1240 : u8 tag1 = 0;
1241 : u8 tag2 = 0;
1242 : u8 ignore_tag1 = 0;
1243 : u8 ignore_tag2 = 0;
1244 : u8 cos1 = 0;
1245 : u8 cos2 = 0;
1246 : u8 dot1q = 0;
1247 : u8 dot1ad = 0;
1248 : int len = 14;
1249 :
1250 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1251 : {
1252 : if (unformat (input, "src"))
1253 : src = 1;
1254 : else if (unformat (input, "dst"))
1255 : dst = 1;
1256 : else if (unformat (input, "proto"))
1257 : proto = 1;
1258 : else if (unformat (input, "tag1"))
1259 : tag1 = 1;
1260 : else if (unformat (input, "tag2"))
1261 : tag2 = 1;
1262 : else if (unformat (input, "ignore-tag1"))
1263 : ignore_tag1 = 1;
1264 : else if (unformat (input, "ignore-tag2"))
1265 : ignore_tag2 = 1;
1266 : else if (unformat (input, "cos1"))
1267 : cos1 = 1;
1268 : else if (unformat (input, "cos2"))
1269 : cos2 = 1;
1270 : else if (unformat (input, "dot1q"))
1271 : dot1q = 1;
1272 : else if (unformat (input, "dot1ad"))
1273 : dot1ad = 1;
1274 : else
1275 : break;
1276 : }
1277 : if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
1278 : ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1279 : return 0;
1280 :
1281 : if (tag1 || ignore_tag1 || cos1 || dot1q)
1282 : len = 18;
1283 : if (tag2 || ignore_tag2 || cos2 || dot1ad)
1284 : len = 22;
1285 :
1286 : vec_validate (mask, len - 1);
1287 :
1288 : if (dst)
1289 : clib_memset (mask, 0xff, 6);
1290 :
1291 : if (src)
1292 : clib_memset (mask + 6, 0xff, 6);
1293 :
1294 : if (tag2 || dot1ad)
1295 : {
1296 : /* inner vlan tag */
1297 : if (tag2)
1298 : {
1299 : mask[19] = 0xff;
1300 : mask[18] = 0x0f;
1301 : }
1302 : if (cos2)
1303 : mask[18] |= 0xe0;
1304 : if (proto)
1305 : mask[21] = mask[20] = 0xff;
1306 : if (tag1)
1307 : {
1308 : mask[15] = 0xff;
1309 : mask[14] = 0x0f;
1310 : }
1311 : if (cos1)
1312 : mask[14] |= 0xe0;
1313 : *maskp = mask;
1314 : return 1;
1315 : }
1316 : if (tag1 | dot1q)
1317 : {
1318 : if (tag1)
1319 : {
1320 : mask[15] = 0xff;
1321 : mask[14] = 0x0f;
1322 : }
1323 : if (cos1)
1324 : mask[14] |= 0xe0;
1325 : if (proto)
1326 : mask[16] = mask[17] = 0xff;
1327 :
1328 : *maskp = mask;
1329 : return 1;
1330 : }
1331 : if (cos2)
1332 : mask[18] |= 0xe0;
1333 : if (cos1)
1334 : mask[14] |= 0xe0;
1335 : if (proto)
1336 : mask[12] = mask[13] = 0xff;
1337 :
1338 : *maskp = mask;
1339 : return 1;
1340 : }
1341 :
1342 : uword
1343 : unformat_classify_mask (unformat_input_t * input, va_list * args)
1344 : {
1345 : u8 **maskp = va_arg (*args, u8 **);
1346 : u32 *skipp = va_arg (*args, u32 *);
1347 : u32 *matchp = va_arg (*args, u32 *);
1348 : u32 match;
1349 : u8 *mask = 0;
1350 : u8 *l2 = 0;
1351 : u8 *l3 = 0;
1352 : u8 *l4 = 0;
1353 : int i;
1354 :
1355 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1356 : {
1357 : if (unformat (input, "hex %U", unformat_hex_string, &mask))
1358 : ;
1359 : else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
1360 : ;
1361 : else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
1362 : ;
1363 : else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
1364 : ;
1365 : else
1366 : break;
1367 : }
1368 :
1369 : if (l4 && !l3)
1370 : {
1371 : vec_free (mask);
1372 : vec_free (l2);
1373 : vec_free (l4);
1374 : return 0;
1375 : }
1376 :
1377 : if (mask || l2 || l3 || l4)
1378 : {
1379 : if (l2 || l3 || l4)
1380 : {
1381 : /* "With a free Ethernet header in every package" */
1382 : if (l2 == 0)
1383 : vec_validate (l2, 13);
1384 : mask = l2;
1385 : if (vec_len (l3))
1386 : {
1387 : vec_append (mask, l3);
1388 : vec_free (l3);
1389 : }
1390 : if (vec_len (l4))
1391 : {
1392 : vec_append (mask, l4);
1393 : vec_free (l4);
1394 : }
1395 : }
1396 :
1397 : /* Scan forward looking for the first significant mask octet */
1398 : for (i = 0; i < vec_len (mask); i++)
1399 : if (mask[i])
1400 : break;
1401 :
1402 : /* compute (skip, match) params */
1403 : *skipp = i / sizeof (u32x4);
1404 : vec_delete (mask, *skipp * sizeof (u32x4), 0);
1405 :
1406 : /* Pad mask to an even multiple of the vector size */
1407 : while (vec_len (mask) % sizeof (u32x4))
1408 : vec_add1 (mask, 0);
1409 :
1410 : match = vec_len (mask) / sizeof (u32x4);
1411 :
1412 : for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
1413 : {
1414 : u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
1415 : if (*tmp || *(tmp + 1))
1416 : break;
1417 : match--;
1418 : }
1419 : if (match == 0)
1420 : clib_warning ("BUG: match 0");
1421 :
1422 : vec_set_len (mask, match * sizeof (u32x4));
1423 :
1424 : *matchp = match;
1425 : *maskp = mask;
1426 :
1427 : return 1;
1428 : }
1429 :
1430 : return 0;
1431 : }
1432 : #endif /* VPP_API_TEST_BUILTIN */
1433 :
1434 : #define foreach_l2_next \
1435 : _(drop, DROP) \
1436 : _(ethernet, ETHERNET_INPUT) \
1437 : _(ip4, IP4_INPUT) \
1438 : _(ip6, IP6_INPUT)
1439 :
1440 : uword
1441 0 : unformat_l2_next_index (unformat_input_t * input, va_list * args)
1442 : {
1443 0 : u32 *miss_next_indexp = va_arg (*args, u32 *);
1444 0 : u32 next_index = 0;
1445 : u32 tmp;
1446 :
1447 : #define _(n,N) \
1448 : if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
1449 0 : foreach_l2_next;
1450 : #undef _
1451 :
1452 0 : if (unformat (input, "%d", &tmp))
1453 : {
1454 0 : next_index = tmp;
1455 0 : goto out;
1456 : }
1457 :
1458 0 : return 0;
1459 :
1460 0 : out:
1461 0 : *miss_next_indexp = next_index;
1462 0 : return 1;
1463 : }
1464 :
1465 : #define foreach_ip_next \
1466 : _(drop, DROP) \
1467 : _(local, LOCAL) \
1468 : _(rewrite, REWRITE)
1469 :
1470 : uword
1471 0 : api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
1472 : {
1473 0 : u32 *miss_next_indexp = va_arg (*args, u32 *);
1474 0 : u32 next_index = 0;
1475 : u32 tmp;
1476 :
1477 : #define _(n,N) \
1478 : if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
1479 0 : foreach_ip_next;
1480 : #undef _
1481 :
1482 0 : if (unformat (input, "%d", &tmp))
1483 : {
1484 0 : next_index = tmp;
1485 0 : goto out;
1486 : }
1487 :
1488 0 : return 0;
1489 :
1490 0 : out:
1491 0 : *miss_next_indexp = next_index;
1492 0 : return 1;
1493 : }
1494 :
1495 : #define foreach_acl_next \
1496 : _(deny, DENY)
1497 :
1498 : uword
1499 0 : api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
1500 : {
1501 0 : u32 *miss_next_indexp = va_arg (*args, u32 *);
1502 0 : u32 next_index = 0;
1503 : u32 tmp;
1504 :
1505 : #define _(n,N) \
1506 : if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
1507 0 : foreach_acl_next;
1508 : #undef _
1509 :
1510 0 : if (unformat (input, "permit"))
1511 : {
1512 0 : next_index = ~0;
1513 0 : goto out;
1514 : }
1515 0 : else if (unformat (input, "%d", &tmp))
1516 : {
1517 0 : next_index = tmp;
1518 0 : goto out;
1519 : }
1520 :
1521 0 : return 0;
1522 :
1523 0 : out:
1524 0 : *miss_next_indexp = next_index;
1525 0 : return 1;
1526 : }
1527 :
1528 : uword
1529 0 : unformat_policer_precolor (unformat_input_t * input, va_list * args)
1530 : {
1531 0 : u32 *r = va_arg (*args, u32 *);
1532 :
1533 0 : if (unformat (input, "conform-color"))
1534 0 : *r = POLICE_CONFORM;
1535 0 : else if (unformat (input, "exceed-color"))
1536 0 : *r = POLICE_EXCEED;
1537 : else
1538 0 : return 0;
1539 :
1540 0 : return 1;
1541 : }
1542 :
1543 : #if VPP_API_TEST_BUILTIN == 0
1544 : uword
1545 : unformat_l4_match (unformat_input_t * input, va_list * args)
1546 : {
1547 : u8 **matchp = va_arg (*args, u8 **);
1548 :
1549 : u8 *proto_header = 0;
1550 : int src_port = 0;
1551 : int dst_port = 0;
1552 :
1553 : tcpudp_header_t h;
1554 :
1555 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1556 : {
1557 : if (unformat (input, "src_port %d", &src_port))
1558 : ;
1559 : else if (unformat (input, "dst_port %d", &dst_port))
1560 : ;
1561 : else
1562 : return 0;
1563 : }
1564 :
1565 : h.src_port = clib_host_to_net_u16 (src_port);
1566 : h.dst_port = clib_host_to_net_u16 (dst_port);
1567 : vec_validate (proto_header, sizeof (h) - 1);
1568 : memcpy (proto_header, &h, sizeof (h));
1569 :
1570 : *matchp = proto_header;
1571 :
1572 : return 1;
1573 : }
1574 :
1575 : uword
1576 : unformat_ip4_match (unformat_input_t * input, va_list * args)
1577 : {
1578 : u8 **matchp = va_arg (*args, u8 **);
1579 : u8 *match = 0;
1580 : ip4_header_t *ip;
1581 : int version = 0;
1582 : u32 version_val;
1583 : int hdr_length = 0;
1584 : u32 hdr_length_val;
1585 : int src = 0, dst = 0;
1586 : ip4_address_t src_val, dst_val;
1587 : int proto = 0;
1588 : u32 proto_val;
1589 : int tos = 0;
1590 : u32 tos_val;
1591 : int length = 0;
1592 : u32 length_val;
1593 : int fragment_id = 0;
1594 : u32 fragment_id_val;
1595 : int ttl = 0;
1596 : int ttl_val;
1597 : int checksum = 0;
1598 : u32 checksum_val;
1599 :
1600 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1601 : {
1602 : if (unformat (input, "version %d", &version_val))
1603 : version = 1;
1604 : else if (unformat (input, "hdr_length %d", &hdr_length_val))
1605 : hdr_length = 1;
1606 : else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
1607 : src = 1;
1608 : else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
1609 : dst = 1;
1610 : else if (unformat (input, "proto %d", &proto_val))
1611 : proto = 1;
1612 : else if (unformat (input, "tos %d", &tos_val))
1613 : tos = 1;
1614 : else if (unformat (input, "length %d", &length_val))
1615 : length = 1;
1616 : else if (unformat (input, "fragment_id %d", &fragment_id_val))
1617 : fragment_id = 1;
1618 : else if (unformat (input, "ttl %d", &ttl_val))
1619 : ttl = 1;
1620 : else if (unformat (input, "checksum %d", &checksum_val))
1621 : checksum = 1;
1622 : else
1623 : break;
1624 : }
1625 :
1626 : if (version + hdr_length + src + dst + proto + tos + length + fragment_id
1627 : + ttl + checksum == 0)
1628 : return 0;
1629 :
1630 : /*
1631 : * Aligned because we use the real comparison functions
1632 : */
1633 : vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1634 :
1635 : ip = (ip4_header_t *) match;
1636 :
1637 : /* These are realistically matched in practice */
1638 : if (src)
1639 : ip->src_address.as_u32 = src_val.as_u32;
1640 :
1641 : if (dst)
1642 : ip->dst_address.as_u32 = dst_val.as_u32;
1643 :
1644 : if (proto)
1645 : ip->protocol = proto_val;
1646 :
1647 :
1648 : /* These are not, but they're included for completeness */
1649 : if (version)
1650 : ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
1651 :
1652 : if (hdr_length)
1653 : ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
1654 :
1655 : if (tos)
1656 : ip->tos = tos_val;
1657 :
1658 : if (length)
1659 : ip->length = clib_host_to_net_u16 (length_val);
1660 :
1661 : if (ttl)
1662 : ip->ttl = ttl_val;
1663 :
1664 : if (checksum)
1665 : ip->checksum = clib_host_to_net_u16 (checksum_val);
1666 :
1667 : *matchp = match;
1668 : return 1;
1669 : }
1670 :
1671 : uword
1672 : unformat_ip6_match (unformat_input_t * input, va_list * args)
1673 : {
1674 : u8 **matchp = va_arg (*args, u8 **);
1675 : u8 *match = 0;
1676 : ip6_header_t *ip;
1677 : int version = 0;
1678 : u32 version_val;
1679 : u8 traffic_class = 0;
1680 : u32 traffic_class_val = 0;
1681 : u8 flow_label = 0;
1682 : u8 flow_label_val;
1683 : int src = 0, dst = 0;
1684 : ip6_address_t src_val, dst_val;
1685 : int proto = 0;
1686 : u32 proto_val;
1687 : int payload_length = 0;
1688 : u32 payload_length_val;
1689 : int hop_limit = 0;
1690 : int hop_limit_val;
1691 : u32 ip_version_traffic_class_and_flow_label;
1692 :
1693 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1694 : {
1695 : if (unformat (input, "version %d", &version_val))
1696 : version = 1;
1697 : else if (unformat (input, "traffic_class %d", &traffic_class_val))
1698 : traffic_class = 1;
1699 : else if (unformat (input, "flow_label %d", &flow_label_val))
1700 : flow_label = 1;
1701 : else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
1702 : src = 1;
1703 : else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
1704 : dst = 1;
1705 : else if (unformat (input, "proto %d", &proto_val))
1706 : proto = 1;
1707 : else if (unformat (input, "payload_length %d", &payload_length_val))
1708 : payload_length = 1;
1709 : else if (unformat (input, "hop_limit %d", &hop_limit_val))
1710 : hop_limit = 1;
1711 : else
1712 : break;
1713 : }
1714 :
1715 : if (version + traffic_class + flow_label + src + dst + proto +
1716 : payload_length + hop_limit == 0)
1717 : return 0;
1718 :
1719 : /*
1720 : * Aligned because we use the real comparison functions
1721 : */
1722 : vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1723 :
1724 : ip = (ip6_header_t *) match;
1725 :
1726 : if (src)
1727 : clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
1728 :
1729 : if (dst)
1730 : clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
1731 :
1732 : if (proto)
1733 : ip->protocol = proto_val;
1734 :
1735 : ip_version_traffic_class_and_flow_label = 0;
1736 :
1737 : if (version)
1738 : ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
1739 :
1740 : if (traffic_class)
1741 : ip_version_traffic_class_and_flow_label |=
1742 : (traffic_class_val & 0xFF) << 20;
1743 :
1744 : if (flow_label)
1745 : ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
1746 :
1747 : ip->ip_version_traffic_class_and_flow_label =
1748 : clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1749 :
1750 : if (payload_length)
1751 : ip->payload_length = clib_host_to_net_u16 (payload_length_val);
1752 :
1753 : if (hop_limit)
1754 : ip->hop_limit = hop_limit_val;
1755 :
1756 : *matchp = match;
1757 : return 1;
1758 : }
1759 :
1760 : uword
1761 : unformat_l3_match (unformat_input_t * input, va_list * args)
1762 : {
1763 : u8 **matchp = va_arg (*args, u8 **);
1764 :
1765 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1766 : {
1767 : if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
1768 : return 1;
1769 : else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
1770 : return 1;
1771 : else
1772 : break;
1773 : }
1774 : return 0;
1775 : }
1776 :
1777 : uword
1778 : unformat_vlan_tag (unformat_input_t * input, va_list * args)
1779 : {
1780 : u8 *tagp = va_arg (*args, u8 *);
1781 : u32 tag;
1782 :
1783 : if (unformat (input, "%d", &tag))
1784 : {
1785 : tagp[0] = (tag >> 8) & 0x0F;
1786 : tagp[1] = tag & 0xFF;
1787 : return 1;
1788 : }
1789 :
1790 : return 0;
1791 : }
1792 :
1793 : uword
1794 : unformat_l2_match (unformat_input_t * input, va_list * args)
1795 : {
1796 : u8 **matchp = va_arg (*args, u8 **);
1797 : u8 *match = 0;
1798 : u8 src = 0;
1799 : u8 src_val[6];
1800 : u8 dst = 0;
1801 : u8 dst_val[6];
1802 : u8 proto = 0;
1803 : u16 proto_val;
1804 : u8 tag1 = 0;
1805 : u8 tag1_val[2];
1806 : u8 tag2 = 0;
1807 : u8 tag2_val[2];
1808 : int len = 14;
1809 : u8 ignore_tag1 = 0;
1810 : u8 ignore_tag2 = 0;
1811 : u8 cos1 = 0;
1812 : u8 cos2 = 0;
1813 : u32 cos1_val = 0;
1814 : u32 cos2_val = 0;
1815 :
1816 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1817 : {
1818 : if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
1819 : src = 1;
1820 : else
1821 : if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
1822 : dst = 1;
1823 : else if (unformat (input, "proto %U",
1824 : unformat_ethernet_type_host_byte_order, &proto_val))
1825 : proto = 1;
1826 : else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
1827 : tag1 = 1;
1828 : else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
1829 : tag2 = 1;
1830 : else if (unformat (input, "ignore-tag1"))
1831 : ignore_tag1 = 1;
1832 : else if (unformat (input, "ignore-tag2"))
1833 : ignore_tag2 = 1;
1834 : else if (unformat (input, "cos1 %d", &cos1_val))
1835 : cos1 = 1;
1836 : else if (unformat (input, "cos2 %d", &cos2_val))
1837 : cos2 = 1;
1838 : else
1839 : break;
1840 : }
1841 : if ((src + dst + proto + tag1 + tag2 +
1842 : ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1843 : return 0;
1844 :
1845 : if (tag1 || ignore_tag1 || cos1)
1846 : len = 18;
1847 : if (tag2 || ignore_tag2 || cos2)
1848 : len = 22;
1849 :
1850 : vec_validate_aligned (match, len - 1, sizeof (u32x4));
1851 :
1852 : if (dst)
1853 : clib_memcpy (match, dst_val, 6);
1854 :
1855 : if (src)
1856 : clib_memcpy (match + 6, src_val, 6);
1857 :
1858 : if (tag2)
1859 : {
1860 : /* inner vlan tag */
1861 : match[19] = tag2_val[1];
1862 : match[18] = tag2_val[0];
1863 : if (cos2)
1864 : match[18] |= (cos2_val & 0x7) << 5;
1865 : if (proto)
1866 : {
1867 : match[21] = proto_val & 0xff;
1868 : match[20] = proto_val >> 8;
1869 : }
1870 : if (tag1)
1871 : {
1872 : match[15] = tag1_val[1];
1873 : match[14] = tag1_val[0];
1874 : }
1875 : if (cos1)
1876 : match[14] |= (cos1_val & 0x7) << 5;
1877 : *matchp = match;
1878 : return 1;
1879 : }
1880 : if (tag1)
1881 : {
1882 : match[15] = tag1_val[1];
1883 : match[14] = tag1_val[0];
1884 : if (proto)
1885 : {
1886 : match[17] = proto_val & 0xff;
1887 : match[16] = proto_val >> 8;
1888 : }
1889 : if (cos1)
1890 : match[14] |= (cos1_val & 0x7) << 5;
1891 :
1892 : *matchp = match;
1893 : return 1;
1894 : }
1895 : if (cos2)
1896 : match[18] |= (cos2_val & 0x7) << 5;
1897 : if (cos1)
1898 : match[14] |= (cos1_val & 0x7) << 5;
1899 : if (proto)
1900 : {
1901 : match[13] = proto_val & 0xff;
1902 : match[12] = proto_val >> 8;
1903 : }
1904 :
1905 : *matchp = match;
1906 : return 1;
1907 : }
1908 :
1909 : uword
1910 : unformat_qos_source (unformat_input_t * input, va_list * args)
1911 : {
1912 : int *qs = va_arg (*args, int *);
1913 :
1914 : if (unformat (input, "ip"))
1915 : *qs = QOS_SOURCE_IP;
1916 : else if (unformat (input, "mpls"))
1917 : *qs = QOS_SOURCE_MPLS;
1918 : else if (unformat (input, "ext"))
1919 : *qs = QOS_SOURCE_EXT;
1920 : else if (unformat (input, "vlan"))
1921 : *qs = QOS_SOURCE_VLAN;
1922 : else
1923 : return 0;
1924 :
1925 : return 1;
1926 : }
1927 : #endif
1928 :
1929 : uword
1930 0 : api_unformat_classify_match (unformat_input_t * input, va_list * args)
1931 : {
1932 0 : u8 **matchp = va_arg (*args, u8 **);
1933 0 : u32 skip_n_vectors = va_arg (*args, u32);
1934 0 : u32 match_n_vectors = va_arg (*args, u32);
1935 :
1936 0 : u8 *match = 0;
1937 0 : u8 *l2 = 0;
1938 0 : u8 *l3 = 0;
1939 0 : u8 *l4 = 0;
1940 :
1941 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1942 : {
1943 0 : if (unformat (input, "hex %U", unformat_hex_string, &match))
1944 : ;
1945 0 : else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
1946 : ;
1947 0 : else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
1948 : ;
1949 0 : else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
1950 : ;
1951 : else
1952 0 : break;
1953 : }
1954 :
1955 0 : if (l4 && !l3)
1956 : {
1957 0 : vec_free (match);
1958 0 : vec_free (l2);
1959 0 : vec_free (l4);
1960 0 : return 0;
1961 : }
1962 :
1963 0 : if (match || l2 || l3 || l4)
1964 : {
1965 0 : if (l2 || l3 || l4)
1966 : {
1967 : /* "Win a free Ethernet header in every packet" */
1968 0 : if (l2 == 0)
1969 0 : vec_validate_aligned (l2, 13, sizeof (u32x4));
1970 0 : match = l2;
1971 0 : if (vec_len (l3))
1972 : {
1973 0 : vec_append_aligned (match, l3, sizeof (u32x4));
1974 0 : vec_free (l3);
1975 : }
1976 0 : if (vec_len (l4))
1977 : {
1978 0 : vec_append_aligned (match, l4, sizeof (u32x4));
1979 0 : vec_free (l4);
1980 : }
1981 : }
1982 :
1983 : /* Make sure the vector is big enough even if key is all 0's */
1984 0 : vec_validate_aligned
1985 : (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
1986 : sizeof (u32x4));
1987 :
1988 : /* Set size, include skipped vectors */
1989 0 : vec_set_len (match, (match_n_vectors + skip_n_vectors) * sizeof (u32x4));
1990 :
1991 0 : *matchp = match;
1992 :
1993 0 : return 1;
1994 : }
1995 :
1996 0 : return 0;
1997 : }
1998 :
1999 : #define foreach_vtr_op \
2000 : _ ("disable", L2_VTR_DISABLED) \
2001 : _ ("push-1", L2_VTR_PUSH_1) \
2002 : _ ("push-2", L2_VTR_PUSH_2) \
2003 : _ ("pop-1", L2_VTR_POP_1) \
2004 : _ ("pop-2", L2_VTR_POP_2) \
2005 : _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \
2006 : _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \
2007 : _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \
2008 : _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
2009 :
2010 : static int
2011 0 : api_get_first_msg_id (vat_main_t *vam)
2012 : {
2013 : vl_api_get_first_msg_id_t *mp;
2014 0 : unformat_input_t *i = vam->input;
2015 : u8 *name;
2016 0 : u8 name_set = 0;
2017 : int ret;
2018 :
2019 0 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2020 : {
2021 0 : if (unformat (i, "client %s", &name))
2022 0 : name_set = 1;
2023 : else
2024 0 : break;
2025 : }
2026 :
2027 0 : if (name_set == 0)
2028 : {
2029 0 : errmsg ("missing client name");
2030 0 : return -99;
2031 : }
2032 0 : vec_add1 (name, 0);
2033 :
2034 0 : if (vec_len (name) > 63)
2035 : {
2036 0 : errmsg ("client name too long");
2037 0 : return -99;
2038 : }
2039 :
2040 0 : M (GET_FIRST_MSG_ID, mp);
2041 0 : clib_memcpy (mp->name, name, vec_len (name));
2042 0 : S (mp);
2043 0 : W (ret);
2044 0 : return ret;
2045 : }
2046 :
2047 : #define foreach_pbb_vtr_op \
2048 : _("disable", L2_VTR_DISABLED) \
2049 : _("pop", L2_VTR_POP_2) \
2050 : _("push", L2_VTR_PUSH_2)
2051 :
2052 : static int
2053 0 : api_sock_init_shm (vat_main_t * vam)
2054 : {
2055 : #if VPP_API_TEST_BUILTIN == 0
2056 : unformat_input_t *i = vam->input;
2057 : vl_api_shm_elem_config_t *config = 0;
2058 : u64 size = 64 << 20;
2059 : int rv;
2060 :
2061 : while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2062 : {
2063 : if (unformat (i, "size %U", unformat_memory_size, &size))
2064 : ;
2065 : else
2066 : break;
2067 : }
2068 :
2069 : /*
2070 : * Canned custom ring allocator config.
2071 : * Should probably parse all of this
2072 : */
2073 : vec_validate (config, 6);
2074 : config[0].type = VL_API_VLIB_RING;
2075 : config[0].size = 256;
2076 : config[0].count = 32;
2077 :
2078 : config[1].type = VL_API_VLIB_RING;
2079 : config[1].size = 1024;
2080 : config[1].count = 16;
2081 :
2082 : config[2].type = VL_API_VLIB_RING;
2083 : config[2].size = 4096;
2084 : config[2].count = 2;
2085 :
2086 : config[3].type = VL_API_CLIENT_RING;
2087 : config[3].size = 256;
2088 : config[3].count = 32;
2089 :
2090 : config[4].type = VL_API_CLIENT_RING;
2091 : config[4].size = 1024;
2092 : config[4].count = 16;
2093 :
2094 : config[5].type = VL_API_CLIENT_RING;
2095 : config[5].size = 4096;
2096 : config[5].count = 2;
2097 :
2098 : config[6].type = VL_API_QUEUE;
2099 : config[6].count = 128;
2100 : config[6].size = sizeof (uword);
2101 :
2102 : rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
2103 : if (!rv)
2104 : vam->client_index_invalid = 1;
2105 : return rv;
2106 : #else
2107 0 : return -99;
2108 : #endif
2109 : }
2110 :
2111 : static int
2112 0 : q_or_quit (vat_main_t * vam)
2113 : {
2114 : #if VPP_API_TEST_BUILTIN == 0
2115 : longjmp (vam->jump_buf, 1);
2116 : #endif
2117 0 : return 0; /* not so much */
2118 : }
2119 :
2120 : static int
2121 0 : q (vat_main_t * vam)
2122 : {
2123 0 : return q_or_quit (vam);
2124 : }
2125 :
2126 : static int
2127 0 : quit (vat_main_t * vam)
2128 : {
2129 0 : return q_or_quit (vam);
2130 : }
2131 :
2132 : static int
2133 0 : comment (vat_main_t * vam)
2134 : {
2135 0 : return 0;
2136 : }
2137 :
2138 : static int
2139 0 : elog_save (vat_main_t * vam)
2140 : {
2141 : #if VPP_API_TEST_BUILTIN == 0
2142 : elog_main_t *em = &vam->elog_main;
2143 : unformat_input_t *i = vam->input;
2144 : char *file, *chroot_file;
2145 : clib_error_t *error;
2146 :
2147 : if (!unformat (i, "%s", &file))
2148 : {
2149 : errmsg ("expected file name, got `%U'", format_unformat_error, i);
2150 : return 0;
2151 : }
2152 :
2153 : /* It's fairly hard to get "../oopsie" through unformat; just in case */
2154 : if (strstr (file, "..") || index (file, '/'))
2155 : {
2156 : errmsg ("illegal characters in filename '%s'", file);
2157 : return 0;
2158 : }
2159 :
2160 : chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
2161 :
2162 : vec_free (file);
2163 :
2164 : errmsg ("Saving %wd of %wd events to %s",
2165 : elog_n_events_in_buffer (em),
2166 : elog_buffer_capacity (em), chroot_file);
2167 :
2168 : error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
2169 : vec_free (chroot_file);
2170 :
2171 : if (error)
2172 : clib_error_report (error);
2173 : #else
2174 0 : errmsg ("Use the vpp event loger...");
2175 : #endif
2176 :
2177 0 : return 0;
2178 : }
2179 :
2180 : static int
2181 0 : elog_setup (vat_main_t * vam)
2182 : {
2183 : #if VPP_API_TEST_BUILTIN == 0
2184 : elog_main_t *em = &vam->elog_main;
2185 : unformat_input_t *i = vam->input;
2186 : u32 nevents = 128 << 10;
2187 :
2188 : (void) unformat (i, "nevents %d", &nevents);
2189 :
2190 : elog_init (em, nevents);
2191 : vl_api_set_elog_main (em);
2192 : vl_api_set_elog_trace_api_messages (1);
2193 : errmsg ("Event logger initialized with %u events", nevents);
2194 : #else
2195 0 : errmsg ("Use the vpp event loger...");
2196 : #endif
2197 0 : return 0;
2198 : }
2199 :
2200 : static int
2201 0 : elog_enable (vat_main_t * vam)
2202 : {
2203 : #if VPP_API_TEST_BUILTIN == 0
2204 : elog_main_t *em = &vam->elog_main;
2205 :
2206 : elog_enable_disable (em, 1 /* enable */ );
2207 : vl_api_set_elog_trace_api_messages (1);
2208 : errmsg ("Event logger enabled...");
2209 : #else
2210 0 : errmsg ("Use the vpp event loger...");
2211 : #endif
2212 0 : return 0;
2213 : }
2214 :
2215 : static int
2216 0 : elog_disable (vat_main_t * vam)
2217 : {
2218 : #if VPP_API_TEST_BUILTIN == 0
2219 : elog_main_t *em = &vam->elog_main;
2220 :
2221 : elog_enable_disable (em, 0 /* enable */ );
2222 : vl_api_set_elog_trace_api_messages (1);
2223 : errmsg ("Event logger disabled...");
2224 : #else
2225 0 : errmsg ("Use the vpp event loger...");
2226 : #endif
2227 0 : return 0;
2228 : }
2229 :
2230 : static int
2231 0 : statseg (vat_main_t * vam)
2232 : {
2233 0 : ssvm_private_t *ssvmp = &vam->stat_segment;
2234 0 : ssvm_shared_header_t *shared_header = ssvmp->sh;
2235 : vlib_counter_t **counters;
2236 : u64 thread0_index1_packets;
2237 : u64 thread0_index1_bytes;
2238 : f64 vector_rate, input_rate;
2239 : uword *p;
2240 :
2241 : uword *counter_vector_by_name;
2242 0 : if (vam->stat_segment_lockp == 0)
2243 : {
2244 0 : errmsg ("Stat segment not mapped...");
2245 0 : return -99;
2246 : }
2247 :
2248 : /* look up "/if/rx for sw_if_index 1 as a test */
2249 :
2250 0 : clib_spinlock_lock (vam->stat_segment_lockp);
2251 :
2252 0 : counter_vector_by_name = (uword *) shared_header->opaque[1];
2253 :
2254 0 : p = hash_get_mem (counter_vector_by_name, "/if/rx");
2255 0 : if (p == 0)
2256 : {
2257 0 : clib_spinlock_unlock (vam->stat_segment_lockp);
2258 0 : errmsg ("/if/tx not found?");
2259 0 : return -99;
2260 : }
2261 :
2262 : /* Fish per-thread vector of combined counters from shared memory */
2263 0 : counters = (vlib_counter_t **) p[0];
2264 :
2265 0 : if (vec_len (counters[0]) < 2)
2266 : {
2267 0 : clib_spinlock_unlock (vam->stat_segment_lockp);
2268 0 : errmsg ("/if/tx vector length %d", vec_len (counters[0]));
2269 0 : return -99;
2270 : }
2271 :
2272 : /* Read thread 0 sw_if_index 1 counter */
2273 0 : thread0_index1_packets = counters[0][1].packets;
2274 0 : thread0_index1_bytes = counters[0][1].bytes;
2275 :
2276 0 : p = hash_get_mem (counter_vector_by_name, "vector_rate");
2277 0 : if (p == 0)
2278 : {
2279 0 : clib_spinlock_unlock (vam->stat_segment_lockp);
2280 0 : errmsg ("vector_rate not found?");
2281 0 : return -99;
2282 : }
2283 :
2284 0 : vector_rate = *(f64 *) (p[0]);
2285 0 : p = hash_get_mem (counter_vector_by_name, "input_rate");
2286 0 : if (p == 0)
2287 : {
2288 0 : clib_spinlock_unlock (vam->stat_segment_lockp);
2289 0 : errmsg ("input_rate not found?");
2290 0 : return -99;
2291 : }
2292 0 : input_rate = *(f64 *) (p[0]);
2293 :
2294 0 : clib_spinlock_unlock (vam->stat_segment_lockp);
2295 :
2296 0 : print (vam->ofp, "vector_rate %.2f input_rate %.2f",
2297 : vector_rate, input_rate);
2298 0 : print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
2299 : thread0_index1_packets, thread0_index1_bytes);
2300 :
2301 0 : return 0;
2302 : }
2303 :
2304 : static int
2305 0 : cmd_cmp (void *a1, void *a2)
2306 : {
2307 0 : u8 **c1 = a1;
2308 0 : u8 **c2 = a2;
2309 :
2310 0 : return strcmp ((char *) (c1[0]), (char *) (c2[0]));
2311 : }
2312 :
2313 : static int
2314 0 : help (vat_main_t * vam)
2315 : {
2316 0 : u8 **cmds = 0;
2317 0 : u8 *name = 0;
2318 : hash_pair_t *p;
2319 0 : unformat_input_t *i = vam->input;
2320 : int j;
2321 :
2322 0 : if (unformat (i, "%s", &name))
2323 : {
2324 : uword *hs;
2325 :
2326 0 : vec_add1 (name, 0);
2327 :
2328 0 : hs = hash_get_mem (vam->help_by_name, name);
2329 0 : if (hs)
2330 0 : print (vam->ofp, "usage: %s %s", name, hs[0]);
2331 : else
2332 0 : print (vam->ofp, "No such msg / command '%s'", name);
2333 0 : vec_free (name);
2334 0 : return 0;
2335 : }
2336 :
2337 0 : print (vam->ofp, "Help is available for the following:");
2338 :
2339 0 : hash_foreach_pair (p, vam->function_by_name,
2340 : ({
2341 : vec_add1 (cmds, (u8 *)(p->key));
2342 : }));
2343 :
2344 0 : vec_sort_with_function (cmds, cmd_cmp);
2345 :
2346 0 : for (j = 0; j < vec_len (cmds); j++)
2347 0 : print (vam->ofp, "%s", cmds[j]);
2348 :
2349 0 : vec_free (cmds);
2350 0 : return 0;
2351 : }
2352 :
2353 : static int
2354 0 : set (vat_main_t * vam)
2355 : {
2356 0 : u8 *name = 0, *value = 0;
2357 0 : unformat_input_t *i = vam->input;
2358 :
2359 0 : if (unformat (i, "%s", &name))
2360 : {
2361 : /* The input buffer is a vector, not a string. */
2362 0 : value = vec_dup (i->buffer);
2363 0 : vec_delete (value, i->index, 0);
2364 : /* Almost certainly has a trailing newline */
2365 0 : if (value[vec_len (value) - 1] == '\n')
2366 0 : value[vec_len (value) - 1] = 0;
2367 : /* Make sure it's a proper string, one way or the other */
2368 0 : vec_add1 (value, 0);
2369 0 : (void) clib_macro_set_value (&vam->macro_main,
2370 : (char *) name, (char *) value);
2371 : }
2372 : else
2373 0 : errmsg ("usage: set <name> <value>");
2374 :
2375 0 : vec_free (name);
2376 0 : vec_free (value);
2377 0 : return 0;
2378 : }
2379 :
2380 : static int
2381 0 : unset (vat_main_t * vam)
2382 : {
2383 0 : u8 *name = 0;
2384 :
2385 0 : if (unformat (vam->input, "%s", &name))
2386 0 : if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
2387 0 : errmsg ("unset: %s wasn't set", name);
2388 0 : vec_free (name);
2389 0 : return 0;
2390 : }
2391 :
2392 : typedef struct
2393 : {
2394 : u8 *name;
2395 : u8 *value;
2396 : } macro_sort_t;
2397 :
2398 :
2399 : static int
2400 0 : macro_sort_cmp (void *a1, void *a2)
2401 : {
2402 0 : macro_sort_t *s1 = a1;
2403 0 : macro_sort_t *s2 = a2;
2404 :
2405 0 : return strcmp ((char *) (s1->name), (char *) (s2->name));
2406 : }
2407 :
2408 : static int
2409 0 : dump_macro_table (vat_main_t * vam)
2410 : {
2411 0 : macro_sort_t *sort_me = 0, *sm;
2412 : int i;
2413 : hash_pair_t *p;
2414 :
2415 0 : hash_foreach_pair (p, vam->macro_main.the_value_table_hash, ({
2416 : vec_add2 (sort_me, sm, 1);
2417 : sm->name = (u8 *) (p->key);
2418 : sm->value = (u8 *) (p->value[0]);
2419 : }));
2420 :
2421 0 : vec_sort_with_function (sort_me, macro_sort_cmp);
2422 :
2423 0 : if (vec_len (sort_me))
2424 0 : print (vam->ofp, "%-15s%s", "Name", "Value");
2425 : else
2426 0 : print (vam->ofp, "The macro table is empty...");
2427 :
2428 0 : for (i = 0; i < vec_len (sort_me); i++)
2429 0 : print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
2430 0 : return 0;
2431 : }
2432 :
2433 : static int
2434 0 : value_sort_cmp (void *a1, void *a2)
2435 : {
2436 0 : name_sort_t *n1 = a1;
2437 0 : name_sort_t *n2 = a2;
2438 :
2439 0 : if (n1->value < n2->value)
2440 0 : return -1;
2441 0 : if (n1->value > n2->value)
2442 0 : return 1;
2443 0 : return 0;
2444 : }
2445 :
2446 :
2447 : static int
2448 0 : dump_msg_api_table (vat_main_t * vam)
2449 : {
2450 0 : api_main_t *am = vlibapi_get_main ();
2451 0 : name_sort_t *nses = 0, *ns;
2452 : hash_pair_t *hp;
2453 : int i;
2454 :
2455 0 : hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
2456 : ({
2457 : vec_add2 (nses, ns, 1);
2458 : ns->name = (u8 *)(hp->key);
2459 : ns->value = (u32) hp->value[0];
2460 : }));
2461 :
2462 0 : vec_sort_with_function (nses, value_sort_cmp);
2463 :
2464 0 : for (i = 0; i < vec_len (nses); i++)
2465 0 : print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
2466 0 : vec_free (nses);
2467 0 : return 0;
2468 : }
2469 :
2470 : static int
2471 0 : get_msg_id (vat_main_t * vam)
2472 : {
2473 : u8 *name_and_crc;
2474 : u32 message_index;
2475 :
2476 0 : if (unformat (vam->input, "%s", &name_and_crc))
2477 : {
2478 0 : message_index = vl_msg_api_get_msg_index (name_and_crc);
2479 0 : if (message_index == ~0)
2480 : {
2481 0 : print (vam->ofp, " '%s' not found", name_and_crc);
2482 0 : return 0;
2483 : }
2484 0 : print (vam->ofp, " '%s' has message index %d",
2485 : name_and_crc, message_index);
2486 0 : return 0;
2487 : }
2488 0 : errmsg ("name_and_crc required...");
2489 0 : return 0;
2490 : }
2491 :
2492 : static int
2493 0 : search_node_table (vat_main_t * vam)
2494 : {
2495 0 : unformat_input_t *line_input = vam->input;
2496 : u8 *node_to_find;
2497 : int j;
2498 : vlib_node_t *node, *next_node;
2499 : uword *p;
2500 :
2501 0 : if (vam->graph_node_index_by_name == 0)
2502 : {
2503 0 : print (vam->ofp, "Node table empty, issue get_node_graph...");
2504 0 : return 0;
2505 : }
2506 :
2507 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2508 : {
2509 0 : if (unformat (line_input, "%s", &node_to_find))
2510 : {
2511 0 : vec_add1 (node_to_find, 0);
2512 0 : p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
2513 0 : if (p == 0)
2514 : {
2515 0 : print (vam->ofp, "%s not found...", node_to_find);
2516 0 : goto out;
2517 : }
2518 0 : node = vam->graph_nodes[0][p[0]];
2519 0 : print (vam->ofp, "[%d] %s", p[0], node->name);
2520 0 : for (j = 0; j < vec_len (node->next_nodes); j++)
2521 : {
2522 0 : if (node->next_nodes[j] != ~0)
2523 : {
2524 0 : next_node = vam->graph_nodes[0][node->next_nodes[j]];
2525 0 : print (vam->ofp, " [%d] %s", j, next_node->name);
2526 : }
2527 : }
2528 : }
2529 :
2530 : else
2531 : {
2532 0 : clib_warning ("parse error '%U'", format_unformat_error,
2533 : line_input);
2534 0 : return -99;
2535 : }
2536 :
2537 0 : out:
2538 0 : vec_free (node_to_find);
2539 :
2540 : }
2541 :
2542 0 : return 0;
2543 : }
2544 :
2545 :
2546 : static int
2547 0 : script (vat_main_t * vam)
2548 : {
2549 : #if (VPP_API_TEST_BUILTIN==0)
2550 : u8 *s = 0;
2551 : char *save_current_file;
2552 : unformat_input_t save_input;
2553 : jmp_buf save_jump_buf;
2554 : u32 save_line_number;
2555 :
2556 : FILE *new_fp, *save_ifp;
2557 :
2558 : if (unformat (vam->input, "%s", &s))
2559 : {
2560 : new_fp = fopen ((char *) s, "r");
2561 : if (new_fp == 0)
2562 : {
2563 : errmsg ("Couldn't open script file %s", s);
2564 : vec_free (s);
2565 : return -99;
2566 : }
2567 : }
2568 : else
2569 : {
2570 : errmsg ("Missing script name");
2571 : return -99;
2572 : }
2573 :
2574 : clib_memcpy (&save_input, &vam->input, sizeof (save_input));
2575 : clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
2576 : save_ifp = vam->ifp;
2577 : save_line_number = vam->input_line_number;
2578 : save_current_file = (char *) vam->current_file;
2579 :
2580 : vam->input_line_number = 0;
2581 : vam->ifp = new_fp;
2582 : vam->current_file = s;
2583 : do_one_file (vam);
2584 :
2585 : clib_memcpy (&vam->input, &save_input, sizeof (save_input));
2586 : clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
2587 : vam->ifp = save_ifp;
2588 : vam->input_line_number = save_line_number;
2589 : vam->current_file = (u8 *) save_current_file;
2590 : vec_free (s);
2591 :
2592 : return 0;
2593 : #else
2594 0 : clib_warning ("use the exec command...");
2595 0 : return -99;
2596 : #endif
2597 : }
2598 :
2599 : static int
2600 0 : echo (vat_main_t * vam)
2601 : {
2602 0 : print (vam->ofp, "%v", vam->input->buffer);
2603 0 : return 0;
2604 : }
2605 :
2606 : int exec (vat_main_t *vam) __attribute__ ((weak));
2607 : int
2608 0 : exec (vat_main_t *vam)
2609 : {
2610 0 : return -1;
2611 : }
2612 :
2613 : static int
2614 0 : name_sort_cmp (void *a1, void *a2)
2615 : {
2616 0 : name_sort_t *n1 = a1;
2617 0 : name_sort_t *n2 = a2;
2618 :
2619 0 : return strcmp ((char *) n1->name, (char *) n2->name);
2620 : }
2621 :
2622 : static int
2623 0 : dump_interface_table (vat_main_t *vam)
2624 : {
2625 : hash_pair_t *p;
2626 0 : name_sort_t *nses = 0, *ns;
2627 :
2628 0 : if (vam->json_output)
2629 : {
2630 0 : clib_warning (
2631 : "JSON output supported only for VPE API calls and dump_stats_table");
2632 0 : return -99;
2633 : }
2634 :
2635 0 : hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
2636 : vec_add2 (nses, ns, 1);
2637 : ns->name = (u8 *) (p->key);
2638 : ns->value = (u32) p->value[0];
2639 : }));
2640 :
2641 0 : vec_sort_with_function (nses, name_sort_cmp);
2642 :
2643 0 : print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
2644 0 : vec_foreach (ns, nses)
2645 : {
2646 0 : print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2647 : }
2648 0 : vec_free (nses);
2649 0 : return 0;
2650 : }
2651 :
2652 : static int
2653 0 : dump_sub_interface_table (vat_main_t *vam)
2654 : {
2655 0 : const sw_interface_subif_t *sub = NULL;
2656 :
2657 0 : if (vam->json_output)
2658 : {
2659 0 : clib_warning (
2660 : "JSON output supported only for VPE API calls and dump_stats_table");
2661 0 : return -99;
2662 : }
2663 :
2664 0 : print (vam->ofp, "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
2665 : "Interface", "sw_if_index", "sub id", "dot1ad", "tags", "outer id",
2666 : "inner id", "exact", "default", "outer any", "inner any");
2667 :
2668 0 : vec_foreach (sub, vam->sw_if_subif_table)
2669 : {
2670 0 : print (vam->ofp, "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
2671 : sub->interface_name, sub->sw_if_index, sub->sub_id,
2672 0 : sub->sub_dot1ad ? "dot1ad" : "dot1q", sub->sub_number_of_tags,
2673 0 : sub->sub_outer_vlan_id, sub->sub_inner_vlan_id,
2674 0 : sub->sub_exact_match, sub->sub_default,
2675 0 : sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2676 0 : if (sub->vtr_op != L2_VTR_DISABLED)
2677 : {
2678 0 : print (vam->ofp,
2679 : " vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2680 : "tag1: %d tag2: %d ]",
2681 : str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q, sub->vtr_tag1,
2682 : sub->vtr_tag2);
2683 : }
2684 : }
2685 :
2686 0 : return 0;
2687 : }
2688 :
2689 : /* List of API message constructors, CLI names map to api_xxx */
2690 : #define foreach_vpe_api_msg \
2691 : _(get_first_msg_id, "client <name>") \
2692 : _(sock_init_shm, "size <nnn>") \
2693 : /* List of command functions, CLI names map directly to functions */
2694 : #define foreach_cli_function \
2695 : _ (comment, "usage: comment <ignore-rest-of-line>") \
2696 : _ (dump_interface_table, "usage: dump_interface_table") \
2697 : _ (dump_sub_interface_table, "usage: dump_sub_interface_table") \
2698 : _ (dump_macro_table, "usage: dump_macro_table ") \
2699 : _ (dump_msg_api_table, "usage: dump_msg_api_table") \
2700 : _ (elog_setup, "usage: elog_setup [nevents, default 128K]") \
2701 : _ (elog_disable, "usage: elog_disable") \
2702 : _ (elog_enable, "usage: elog_enable") \
2703 : _ (elog_save, "usage: elog_save <filename>") \
2704 : _ (get_msg_id, "usage: get_msg_id name_and_crc") \
2705 : _ (echo, "usage: echo <message>") \
2706 : _ (help, "usage: help") \
2707 : _ (q, "usage: quit") \
2708 : _ (quit, "usage: quit") \
2709 : _ (search_node_table, "usage: search_node_table <name>...") \
2710 : _ (set, "usage: set <variable-name> <value>") \
2711 : _ (script, "usage: script <file-name>") \
2712 : _ (statseg, "usage: statseg") \
2713 : _ (unset, "usage: unset <variable-name>")
2714 :
2715 : #define _(N,n) \
2716 : static void vl_api_##n##_t_handler_uni \
2717 : (vl_api_##n##_t * mp) \
2718 : { \
2719 : vat_main_t * vam = &vat_main; \
2720 : if (vam->json_output) { \
2721 : vl_api_##n##_t_handler_json(mp); \
2722 : } else { \
2723 : vl_api_##n##_t_handler(mp); \
2724 : } \
2725 : }
2726 2 : foreach_vpe_api_reply_msg;
2727 : #if VPP_API_TEST_BUILTIN == 0
2728 : foreach_standalone_reply_msg;
2729 : #endif
2730 : #undef _
2731 :
2732 : void
2733 575 : vat_api_hookup (vat_main_t * vam)
2734 : {
2735 : #define _(N, n) \
2736 : vl_msg_api_config (&(vl_msg_api_msg_config_t){ \
2737 : .id = VL_API_##N + 1, \
2738 : .name = #n, \
2739 : .handler = vl_api_##n##_t_handler_uni, \
2740 : .endian = vl_api_##n##_t_endian, \
2741 : .format_fn = vl_api_##n##_t_format, \
2742 : .size = sizeof (vl_api_##n##_t), \
2743 : .traced = 1, \
2744 : .tojson = vl_api_##n##_t_tojson, \
2745 : .fromjson = vl_api_##n##_t_fromjson, \
2746 : .calc_size = vl_api_##n##_t_calc_size, \
2747 : });
2748 575 : foreach_vpe_api_reply_msg;
2749 : #if VPP_API_TEST_BUILTIN == 0
2750 : foreach_standalone_reply_msg;
2751 : #endif
2752 : #undef _
2753 :
2754 : #if (VPP_API_TEST_BUILTIN==0)
2755 : vl_msg_api_set_first_available_msg_id (VL_MSG_MEMCLNT_LAST + 1);
2756 :
2757 : vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2758 :
2759 : vam->function_by_name = hash_create_string (0, sizeof (uword));
2760 :
2761 : vam->help_by_name = hash_create_string (0, sizeof (uword));
2762 : #endif
2763 :
2764 : /* API messages we can send */
2765 : #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
2766 1725 : foreach_vpe_api_msg;
2767 : #undef _
2768 :
2769 : /* Help strings */
2770 : #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2771 1725 : foreach_vpe_api_msg;
2772 : #undef _
2773 :
2774 : /* CLI functions */
2775 : #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
2776 11500 : foreach_cli_function;
2777 : #undef _
2778 :
2779 : /* Help strings */
2780 : #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2781 11500 : foreach_cli_function;
2782 : #undef _
2783 575 : }
2784 :
2785 : #if VPP_API_TEST_BUILTIN
2786 : static clib_error_t *
2787 575 : vat_api_hookup_shim (vlib_main_t * vm)
2788 : {
2789 575 : vat_api_hookup (&vat_main);
2790 575 : return 0;
2791 : }
2792 :
2793 23039 : VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
2794 : #endif
2795 :
2796 : /*
2797 : * fd.io coding-style-patch-verification: ON
2798 : *
2799 : * Local Variables:
2800 : * eval: (c-set-style "gnu")
2801 : * End:
2802 : */
|