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