test/crypto: skip null auth in ICV corrupt case
[dpdk.git] / app / test / test_interrupts.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <unistd.h>
8
9 #include <rte_common.h>
10 #include <rte_cycles.h>
11 #include <rte_interrupts.h>
12
13 #include "test.h"
14
15 #define TEST_INTERRUPT_CHECK_INTERVAL 100 /* ms */
16
17 /* predefined interrupt handle types */
18 enum test_interrupt_handle_type {
19         TEST_INTERRUPT_HANDLE_INVALID = 0,
20         TEST_INTERRUPT_HANDLE_VALID,
21         TEST_INTERRUPT_HANDLE_VALID_UIO,
22         TEST_INTERRUPT_HANDLE_VALID_ALARM,
23         TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT,
24         TEST_INTERRUPT_HANDLE_CASE1,
25         TEST_INTERRUPT_HANDLE_MAX
26 };
27
28 /* flag of if callback is called */
29 static volatile int flag;
30 static struct rte_intr_handle *intr_handles[TEST_INTERRUPT_HANDLE_MAX];
31 static enum test_interrupt_handle_type test_intr_type =
32                                 TEST_INTERRUPT_HANDLE_MAX;
33
34 #ifdef RTE_EXEC_ENV_LINUX
35 union intr_pipefds{
36         struct {
37                 int pipefd[2];
38         };
39         struct {
40                 int readfd;
41                 int writefd;
42         };
43 };
44
45 static union intr_pipefds pfds;
46
47 /**
48  * Check if the interrupt handle is valid.
49  */
50 static inline int
51 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
52 {
53         if (!intr_handle || rte_intr_fd_get(intr_handle) < 0)
54                 return -1;
55
56         return 0;
57 }
58
59 /**
60  * Initialization for interrupt test.
61  */
62 static int
63 test_interrupt_init(void)
64 {
65         struct rte_intr_handle *test_intr_handle;
66         int i;
67
68         if (pipe(pfds.pipefd) < 0)
69                 return -1;
70
71         for (i = 0; i < TEST_INTERRUPT_HANDLE_MAX; i++) {
72                 intr_handles[i] =
73                         rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
74                 if (!intr_handles[i])
75                         return -1;
76         }
77
78         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
79         if (rte_intr_fd_set(test_intr_handle, -1))
80                 return -1;
81         if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UNKNOWN))
82                 return -1;
83
84         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
85         if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
86                 return -1;
87         if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UNKNOWN))
88                 return -1;
89
90         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
91         if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
92                 return -1;
93         if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UIO))
94                 return -1;
95
96         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
97         if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
98                 return -1;
99         if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_ALARM))
100                 return -1;
101
102         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
103         if (rte_intr_fd_set(test_intr_handle, pfds.readfd))
104                 return -1;
105         if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_DEV_EVENT))
106                 return -1;
107
108         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
109         if (rte_intr_fd_set(test_intr_handle, pfds.writefd))
110                 return -1;
111         if (rte_intr_type_set(test_intr_handle, RTE_INTR_HANDLE_UIO))
112                 return -1;
113
114         return 0;
115 }
116
117 /**
118  * Deinitialization for interrupt test.
119  */
120 static int
121 test_interrupt_deinit(void)
122 {
123         int i;
124
125         for (i = 0; i < TEST_INTERRUPT_HANDLE_MAX; i++)
126                 rte_intr_instance_free(intr_handles[i]);
127         close(pfds.pipefd[0]);
128         close(pfds.pipefd[1]);
129
130         return 0;
131 }
132
133 /**
134  * Write the pipe to simulate an interrupt.
135  */
136 static int
137 test_interrupt_trigger_interrupt(void)
138 {
139         if (write(pfds.writefd, "1", 1) < 0)
140                 return -1;
141
142         return 0;
143 }
144
145 /**
146  * Check if two interrupt handles are the same.
147  */
148 static int
149 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
150                                 struct rte_intr_handle *intr_handle_r)
151 {
152         if (!intr_handle_l || !intr_handle_r)
153                 return -1;
154
155         if (rte_intr_fd_get(intr_handle_l) !=
156             rte_intr_fd_get(intr_handle_r) ||
157                 rte_intr_type_get(intr_handle_l) !=
158                 rte_intr_type_get(intr_handle_r))
159                 return -1;
160
161         return 0;
162 }
163
164 #else
165 /* to be implemented for bsd later */
166 static inline int
167 test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
168 {
169         RTE_SET_USED(intr_handle);
170
171         return 0;
172 }
173
174 static int
175 test_interrupt_init(void)
176 {
177         return 0;
178 }
179
180 static int
181 test_interrupt_deinit(void)
182 {
183         return 0;
184 }
185
186 static int
187 test_interrupt_trigger_interrupt(void)
188 {
189         return 0;
190 }
191
192 static int
193 test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
194                                 struct rte_intr_handle *intr_handle_r)
195 {
196         (void)intr_handle_l;
197         (void)intr_handle_r;
198
199         return 0;
200 }
201 #endif /* RTE_EXEC_ENV_LINUX */
202
203 /**
204  * Callback for the test interrupt.
205  */
206 static void
207 test_interrupt_callback(void *arg)
208 {
209         struct rte_intr_handle *intr_handle = arg;
210         struct rte_intr_handle *test_intr_handle;
211
212         if (test_intr_type >= TEST_INTERRUPT_HANDLE_MAX) {
213                 printf("invalid interrupt type\n");
214                 flag = -1;
215                 return;
216         }
217
218         if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
219                 printf("null or invalid intr_handle for %s\n", __func__);
220                 flag = -1;
221                 return;
222         }
223
224         if (rte_intr_callback_unregister(intr_handle,
225                         test_interrupt_callback, arg) >= 0) {
226                 printf("%s: unexpectedly able to unregister itself\n",
227                         __func__);
228                 flag = -1;
229                 return;
230         }
231
232         test_intr_handle = intr_handles[test_intr_type];
233         if (test_interrupt_handle_compare(intr_handle, test_intr_handle) == 0)
234                 flag = 1;
235 }
236
237 /**
238  * Callback for the test interrupt.
239  */
240 static void
241 test_interrupt_callback_1(void *arg)
242 {
243         struct rte_intr_handle *intr_handle = arg;
244         if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
245                 printf("null or invalid intr_handle for %s\n", __func__);
246                 flag = -1;
247                 return;
248         }
249 }
250
251 /**
252  * Tests for rte_intr_enable().
253  */
254 static int
255 test_interrupt_enable(void)
256 {
257         struct rte_intr_handle *test_intr_handle;
258
259         /* check with null intr_handle */
260         if (rte_intr_enable(NULL) == 0) {
261                 printf("unexpectedly enable null intr_handle successfully\n");
262                 return -1;
263         }
264
265         /* check with invalid intr_handle */
266         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
267         if (rte_intr_enable(test_intr_handle) == 0) {
268                 printf("unexpectedly enable invalid intr_handle "
269                         "successfully\n");
270                 return -1;
271         }
272
273         /* check with valid intr_handle */
274         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
275         if (rte_intr_enable(test_intr_handle) == 0) {
276                 printf("unexpectedly enable a specific intr_handle "
277                         "successfully\n");
278                 return -1;
279         }
280
281         /* check with specific valid intr_handle */
282         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
283         if (rte_intr_enable(test_intr_handle) == 0) {
284                 printf("unexpectedly enable a specific intr_handle "
285                         "successfully\n");
286                 return -1;
287         }
288
289         /* check with specific valid intr_handle */
290         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
291         if (rte_intr_enable(test_intr_handle) == 0) {
292                 printf("unexpectedly enable a specific intr_handle "
293                         "successfully\n");
294                 return -1;
295         }
296
297         /* check with valid handler and its type */
298         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
299         if (rte_intr_enable(test_intr_handle) < 0) {
300                 printf("fail to enable interrupt on a simulated handler\n");
301                 return -1;
302         }
303
304         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
305         if (rte_intr_enable(test_intr_handle) == 0) {
306                 printf("unexpectedly enable a specific intr_handle "
307                         "successfully\n");
308                 return -1;
309         }
310
311         return 0;
312 }
313
314 /**
315  * Tests for rte_intr_disable().
316  */
317 static int
318 test_interrupt_disable(void)
319 {
320         struct rte_intr_handle *test_intr_handle;
321
322         /* check with null intr_handle */
323         if (rte_intr_disable(NULL) == 0) {
324                 printf("unexpectedly disable null intr_handle "
325                         "successfully\n");
326                 return -1;
327         }
328
329         /* check with invalid intr_handle */
330         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
331         if (rte_intr_disable(test_intr_handle) == 0) {
332                 printf("unexpectedly disable invalid intr_handle "
333                         "successfully\n");
334                 return -1;
335         }
336
337         /* check with valid intr_handle */
338         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
339         if (rte_intr_disable(test_intr_handle) == 0) {
340                 printf("unexpectedly disable a specific intr_handle "
341                         "successfully\n");
342                 return -1;
343         }
344
345         /* check with specific valid intr_handle */
346         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
347         if (rte_intr_disable(test_intr_handle) == 0) {
348                 printf("unexpectedly disable a specific intr_handle "
349                         "successfully\n");
350                 return -1;
351         }
352
353         /* check with specific valid intr_handle */
354         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
355         if (rte_intr_disable(test_intr_handle) == 0) {
356                 printf("unexpectedly disable a specific intr_handle "
357                         "successfully\n");
358                 return -1;
359         }
360
361         /* check with valid handler and its type */
362         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
363         if (rte_intr_disable(test_intr_handle) < 0) {
364                 printf("fail to disable interrupt on a simulated handler\n");
365                 return -1;
366         }
367
368         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
369         if (rte_intr_disable(test_intr_handle) == 0) {
370                 printf("unexpectedly disable a specific intr_handle "
371                         "successfully\n");
372                 return -1;
373         }
374
375         return 0;
376 }
377
378 /**
379  * Check the full path of a specified type of interrupt simulated.
380  */
381 static int
382 test_interrupt_full_path_check(enum test_interrupt_handle_type intr_type)
383 {
384         int count;
385         struct rte_intr_handle *test_intr_handle;
386
387         flag = 0;
388         test_intr_handle = intr_handles[intr_type];
389         test_intr_type = intr_type;
390         if (rte_intr_callback_register(test_intr_handle,
391                         test_interrupt_callback, test_intr_handle) < 0) {
392                 printf("fail to register callback\n");
393                 return -1;
394         }
395
396         if (test_interrupt_trigger_interrupt() < 0)
397                 return -1;
398
399         /* check flag */
400         for (count = 0; flag == 0 && count < 3; count++)
401                 rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
402
403         rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
404         while ((count =
405                 rte_intr_callback_unregister(test_intr_handle,
406                                              test_interrupt_callback,
407                                              test_intr_handle)) < 0) {
408                 if (count != -EAGAIN)
409                         return -1;
410         }
411
412         if (flag == 0) {
413                 printf("callback has not been called\n");
414                 return -1;
415         } else if (flag < 0) {
416                 printf("it has internal error in callback\n");
417                 return -1;
418         }
419
420         return 0;
421 }
422
423 /**
424  * Main function of testing interrupt.
425  */
426 static int
427 test_interrupt(void)
428 {
429         int ret = -1;
430         struct rte_intr_handle *test_intr_handle;
431
432         if (test_interrupt_init() < 0) {
433                 printf("fail to initialize for testing interrupt\n");
434                 goto out;
435         }
436
437         printf("Check unknown valid interrupt full path\n");
438         if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID) < 0) {
439                 printf("failure occurred during checking unknown valid "
440                                                 "interrupt full path\n");
441                 goto out;
442         }
443
444         printf("Check valid UIO interrupt full path\n");
445         if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_UIO)
446                                                                         < 0) {
447                 printf("failure occurred during checking valid UIO interrupt "
448                                                                 "full path\n");
449                 goto out;
450         }
451
452         printf("Check valid device event interrupt full path\n");
453         if (test_interrupt_full_path_check(
454                 TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT) < 0) {
455                 printf("failure occurred during checking valid device event "
456                                                 "interrupt full path\n");
457                 goto out;
458         }
459
460         printf("Check valid alarm interrupt full path\n");
461         if (test_interrupt_full_path_check(
462                 TEST_INTERRUPT_HANDLE_VALID_ALARM) < 0) {
463                 printf("failure occurred during checking valid alarm "
464                                                 "interrupt full path\n");
465                 goto out;
466         }
467
468         printf("start register/unregister test\n");
469         /* check if it will fail to register cb with intr_handle = NULL */
470         if (rte_intr_callback_register(NULL, test_interrupt_callback,
471                                                         NULL) == 0) {
472                 printf("unexpectedly register successfully with null "
473                         "intr_handle\n");
474                 goto out;
475         }
476
477         /* check if it will fail to register cb with invalid intr_handle */
478         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
479         if (rte_intr_callback_register(test_intr_handle,
480                         test_interrupt_callback, test_intr_handle) == 0) {
481                 printf("unexpectedly register successfully with invalid "
482                         "intr_handle\n");
483                 goto out;
484         }
485
486         /* check if it will fail to register without callback */
487         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
488         if (rte_intr_callback_register(test_intr_handle, NULL,
489                                        test_intr_handle) == 0) {
490                 printf("unexpectedly register successfully with "
491                         "null callback\n");
492                 goto out;
493         }
494
495         /* check if it will fail to unregister cb with intr_handle = NULL */
496         if (rte_intr_callback_unregister(NULL,
497                         test_interrupt_callback, NULL) > 0) {
498                 printf("unexpectedly unregister successfully with "
499                         "null intr_handle\n");
500                 goto out;
501         }
502
503         /* check if it will fail to unregister cb with invalid intr_handle */
504         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
505         if (rte_intr_callback_unregister(test_intr_handle,
506                         test_interrupt_callback, test_intr_handle) > 0) {
507                 printf("unexpectedly unregister successfully with "
508                         "invalid intr_handle\n");
509                 goto out;
510         }
511
512         /* check if it is ok to register the same intr_handle twice */
513         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
514         if (rte_intr_callback_register(test_intr_handle,
515                         test_interrupt_callback, test_intr_handle) < 0) {
516                 printf("it fails to register test_interrupt_callback\n");
517                 goto out;
518         }
519         if (rte_intr_callback_register(test_intr_handle,
520                         test_interrupt_callback_1, test_intr_handle) < 0) {
521                 printf("it fails to register test_interrupt_callback_1\n");
522                 goto out;
523         }
524         /* check if it will fail to unregister with invalid parameter */
525         if (rte_intr_callback_unregister(test_intr_handle,
526                         test_interrupt_callback, (void *)0xff) != 0) {
527                 printf("unexpectedly unregisters successfully with "
528                                                         "invalid arg\n");
529                 goto out;
530         }
531         if (rte_intr_callback_unregister(test_intr_handle,
532                         test_interrupt_callback, test_intr_handle) <= 0) {
533                 printf("it fails to unregister test_interrupt_callback\n");
534                 goto out;
535         }
536         if (rte_intr_callback_unregister(test_intr_handle,
537                         test_interrupt_callback_1, (void *)-1) <= 0) {
538                 printf("it fails to unregister test_interrupt_callback_1 "
539                         "for all\n");
540                 goto out;
541         }
542         rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
543
544         printf("start interrupt enable/disable test\n");
545         /* check interrupt enable/disable functions */
546         if (test_interrupt_enable() < 0) {
547                 printf("fail to check interrupt enabling\n");
548                 goto out;
549         }
550         rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
551
552         if (test_interrupt_disable() < 0) {
553                 printf("fail to check interrupt disabling\n");
554                 goto out;
555         }
556         rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
557
558         ret = 0;
559
560 out:
561         printf("Clearing for interrupt tests\n");
562         /* clear registered callbacks */
563         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
564         rte_intr_callback_unregister(test_intr_handle,
565                         test_interrupt_callback, (void *)-1);
566         rte_intr_callback_unregister(test_intr_handle,
567                         test_interrupt_callback_1, (void *)-1);
568
569         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
570         rte_intr_callback_unregister(test_intr_handle,
571                         test_interrupt_callback, (void *)-1);
572         rte_intr_callback_unregister(test_intr_handle,
573                         test_interrupt_callback_1, (void *)-1);
574
575         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
576         rte_intr_callback_unregister(test_intr_handle,
577                         test_interrupt_callback, (void *)-1);
578         rte_intr_callback_unregister(test_intr_handle,
579                         test_interrupt_callback_1, (void *)-1);
580
581         test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
582         rte_intr_callback_unregister(test_intr_handle,
583                         test_interrupt_callback, (void *)-1);
584         rte_intr_callback_unregister(test_intr_handle,
585                         test_interrupt_callback_1, (void *)-1);
586
587         rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL);
588         /* deinit */
589         test_interrupt_deinit();
590
591         return ret;
592 }
593
594 REGISTER_TEST_COMMAND(interrupt_autotest, test_interrupt);