blob: ad75ad6e8b8b1cf62194c403ee9a71e074430632 [file] [log] [blame]
Klement Sekera8f2a4ea2017-05-04 06:15:18 +02001/*
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>
Klement Sekeradc15be22017-06-12 06:49:33 +020025#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>
Klement Sekera8f2a4ea2017-05-04 06:15:18 +020031
32DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
33DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
34DEFINE_VAPI_MSG_IDS_L2_API_JSON;
35DEFINE_VAPI_MSG_IDS_STATS_API_JSON;
Klement Sekeradc15be22017-06-12 06:49:33 +020036DEFINE_VAPI_MSG_IDS_FAKE_API_JSON;
Klement Sekera8f2a4ea2017-05-04 06:15:18 +020037
38static char *app_name = NULL;
39static char *api_prefix = NULL;
40static const int max_outstanding_requests = 64;
41static const int response_queue_size = 32;
42
Klement Sekerad3e671e2017-09-29 12:36:37 +020043/* 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
Klement Sekera8f2a4ea2017-05-04 06:15:18 +020053START_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);
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);
70 ck_assert_int_eq (VAPI_EINVAL, rv);
71 rv = vapi_recv (ctx, NULL, NULL);
72 ck_assert_int_eq (VAPI_EINVAL, rv);
73 vapi_msg_show_version_reply *reply;
74 rv = vapi_recv (ctx, (void **) &reply, NULL);
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
81END_TEST;
82
83START_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
92END_TEST;
93
94START_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
106END_TEST;
107
108START_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
141END_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
157START_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
253END_TEST;
254
255START_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
264END_TEST;
265
266START_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
278END_TEST;
279
280START_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
314END_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
330START_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
425END_TEST;
426
427vapi_error_e
428show_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
443typedef struct
444{
445 int called;
446 int expected_retval;
447 u32 *sw_if_index_storage;
448} test_create_loopback_ctx_t;
449
450vapi_error_e
451loopback_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
462typedef struct
463{
464 int called;
465 int expected_retval;
466 u32 *sw_if_index_storage;
467} test_delete_loopback_ctx_t;
468
469vapi_error_e
470loopback_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
480START_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);
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
493END_TEST;
494
495vapi_ctx_t ctx;
496
497void
498setup_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);
504 ck_assert_int_eq (VAPI_OK, rv);
505}
506
507void
508setup_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);
514 ck_assert_int_eq (VAPI_OK, rv);
515}
516
517void
518teardown (void)
519{
520 vapi_disconnect (ctx);
521 vapi_ctx_free (ctx);
522}
523
524START_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);
535 ck_assert_int_eq (VAPI_OK, rv);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200536 int dummy;
Klement Sekeradc15be22017-06-12 06:49:33 +0200537 show_version_cb (NULL, &dummy, VAPI_OK, true, &resp->payload);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200538 vapi_msg_free (ctx, resp);
539}
540
541END_TEST;
542
543START_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
559END_TEST;
560
561typedef 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
570vapi_error_e
571sw_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 {
Klement Sekerad3e671e2017-09-29 12:36:37 +0200584 ck_assert (NULL != reply);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200585 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
601START_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
693END_TEST;
694
695START_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
716END_TEST;
717
718START_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
756END_TEST;
757
758START_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
860END_TEST;
861
862vapi_error_e
863interface_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
871vapi_error_e
872simple_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
882START_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
901END_TEST;
902
903START_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
923END_TEST;
924
925vapi_error_e
926generic_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
938START_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
967END_TEST;
968
969vapi_error_e
970combined_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
980vapi_error_e
981stats_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
987START_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
1014END_TEST;
1015
1016vapi_error_e
1017show_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
1028START_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
1051END_TEST;
1052
1053vapi_error_e
1054no_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
1066START_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
1082END_TEST;
Klement Sekeradc15be22017-06-12 06:49:33 +02001083
1084START_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
1091END_TEST;
1092
Klement Sekera8f2a4ea2017-05-04 06:15:18 +02001093Suite *
1094test_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
Klement Sekeradc15be22017-06-12 06:49:33 +02001139 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
Klement Sekera8f2a4ea2017-05-04 06:15:18 +02001144 return s;
1145}
1146
1147int
1148main (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 */