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