session/tcp: improve preallocated segment handling
[vpp.git] / test / ext / vapi_test.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #include <stdio.h>
19 #include <endian.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <assert.h>
23 #include <setjmp.h>
24 #include <check.h>
25 #include <vpp-api/vapi/vapi.h>
26 #include <vpe.api.vapi.h>
27 #include <interface.api.vapi.h>
28 #include <l2.api.vapi.h>
29 #include <stats.api.vapi.h>
30
31 DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
32 DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
33 DEFINE_VAPI_MSG_IDS_L2_API_JSON;
34 DEFINE_VAPI_MSG_IDS_STATS_API_JSON;
35
36 static char *app_name = NULL;
37 static char *api_prefix = NULL;
38 static const int max_outstanding_requests = 64;
39 static const int response_queue_size = 32;
40
41 START_TEST (test_invalid_values)
42 {
43   vapi_ctx_t ctx;
44   vapi_error_e rv = vapi_ctx_alloc (&ctx);
45   ck_assert_int_eq (VAPI_OK, rv);
46   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
47   ck_assert_ptr_eq (NULL, sv);
48   rv = vapi_send (ctx, sv);
49   ck_assert_int_eq (VAPI_EINVAL, rv);
50   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
51                      response_queue_size, VAPI_MODE_BLOCKING);
52   ck_assert_int_eq (VAPI_OK, rv);
53   rv = vapi_send (ctx, NULL);
54   ck_assert_int_eq (VAPI_EINVAL, rv);
55   rv = vapi_send (NULL, NULL);
56   ck_assert_int_eq (VAPI_EINVAL, rv);
57   rv = vapi_recv (NULL, NULL, NULL);
58   ck_assert_int_eq (VAPI_EINVAL, rv);
59   rv = vapi_recv (ctx, NULL, NULL);
60   ck_assert_int_eq (VAPI_EINVAL, rv);
61   vapi_msg_show_version_reply *reply;
62   rv = vapi_recv (ctx, (void **) &reply, NULL);
63   ck_assert_int_eq (VAPI_EINVAL, rv);
64   rv = vapi_disconnect (ctx);
65   ck_assert_int_eq (VAPI_OK, rv);
66   vapi_ctx_free (ctx);
67 }
68
69 END_TEST;
70
71 START_TEST (test_hton_1)
72 {
73   const u16 _vl_msg_id = 1;
74   vapi_type_msg_header1_t h;
75   h._vl_msg_id = _vl_msg_id;
76   vapi_type_msg_header1_t_hton (&h);
77   ck_assert_int_eq (be16toh (h._vl_msg_id), _vl_msg_id);
78 }
79
80 END_TEST;
81
82 START_TEST (test_hton_2)
83 {
84   const u16 _vl_msg_id = 1;
85   const u32 client_index = 3;
86   vapi_type_msg_header2_t h;
87   h._vl_msg_id = _vl_msg_id;
88   h.client_index = client_index;
89   vapi_type_msg_header2_t_hton (&h);
90   ck_assert_int_eq (be16toh (h._vl_msg_id), _vl_msg_id);
91   ck_assert_int_eq (h.client_index, client_index);
92 }
93
94 END_TEST;
95
96 START_TEST (test_hton_3)
97 {
98   const size_t data_size = 10;
99   vapi_msg_vnet_interface_combined_counters *m =
100     malloc (sizeof (vapi_msg_vnet_interface_combined_counters) +
101             data_size * sizeof (vapi_type_vlib_counter));
102   ck_assert_ptr_ne (NULL, m);
103   vapi_payload_vnet_interface_combined_counters *p = &m->payload;
104   const u16 _vl_msg_id = 1;
105   p->_vl_msg_id = _vl_msg_id;
106   const u32 first_sw_if_index = 2;
107   p->first_sw_if_index = first_sw_if_index;
108   p->count = data_size;
109   const u64 packets = 1234;
110   const u64 bytes = 2345;
111   int i;
112   for (i = 0; i < data_size; ++i)
113     {
114       p->data[i].packets = packets;
115       p->data[i].bytes = bytes;
116     }
117   vapi_msg_vnet_interface_combined_counters_hton (m);
118   ck_assert_int_eq (_vl_msg_id, be16toh (p->_vl_msg_id));
119   ck_assert_int_eq (first_sw_if_index, be32toh (p->first_sw_if_index));
120   ck_assert_int_eq (data_size, be32toh (p->count));
121   for (i = 0; i < data_size; ++i)
122     {
123       ck_assert_int_eq (packets, be64toh (p->data[i].packets));
124       ck_assert_int_eq (bytes, be64toh (p->data[i].bytes));
125     }
126   free (p);
127 }
128
129 END_TEST;
130
131 #define verify_hton_swap(expr, value)           \
132   if (4 == sizeof (expr))                       \
133     {                                           \
134       ck_assert_int_eq (expr, htobe32 (value)); \
135     }                                           \
136   else if (2 == sizeof (expr))                  \
137     {                                           \
138       ck_assert_int_eq (expr, htobe16 (value)); \
139     }                                           \
140   else                                          \
141     {                                           \
142       ck_assert_int_eq (expr, value);           \
143     }
144
145 START_TEST (test_hton_4)
146 {
147   const int vla_count = 3;
148   char x[sizeof (vapi_msg_bridge_domain_details) +
149          vla_count * sizeof (vapi_type_bridge_domain_sw_if)];
150   vapi_msg_bridge_domain_details *d = (void *) x;
151   int cnt = 1;
152   d->header._vl_msg_id = cnt++;
153   d->header.context = cnt++;
154   d->payload.bd_id = cnt++;
155   d->payload.flood = cnt++;
156   d->payload.uu_flood = cnt++;
157   d->payload.forward = cnt++;
158   d->payload.learn = cnt++;
159   d->payload.arp_term = cnt++;
160   d->payload.mac_age = cnt++;
161   d->payload.bvi_sw_if_index = cnt++;
162   d->payload.n_sw_ifs = vla_count;
163   int i;
164   for (i = 0; i < vla_count; ++i)
165     {
166       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
167       det->context = cnt++;
168       det->sw_if_index = cnt++;
169       det->shg = cnt++;
170     }
171   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
172   vapi_msg_bridge_domain_details_hton (d);
173   int tmp = 1;
174   verify_hton_swap (d->header._vl_msg_id, tmp);
175   ++tmp;
176   ck_assert_int_eq (d->header.context, tmp);
177   ++tmp;
178   verify_hton_swap (d->payload.bd_id, tmp);
179   ++tmp;
180   verify_hton_swap (d->payload.flood, tmp);
181   ++tmp;
182   verify_hton_swap (d->payload.uu_flood, tmp);
183   ++tmp;
184   verify_hton_swap (d->payload.forward, tmp);
185   ++tmp;
186   verify_hton_swap (d->payload.learn, tmp);
187   ++tmp;
188   verify_hton_swap (d->payload.arp_term, tmp);
189   ++tmp;
190   verify_hton_swap (d->payload.mac_age, tmp);
191   ++tmp;
192   verify_hton_swap (d->payload.bvi_sw_if_index, tmp);
193   ++tmp;
194   ck_assert_int_eq (d->payload.n_sw_ifs, htobe32 (vla_count));
195   for (i = 0; i < vla_count; ++i)
196     {
197       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
198       verify_hton_swap (det->context, tmp);
199       ++tmp;
200       verify_hton_swap (det->sw_if_index, tmp);
201       ++tmp;
202       verify_hton_swap (det->shg, tmp);
203       ++tmp;
204     }
205   vapi_msg_bridge_domain_details_ntoh (d);
206   tmp = 1;
207   ck_assert_int_eq (d->header._vl_msg_id, tmp);
208   ++tmp;
209   ck_assert_int_eq (d->header.context, tmp);
210   ++tmp;
211   ck_assert_int_eq (d->payload.bd_id, tmp);
212   ++tmp;
213   ck_assert_int_eq (d->payload.flood, tmp);
214   ++tmp;
215   ck_assert_int_eq (d->payload.uu_flood, tmp);
216   ++tmp;
217   ck_assert_int_eq (d->payload.forward, tmp);
218   ++tmp;
219   ck_assert_int_eq (d->payload.learn, tmp);
220   ++tmp;
221   ck_assert_int_eq (d->payload.arp_term, tmp);
222   ++tmp;
223   ck_assert_int_eq (d->payload.mac_age, tmp);
224   ++tmp;
225   ck_assert_int_eq (d->payload.bvi_sw_if_index, tmp);
226   ++tmp;
227   ck_assert_int_eq (d->payload.n_sw_ifs, vla_count);
228   for (i = 0; i < vla_count; ++i)
229     {
230       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
231       ck_assert_int_eq (det->context, tmp);
232       ++tmp;
233       ck_assert_int_eq (det->sw_if_index, tmp);
234       ++tmp;
235       ck_assert_int_eq (det->shg, tmp);
236       ++tmp;
237     }
238   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
239 }
240
241 END_TEST;
242
243 START_TEST (test_ntoh_1)
244 {
245   const u16 _vl_msg_id = 1;
246   vapi_type_msg_header1_t h;
247   h._vl_msg_id = _vl_msg_id;
248   vapi_type_msg_header1_t_ntoh (&h);
249   ck_assert_int_eq (htobe16 (h._vl_msg_id), _vl_msg_id);
250 }
251
252 END_TEST;
253
254 START_TEST (test_ntoh_2)
255 {
256   const u16 _vl_msg_id = 1;
257   const u32 client_index = 3;
258   vapi_type_msg_header2_t h;
259   h._vl_msg_id = _vl_msg_id;
260   h.client_index = client_index;
261   vapi_type_msg_header2_t_ntoh (&h);
262   ck_assert_int_eq (htobe16 (h._vl_msg_id), _vl_msg_id);
263   ck_assert_int_eq (h.client_index, client_index);
264 }
265
266 END_TEST;
267
268 START_TEST (test_ntoh_3)
269 {
270   const size_t data_size = 10;
271   vapi_msg_vnet_interface_combined_counters *m =
272     malloc (sizeof (vapi_msg_vnet_interface_combined_counters) +
273             data_size * sizeof (vapi_type_vlib_counter));
274   ck_assert_ptr_ne (NULL, m);
275   vapi_payload_vnet_interface_combined_counters *p = &m->payload;
276   const u16 _vl_msg_id = 1;
277   p->_vl_msg_id = _vl_msg_id;
278   const u32 first_sw_if_index = 2;
279   p->first_sw_if_index = first_sw_if_index;
280   const size_t be_data_size = htobe32 (data_size);
281   p->count = be_data_size;
282   const u64 packets = 1234;
283   const u64 bytes = 2345;
284   int i;
285   for (i = 0; i < data_size; ++i)
286     {
287       p->data[i].packets = packets;
288       p->data[i].bytes = bytes;
289     }
290   vapi_msg_vnet_interface_combined_counters_ntoh (m);
291   ck_assert_int_eq (_vl_msg_id, be16toh (p->_vl_msg_id));
292   ck_assert_int_eq (first_sw_if_index, be32toh (p->first_sw_if_index));
293   ck_assert_int_eq (be_data_size, be32toh (p->count));
294   for (i = 0; i < data_size; ++i)
295     {
296       ck_assert_int_eq (packets, htobe64 (p->data[i].packets));
297       ck_assert_int_eq (bytes, htobe64 (p->data[i].bytes));
298     }
299   free (p);
300 }
301
302 END_TEST;
303
304 #define verify_ntoh_swap(expr, value)           \
305   if (4 == sizeof (expr))                       \
306     {                                           \
307       ck_assert_int_eq (expr, be32toh (value)); \
308     }                                           \
309   else if (2 == sizeof (expr))                  \
310     {                                           \
311       ck_assert_int_eq (expr, be16toh (value)); \
312     }                                           \
313   else                                          \
314     {                                           \
315       ck_assert_int_eq (expr, value);           \
316     }
317
318 START_TEST (test_ntoh_4)
319 {
320   const int vla_count = 3;
321   char x[sizeof (vapi_msg_bridge_domain_details) +
322          vla_count * sizeof (vapi_type_bridge_domain_sw_if)];
323   vapi_msg_bridge_domain_details *d = (void *) x;
324   int cnt = 1;
325   d->header._vl_msg_id = cnt++;
326   d->header.context = cnt++;
327   d->payload.bd_id = cnt++;
328   d->payload.flood = cnt++;
329   d->payload.uu_flood = cnt++;
330   d->payload.forward = cnt++;
331   d->payload.learn = cnt++;
332   d->payload.arp_term = cnt++;
333   d->payload.mac_age = cnt++;
334   d->payload.bvi_sw_if_index = cnt++;
335   d->payload.n_sw_ifs = htobe32 (vla_count);
336   int i;
337   for (i = 0; i < vla_count; ++i)
338     {
339       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
340       det->context = cnt++;
341       det->sw_if_index = cnt++;
342       det->shg = cnt++;
343     }
344   vapi_msg_bridge_domain_details_ntoh (d);
345   ck_assert_int_eq (sizeof (x), vapi_calc_bridge_domain_details_msg_size (d));
346   int tmp = 1;
347   verify_ntoh_swap (d->header._vl_msg_id, tmp);
348   ++tmp;
349   ck_assert_int_eq (d->header.context, tmp);
350   ++tmp;
351   verify_ntoh_swap (d->payload.bd_id, tmp);
352   ++tmp;
353   verify_ntoh_swap (d->payload.flood, tmp);
354   ++tmp;
355   verify_ntoh_swap (d->payload.uu_flood, tmp);
356   ++tmp;
357   verify_ntoh_swap (d->payload.forward, tmp);
358   ++tmp;
359   verify_ntoh_swap (d->payload.learn, tmp);
360   ++tmp;
361   verify_ntoh_swap (d->payload.arp_term, tmp);
362   ++tmp;
363   verify_ntoh_swap (d->payload.mac_age, tmp);
364   ++tmp;
365   verify_ntoh_swap (d->payload.bvi_sw_if_index, tmp);
366   ++tmp;
367   ck_assert_int_eq (d->payload.n_sw_ifs, vla_count);
368   for (i = 0; i < vla_count; ++i)
369     {
370       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
371       verify_ntoh_swap (det->context, tmp);
372       ++tmp;
373       verify_ntoh_swap (det->sw_if_index, tmp);
374       ++tmp;
375       verify_ntoh_swap (det->shg, tmp);
376       ++tmp;
377     }
378   vapi_msg_bridge_domain_details_hton (d);
379   tmp = 1;
380   ck_assert_int_eq (d->header._vl_msg_id, tmp);
381   ++tmp;
382   ck_assert_int_eq (d->header.context, tmp);
383   ++tmp;
384   ck_assert_int_eq (d->payload.bd_id, tmp);
385   ++tmp;
386   ck_assert_int_eq (d->payload.flood, tmp);
387   ++tmp;
388   ck_assert_int_eq (d->payload.uu_flood, tmp);
389   ++tmp;
390   ck_assert_int_eq (d->payload.forward, tmp);
391   ++tmp;
392   ck_assert_int_eq (d->payload.learn, tmp);
393   ++tmp;
394   ck_assert_int_eq (d->payload.arp_term, tmp);
395   ++tmp;
396   ck_assert_int_eq (d->payload.mac_age, tmp);
397   ++tmp;
398   ck_assert_int_eq (d->payload.bvi_sw_if_index, tmp);
399   ++tmp;
400   ck_assert_int_eq (d->payload.n_sw_ifs, htobe32 (vla_count));
401   for (i = 0; i < vla_count; ++i)
402     {
403       vapi_type_bridge_domain_sw_if *det = &d->payload.sw_if_details[i];
404       ck_assert_int_eq (det->context, tmp);
405       ++tmp;
406       ck_assert_int_eq (det->sw_if_index, tmp);
407       ++tmp;
408       ck_assert_int_eq (det->shg, tmp);
409       ++tmp;
410     }
411 }
412
413 END_TEST;
414
415 vapi_error_e
416 show_version_cb (vapi_ctx_t ctx, void *caller_ctx,
417                  vapi_error_e rv, bool is_last,
418                  vapi_payload_show_version_reply * p)
419 {
420   ck_assert_int_eq (VAPI_OK, rv);
421   ck_assert_int_eq (true, is_last);
422   ck_assert_str_eq ("vpe", (char *) p->program);
423   printf
424     ("show_version_reply: program: `%s', version: `%s', build directory: "
425      "`%s', build date: `%s'\n", p->program, p->version, p->build_directory,
426      p->build_date);
427   ++*(int *) caller_ctx;
428   return VAPI_OK;
429 }
430
431 typedef struct
432 {
433   int called;
434   int expected_retval;
435   u32 *sw_if_index_storage;
436 } test_create_loopback_ctx_t;
437
438 vapi_error_e
439 loopback_create_cb (vapi_ctx_t ctx, void *caller_ctx,
440                     vapi_error_e rv, bool is_last,
441                     vapi_payload_create_loopback_reply * p)
442 {
443   test_create_loopback_ctx_t *clc = caller_ctx;
444   ck_assert_int_eq (clc->expected_retval, p->retval);
445   *clc->sw_if_index_storage = p->sw_if_index;
446   ++clc->called;
447   return VAPI_OK;
448 }
449
450 typedef struct
451 {
452   int called;
453   int expected_retval;
454   u32 *sw_if_index_storage;
455 } test_delete_loopback_ctx_t;
456
457 vapi_error_e
458 loopback_delete_cb (vapi_ctx_t ctx, void *caller_ctx,
459                     vapi_error_e rv, bool is_last,
460                     vapi_payload_delete_loopback_reply * p)
461 {
462   test_delete_loopback_ctx_t *dlc = caller_ctx;
463   ck_assert_int_eq (dlc->expected_retval, p->retval);
464   ++dlc->called;
465   return VAPI_OK;
466 }
467
468 START_TEST (test_connect)
469 {
470   vapi_ctx_t ctx;
471   vapi_error_e rv = vapi_ctx_alloc (&ctx);
472   ck_assert_int_eq (VAPI_OK, rv);
473   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
474                      response_queue_size, VAPI_MODE_BLOCKING);
475   ck_assert_int_eq (VAPI_OK, rv);
476   rv = vapi_disconnect (ctx);
477   ck_assert_int_eq (VAPI_OK, rv);
478   vapi_ctx_free (ctx);
479 }
480
481 END_TEST;
482
483 vapi_ctx_t ctx;
484
485 void
486 setup_blocking (void)
487 {
488   vapi_error_e rv = vapi_ctx_alloc (&ctx);
489   ck_assert_int_eq (VAPI_OK, rv);
490   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
491                      response_queue_size, VAPI_MODE_BLOCKING);
492   ck_assert_int_eq (VAPI_OK, rv);
493 }
494
495 void
496 setup_nonblocking (void)
497 {
498   vapi_error_e rv = vapi_ctx_alloc (&ctx);
499   ck_assert_int_eq (VAPI_OK, rv);
500   rv = vapi_connect (ctx, app_name, api_prefix, max_outstanding_requests,
501                      response_queue_size, VAPI_MODE_NONBLOCKING);
502   ck_assert_int_eq (VAPI_OK, rv);
503 }
504
505 void
506 teardown (void)
507 {
508   vapi_disconnect (ctx);
509   vapi_ctx_free (ctx);
510 }
511
512 START_TEST (test_show_version_1)
513 {
514   printf ("--- Basic show version message - reply test ---\n");
515   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
516   ck_assert_ptr_ne (NULL, sv);
517   vapi_msg_show_version_hton (sv);
518   vapi_error_e rv = vapi_send (ctx, sv);
519   ck_assert_int_eq (VAPI_OK, rv);
520   vapi_msg_show_version_reply *resp;
521   size_t size;
522   rv = vapi_recv (ctx, (void *) &resp, &size);
523   ck_assert_int_eq (VAPI_OK, rv);
524   vapi_payload_show_version_reply *payload = &resp->payload;
525   int dummy;
526   show_version_cb (NULL, &dummy, VAPI_OK, true, payload);
527   vapi_msg_free (ctx, resp);
528 }
529
530 END_TEST;
531
532 START_TEST (test_show_version_2)
533 {
534   int called = 0;
535   printf ("--- Show version via blocking callback API ---\n");
536   const int attempts = response_queue_size * 4;
537   int i = 0;
538   for (i = 0; i < attempts; ++i)
539     {
540       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
541       ck_assert_ptr_ne (NULL, sv);
542       vapi_error_e rv = vapi_show_version (ctx, sv, show_version_cb, &called);
543       ck_assert_int_eq (VAPI_OK, rv);
544     }
545   ck_assert_int_eq (attempts, called);
546 }
547
548 END_TEST;
549
550 typedef struct
551 {
552   bool last_called;
553   size_t num_ifs;
554   u32 *sw_if_indexes;
555   bool *seen;
556   int called;
557 } sw_interface_dump_ctx;
558
559 vapi_error_e
560 sw_interface_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
561                       vapi_error_e rv, bool is_last,
562                       vapi_payload_sw_interface_details * reply)
563 {
564   sw_interface_dump_ctx *dctx = callback_ctx;
565   ck_assert_int_eq (false, dctx->last_called);
566   if (is_last)
567     {
568       ck_assert (NULL == reply);
569       dctx->last_called = true;
570     }
571   else
572     {
573       ck_assert (reply);
574       printf ("Interface dump entry: [%u]: %s\n", reply->sw_if_index,
575               reply->interface_name);
576       size_t i = 0;
577       for (i = 0; i < dctx->num_ifs; ++i)
578         {
579           if (dctx->sw_if_indexes[i] == reply->sw_if_index)
580             {
581               ck_assert_int_eq (false, dctx->seen[i]);
582               dctx->seen[i] = true;
583             }
584         }
585     }
586   ++dctx->called;
587   return VAPI_OK;
588 }
589
590 START_TEST (test_loopbacks_1)
591 {
592   printf ("--- Create/delete loopbacks using blocking API ---\n");
593   const size_t num_ifs = 5;
594   u8 mac_addresses[num_ifs][6];
595   memset (&mac_addresses, 0, sizeof (mac_addresses));
596   u32 sw_if_indexes[num_ifs];
597   memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
598   test_create_loopback_ctx_t clcs[num_ifs];
599   memset (&clcs, 0, sizeof (clcs));
600   test_delete_loopback_ctx_t dlcs[num_ifs];
601   memset (&dlcs, 0, sizeof (dlcs));
602   int i;
603   for (i = 0; i < num_ifs; ++i)
604     {
605       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
606       mac_addresses[i][5] = i;
607       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
608     }
609   for (i = 0; i < num_ifs; ++i)
610     {
611       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
612       memcpy (cl->payload.mac_address, mac_addresses[i],
613               sizeof (cl->payload.mac_address));
614       vapi_error_e rv =
615         vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i]);
616       ck_assert_int_eq (VAPI_OK, rv);
617     }
618   for (i = 0; i < num_ifs; ++i)
619     {
620       ck_assert_int_eq (1, clcs[i].called);
621       printf ("Created loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
622               "sw_if_index %u\n",
623               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
624               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
625               sw_if_indexes[i]);
626     }
627   bool seen[num_ifs];
628   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
629   vapi_msg_sw_interface_dump *dump;
630   vapi_error_e rv;
631   const int attempts = response_queue_size * 4;
632   for (i = 0; i < attempts; ++i)
633     {
634       dctx.last_called = false;
635       memset (&seen, 0, sizeof (seen));
636       dump = vapi_alloc_sw_interface_dump (ctx);
637       dump->payload.name_filter_valid = 0;
638       memset (dump->payload.name_filter, 0,
639               sizeof (dump->payload.name_filter));
640       while (VAPI_EAGAIN ==
641              (rv =
642               vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb,
643                                       &dctx)))
644         ;
645       ck_assert_int_eq (true, dctx.last_called);
646       int j = 0;
647       for (j = 0; j < num_ifs; ++j)
648         {
649           ck_assert_int_eq (true, seen[j]);
650         }
651     }
652   memset (&seen, 0, sizeof (seen));
653   for (i = 0; i < num_ifs; ++i)
654     {
655       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
656       dl->payload.sw_if_index = sw_if_indexes[i];
657       vapi_error_e rv =
658         vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i]);
659       ck_assert_int_eq (VAPI_OK, rv);
660     }
661   for (i = 0; i < num_ifs; ++i)
662     {
663       ck_assert_int_eq (1, dlcs[i].called);
664       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
665     }
666   dctx.last_called = false;
667   memset (&seen, 0, sizeof (seen));
668   dump = vapi_alloc_sw_interface_dump (ctx);
669   dump->payload.name_filter_valid = 0;
670   memset (dump->payload.name_filter, 0, sizeof (dump->payload.name_filter));
671   while (VAPI_EAGAIN ==
672          (rv =
673           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
674     ;
675   ck_assert_int_eq (true, dctx.last_called);
676   for (i = 0; i < num_ifs; ++i)
677     {
678       ck_assert_int_eq (false, seen[i]);
679     }
680 }
681
682 END_TEST;
683
684 START_TEST (test_show_version_3)
685 {
686   printf ("--- Show version via async callback ---\n");
687   int called = 0;
688   vapi_error_e rv;
689   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
690   ck_assert_ptr_ne (NULL, sv);
691   while (VAPI_EAGAIN ==
692          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
693     ;
694   ck_assert_int_eq (VAPI_OK, rv);
695   ck_assert_int_eq (0, called);
696   rv = vapi_dispatch (ctx);
697   ck_assert_int_eq (VAPI_OK, rv);
698   ck_assert_int_eq (1, called);
699   called = 0;
700   rv = vapi_dispatch (ctx);
701   ck_assert_int_eq (VAPI_OK, rv);
702   ck_assert_int_eq (0, called);
703 }
704
705 END_TEST;
706
707 START_TEST (test_show_version_4)
708 {
709   printf ("--- Show version via async callback - multiple messages ---\n");
710   vapi_error_e rv;
711   const size_t num_req = 5;
712   int contexts[num_req];
713   memset (contexts, 0, sizeof (contexts));
714   int i;
715   for (i = 0; i < num_req; ++i)
716     {
717       vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
718       ck_assert_ptr_ne (NULL, sv);
719       while (VAPI_EAGAIN ==
720              (rv =
721               vapi_show_version (ctx, sv, show_version_cb, &contexts[i])))
722         ;
723       ck_assert_int_eq (VAPI_OK, rv);
724       int j;
725       for (j = 0; j < num_req; ++j)
726         {
727           ck_assert_int_eq (0, contexts[j]);
728         }
729     }
730   rv = vapi_dispatch (ctx);
731   ck_assert_int_eq (VAPI_OK, rv);
732   for (i = 0; i < num_req; ++i)
733     {
734       ck_assert_int_eq (1, contexts[i]);
735     }
736   memset (contexts, 0, sizeof (contexts));
737   rv = vapi_dispatch (ctx);
738   ck_assert_int_eq (VAPI_OK, rv);
739   for (i = 0; i < num_req; ++i)
740     {
741       ck_assert_int_eq (0, contexts[i]);
742     }
743 }
744
745 END_TEST;
746
747 START_TEST (test_loopbacks_2)
748 {
749   printf ("--- Create/delete loopbacks using non-blocking API ---\n");
750   vapi_error_e rv;
751   const size_t num_ifs = 5;
752   u8 mac_addresses[num_ifs][6];
753   memset (&mac_addresses, 0, sizeof (mac_addresses));
754   u32 sw_if_indexes[num_ifs];
755   memset (&sw_if_indexes, 0xff, sizeof (sw_if_indexes));
756   test_create_loopback_ctx_t clcs[num_ifs];
757   memset (&clcs, 0, sizeof (clcs));
758   test_delete_loopback_ctx_t dlcs[num_ifs];
759   memset (&dlcs, 0, sizeof (dlcs));
760   int i;
761   for (i = 0; i < num_ifs; ++i)
762     {
763       memcpy (&mac_addresses[i], "\1\2\3\4\5\6", 6);
764       mac_addresses[i][5] = i;
765       clcs[i].sw_if_index_storage = &sw_if_indexes[i];
766     }
767   for (i = 0; i < num_ifs; ++i)
768     {
769       vapi_msg_create_loopback *cl = vapi_alloc_create_loopback (ctx);
770       memcpy (cl->payload.mac_address, mac_addresses[i],
771               sizeof (cl->payload.mac_address));
772       while (VAPI_EAGAIN ==
773              (rv =
774               vapi_create_loopback (ctx, cl, loopback_create_cb, &clcs[i])))
775         ;
776       ck_assert_int_eq (VAPI_OK, rv);
777     }
778   rv = vapi_dispatch (ctx);
779   ck_assert_int_eq (VAPI_OK, rv);
780   for (i = 0; i < num_ifs; ++i)
781     {
782       ck_assert_int_eq (1, clcs[i].called);
783       printf ("Loopback with MAC %02x:%02x:%02x:%02x:%02x:%02x --> "
784               "sw_if_index %u\n",
785               mac_addresses[i][0], mac_addresses[i][1], mac_addresses[i][2],
786               mac_addresses[i][3], mac_addresses[i][4], mac_addresses[i][5],
787               sw_if_indexes[i]);
788     }
789   bool seen[num_ifs];
790   memset (&seen, 0, sizeof (seen));
791   sw_interface_dump_ctx dctx = { false, num_ifs, sw_if_indexes, seen, 0 };
792   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
793   dump->payload.name_filter_valid = 0;
794   memset (dump->payload.name_filter, 0, sizeof (dump->payload.name_filter));
795   while (VAPI_EAGAIN ==
796          (rv =
797           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
798     ;
799   for (i = 0; i < num_ifs; ++i)
800     {
801       ck_assert_int_eq (false, seen[i]);
802     }
803   memset (&seen, 0, sizeof (seen));
804   ck_assert_int_eq (false, dctx.last_called);
805   rv = vapi_dispatch (ctx);
806   ck_assert_int_eq (VAPI_OK, rv);
807   for (i = 0; i < num_ifs; ++i)
808     {
809       ck_assert_int_eq (true, seen[i]);
810     }
811   memset (&seen, 0, sizeof (seen));
812   ck_assert_int_eq (true, dctx.last_called);
813   for (i = 0; i < num_ifs; ++i)
814     {
815       vapi_msg_delete_loopback *dl = vapi_alloc_delete_loopback (ctx);
816       dl->payload.sw_if_index = sw_if_indexes[i];
817       while (VAPI_EAGAIN ==
818              (rv =
819               vapi_delete_loopback (ctx, dl, loopback_delete_cb, &dlcs[i])))
820         ;
821       ck_assert_int_eq (VAPI_OK, rv);
822     }
823   rv = vapi_dispatch (ctx);
824   ck_assert_int_eq (VAPI_OK, rv);
825   for (i = 0; i < num_ifs; ++i)
826     {
827       ck_assert_int_eq (1, dlcs[i].called);
828       printf ("Deleted loopback with sw_if_index %u\n", sw_if_indexes[i]);
829     }
830   memset (&seen, 0, sizeof (seen));
831   dctx.last_called = false;
832   dump = vapi_alloc_sw_interface_dump (ctx);
833   dump->payload.name_filter_valid = 0;
834   memset (dump->payload.name_filter, 0, sizeof (dump->payload.name_filter));
835   while (VAPI_EAGAIN ==
836          (rv =
837           vapi_sw_interface_dump (ctx, dump, sw_interface_dump_cb, &dctx)))
838     ;
839   rv = vapi_dispatch (ctx);
840   ck_assert_int_eq (VAPI_OK, rv);
841   for (i = 0; i < num_ifs; ++i)
842     {
843       ck_assert_int_eq (false, seen[i]);
844     }
845   memset (&seen, 0, sizeof (seen));
846   ck_assert_int_eq (true, dctx.last_called);
847 }
848
849 END_TEST;
850
851 vapi_error_e
852 interface_simple_stats_cb (vapi_ctx_t ctx, void *callback_ctx,
853                            vapi_error_e rv, bool is_last,
854                            vapi_payload_want_interface_simple_stats_reply *
855                            payload)
856 {
857   return VAPI_OK;
858 }
859
860 vapi_error_e
861 simple_counters_cb (vapi_ctx_t ctx, void *callback_ctx,
862                     vapi_payload_vnet_interface_simple_counters * payload)
863 {
864   int *called = callback_ctx;
865   ++*called;
866   printf ("simple counters: first_sw_if_index=%u\n",
867           payload->first_sw_if_index);
868   return VAPI_OK;
869 }
870
871 START_TEST (test_stats_1)
872 {
873   printf ("--- Receive stats using generic blocking API ---\n");
874   vapi_msg_want_interface_simple_stats *ws =
875     vapi_alloc_want_interface_simple_stats (ctx);
876   ws->payload.enable_disable = 1;
877   ws->payload.pid = getpid ();
878   vapi_error_e rv;
879   rv = vapi_want_interface_simple_stats (ctx, ws, interface_simple_stats_cb,
880                                          NULL);
881   ck_assert_int_eq (VAPI_OK, rv);
882   int called = 0;
883   vapi_set_event_cb (ctx, vapi_msg_id_vnet_interface_simple_counters,
884                      (vapi_event_cb) simple_counters_cb, &called);
885   rv = vapi_dispatch_one (ctx);
886   ck_assert_int_eq (VAPI_OK, rv);
887   ck_assert_int_eq (1, called);
888 }
889
890 END_TEST;
891
892 START_TEST (test_stats_2)
893 {
894   printf ("--- Receive stats using stat-specific blocking API ---\n");
895   vapi_msg_want_interface_simple_stats *ws =
896     vapi_alloc_want_interface_simple_stats (ctx);
897   ws->payload.enable_disable = 1;
898   ws->payload.pid = getpid ();
899   vapi_error_e rv;
900   rv = vapi_want_interface_simple_stats (ctx, ws, interface_simple_stats_cb,
901                                          NULL);
902   ck_assert_int_eq (VAPI_OK, rv);
903   int called = 0;
904   vapi_set_vapi_msg_vnet_interface_simple_counters_event_cb (ctx,
905                                                              simple_counters_cb,
906                                                              &called);
907   rv = vapi_dispatch_one (ctx);
908   ck_assert_int_eq (VAPI_OK, rv);
909   ck_assert_int_eq (1, called);
910 }
911
912 END_TEST;
913
914 vapi_error_e
915 generic_cb (vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *msg)
916 {
917   int *called = callback_ctx;
918   ck_assert_int_eq (0, *called);
919   ++*called;
920   ck_assert_int_eq (id, vapi_msg_id_show_version_reply);
921   ck_assert_ptr_ne (NULL, msg);
922   vapi_msg_show_version_reply *reply = msg;
923   ck_assert_str_eq ("vpe", (char *) reply->payload.program);
924   return VAPI_OK;
925 }
926
927 START_TEST (test_show_version_5)
928 {
929   printf ("--- Receive show version using generic callback - nonblocking "
930           "API ---\n");
931   vapi_error_e rv;
932   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
933   ck_assert_ptr_ne (NULL, sv);
934   vapi_msg_show_version_hton (sv);
935   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
936     ;
937   ck_assert_int_eq (VAPI_OK, rv);
938   int called = 0;
939   vapi_set_generic_event_cb (ctx, generic_cb, &called);
940   ck_assert_int_eq (VAPI_OK, rv);
941   rv = vapi_dispatch_one (ctx);
942   ck_assert_int_eq (VAPI_OK, rv);
943   ck_assert_int_eq (1, called);
944   sv = vapi_alloc_show_version (ctx);
945   ck_assert_ptr_ne (NULL, sv);
946   vapi_msg_show_version_hton (sv);
947   while (VAPI_EAGAIN == (rv = vapi_send (ctx, sv)))
948     ;
949   ck_assert_int_eq (VAPI_OK, rv);
950   vapi_clear_generic_event_cb (ctx);
951   rv = vapi_dispatch_one (ctx);
952   ck_assert_int_eq (VAPI_OK, rv);
953   ck_assert_int_eq (1, called); /* needs to remain unchanged */
954 }
955
956 END_TEST;
957
958 vapi_error_e
959 combined_counters_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
960                       vapi_payload_vnet_interface_combined_counters * payload)
961 {
962   int *called = callback_ctx;
963   ++*called;
964   printf ("combined counters: first_sw_if_index=%u\n",
965           payload->first_sw_if_index);
966   return VAPI_OK;
967 }
968
969 vapi_error_e
970 stats_cb (vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
971           bool is_last, vapi_payload_want_stats_reply * payload)
972 {
973   return VAPI_OK;
974 }
975
976 START_TEST (test_stats_3)
977 {
978   printf ("--- Receive multiple stats using stat-specific non-blocking API "
979           "---\n");
980   vapi_msg_want_stats *ws = vapi_alloc_want_stats (ctx);
981   ws->payload.enable_disable = 1;
982   ws->payload.pid = getpid ();
983   vapi_error_e rv;
984   rv = vapi_want_stats (ctx, ws, stats_cb, NULL);
985   ck_assert_int_eq (VAPI_OK, rv);
986   int called = 0;
987   int called2 = 0;
988   vapi_set_vapi_msg_vnet_interface_simple_counters_event_cb (ctx,
989                                                              simple_counters_cb,
990                                                              &called);
991   vapi_set_vapi_msg_vnet_interface_combined_counters_event_cb (ctx,
992                                                                combined_counters_cb,
993                                                                &called2);
994   while (!called || !called2)
995     {
996       if (VAPI_EAGAIN != (rv = vapi_dispatch_one (ctx)))
997         {
998           ck_assert_int_eq (VAPI_OK, rv);
999         }
1000     }
1001 }
1002
1003 END_TEST;
1004
1005 vapi_error_e
1006 show_version_no_cb (vapi_ctx_t ctx, void *caller_ctx,
1007                     vapi_error_e rv, bool is_last,
1008                     vapi_payload_show_version_reply * p)
1009 {
1010   ck_assert_int_eq (VAPI_ENORESP, rv);
1011   ck_assert_int_eq (true, is_last);
1012   ck_assert_ptr_eq (NULL, p);
1013   ++*(int *) caller_ctx;
1014   return VAPI_OK;
1015 }
1016
1017 START_TEST (test_no_response_1)
1018 {
1019   printf ("--- Simulate no response to regular message ---\n");
1020   vapi_error_e rv;
1021   vapi_msg_show_version *sv = vapi_alloc_show_version (ctx);
1022   ck_assert_ptr_ne (NULL, sv);
1023   sv->header._vl_msg_id = ~0;   /* malformed ID causes vpp to drop the msg */
1024   int called = 0;
1025   while (VAPI_EAGAIN ==
1026          (rv = vapi_show_version (ctx, sv, show_version_no_cb, &called)))
1027     ;
1028   ck_assert_int_eq (VAPI_OK, rv);
1029   sv = vapi_alloc_show_version (ctx);
1030   ck_assert_ptr_ne (NULL, sv);
1031   while (VAPI_EAGAIN ==
1032          (rv = vapi_show_version (ctx, sv, show_version_cb, &called)))
1033     ;
1034   ck_assert_int_eq (VAPI_OK, rv);
1035   rv = vapi_dispatch (ctx);
1036   ck_assert_int_eq (VAPI_OK, rv);
1037   ck_assert_int_eq (2, called);
1038 }
1039
1040 END_TEST;
1041
1042 vapi_error_e
1043 no_msg_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
1044            vapi_error_e rv, bool is_last,
1045            vapi_payload_sw_interface_details * reply)
1046 {
1047   int *called = callback_ctx;
1048   ++*called;
1049   ck_assert_int_eq (VAPI_OK, rv);
1050   ck_assert_int_eq (true, is_last);
1051   ck_assert_ptr_eq (NULL, reply);
1052   return VAPI_OK;
1053 }
1054
1055 START_TEST (test_no_response_2)
1056 {
1057   printf ("--- Simulate no response to dump message ---\n");
1058   vapi_error_e rv;
1059   vapi_msg_sw_interface_dump *dump = vapi_alloc_sw_interface_dump (ctx);
1060   dump->header._vl_msg_id = ~0; /* malformed ID causes vpp to drop the msg */
1061   int no_called = 0;
1062   while (VAPI_EAGAIN ==
1063          (rv = vapi_sw_interface_dump (ctx, dump, no_msg_cb, &no_called)))
1064     ;
1065   ck_assert_int_eq (VAPI_OK, rv);
1066   rv = vapi_dispatch (ctx);
1067   ck_assert_int_eq (VAPI_OK, rv);
1068   ck_assert_int_eq (1, no_called);
1069 }
1070
1071 END_TEST;
1072 Suite *
1073 test_suite (void)
1074 {
1075   Suite *s = suite_create ("VAPI test");
1076
1077   TCase *tc_negative = tcase_create ("Negative tests");
1078   tcase_add_test (tc_negative, test_invalid_values);
1079   suite_add_tcase (s, tc_negative);
1080
1081   TCase *tc_swap = tcase_create ("Byteswap tests");
1082   tcase_add_test (tc_swap, test_hton_1);
1083   tcase_add_test (tc_swap, test_hton_2);
1084   tcase_add_test (tc_swap, test_hton_3);
1085   tcase_add_test (tc_swap, test_hton_4);
1086   tcase_add_test (tc_swap, test_ntoh_1);
1087   tcase_add_test (tc_swap, test_ntoh_2);
1088   tcase_add_test (tc_swap, test_ntoh_3);
1089   tcase_add_test (tc_swap, test_ntoh_4);
1090   suite_add_tcase (s, tc_swap);
1091
1092   TCase *tc_connect = tcase_create ("Connect");
1093   tcase_add_test (tc_connect, test_connect);
1094   suite_add_tcase (s, tc_connect);
1095
1096   TCase *tc_block = tcase_create ("Blocking API");
1097   tcase_set_timeout (tc_block, 25);
1098   tcase_add_checked_fixture (tc_block, setup_blocking, teardown);
1099   tcase_add_test (tc_block, test_show_version_1);
1100   tcase_add_test (tc_block, test_show_version_2);
1101   tcase_add_test (tc_block, test_loopbacks_1);
1102   tcase_add_test (tc_block, test_stats_1);
1103   tcase_add_test (tc_block, test_stats_2);
1104   suite_add_tcase (s, tc_block);
1105
1106   TCase *tc_nonblock = tcase_create ("Nonblocking API");
1107   tcase_set_timeout (tc_nonblock, 25);
1108   tcase_add_checked_fixture (tc_nonblock, setup_nonblocking, teardown);
1109   tcase_add_test (tc_nonblock, test_show_version_3);
1110   tcase_add_test (tc_nonblock, test_show_version_4);
1111   tcase_add_test (tc_nonblock, test_show_version_5);
1112   tcase_add_test (tc_nonblock, test_loopbacks_2);
1113   tcase_add_test (tc_nonblock, test_stats_3);
1114   tcase_add_test (tc_nonblock, test_no_response_1);
1115   tcase_add_test (tc_nonblock, test_no_response_2);
1116   suite_add_tcase (s, tc_nonblock);
1117
1118   return s;
1119 }
1120
1121 int
1122 main (int argc, char *argv[])
1123 {
1124   if (3 != argc)
1125     {
1126       printf ("Invalid argc==`%d'\n", argc);
1127       return EXIT_FAILURE;
1128     }
1129   app_name = argv[1];
1130   api_prefix = argv[2];
1131   printf ("App name: `%s', API prefix: `%s'\n", app_name, api_prefix);
1132
1133   int number_failed;
1134   Suite *s;
1135   SRunner *sr;
1136
1137   s = test_suite ();
1138   sr = srunner_create (s);
1139
1140   srunner_run_all (sr, CK_NORMAL);
1141   number_failed = srunner_ntests_failed (sr);
1142   srunner_free (sr);
1143   return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1144 }
1145
1146 /*
1147  * fd.io coding-style-patch-verification: ON
1148  *
1149  * Local Variables:
1150  * eval: (c-set-style "gnu")
1151  * End:
1152  */