uringmachine 0.8.2 → 0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/TODO.md +0 -1
- data/examples/bm_side_running.rb +83 -0
- data/examples/bm_sqlite.rb +1 -1
- data/ext/um/um.c +66 -4
- data/ext/um/um.h +36 -0
- data/ext/um/um_class.c +6 -0
- data/ext/um/um_const.c +36 -0
- data/ext/um/um_ext.c +2 -0
- data/ext/um/um_stream.c +344 -0
- data/ext/um/um_stream_class.c +140 -0
- data/ext/um/um_utils.c +4 -0
- data/lib/uringmachine/actor.rb +1 -1
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +35 -17
- data/test/test_fiber.rb +23 -3
- data/test/test_stream.rb +133 -0
- data/test/test_um.rb +109 -2
- data/uringmachine.gemspec +0 -2
- data/vendor/liburing/.github/workflows/{build.yml → ci.yml} +107 -42
- data/vendor/liburing/.gitignore +1 -0
- data/vendor/liburing/CHANGELOG +10 -0
- data/vendor/liburing/README +5 -0
- data/vendor/liburing/configure +1 -1
- data/vendor/liburing/examples/Makefile +1 -0
- data/vendor/liburing/examples/helpers.c +25 -0
- data/vendor/liburing/examples/helpers.h +13 -0
- data/vendor/liburing/examples/io_uring-test.c +3 -0
- data/vendor/liburing/examples/proxy.c +1 -1
- data/vendor/liburing/examples/reg-wait.c +41 -6
- data/vendor/liburing/examples/send-zerocopy.c +79 -32
- data/vendor/liburing/examples/zcrx.c +436 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/Makefile +0 -1
- data/vendor/liburing/src/arch/generic/syscall.h +2 -2
- data/vendor/liburing/src/arch/syscall-defs.h +2 -2
- data/vendor/liburing/src/include/liburing/io_uring.h +101 -17
- data/vendor/liburing/src/include/liburing.h +179 -59
- data/vendor/liburing/src/int_flags.h +4 -1
- data/vendor/liburing/src/liburing-ffi.map +14 -2
- data/vendor/liburing/src/liburing.map +9 -2
- data/vendor/liburing/src/queue.c +35 -30
- data/vendor/liburing/src/register.c +46 -15
- data/vendor/liburing/src/sanitize.c +6 -9
- data/vendor/liburing/src/setup.c +37 -71
- data/vendor/liburing/src/syscall.c +2 -2
- data/vendor/liburing/test/232c93d07b74.c +1 -0
- data/vendor/liburing/test/Makefile +9 -0
- data/vendor/liburing/test/accept-test.c +1 -0
- data/vendor/liburing/test/cmd-discard.c +16 -8
- data/vendor/liburing/test/connect.c +11 -7
- data/vendor/liburing/test/epwait.c +420 -0
- data/vendor/liburing/test/eventfd-ring.c +30 -5
- data/vendor/liburing/test/fallocate.c +1 -1
- data/vendor/liburing/test/fixed-hugepage.c +10 -7
- data/vendor/liburing/test/fixed-seg.c +187 -0
- data/vendor/liburing/test/helpers.c +121 -0
- data/vendor/liburing/test/helpers.h +13 -0
- data/vendor/liburing/test/init-mem.c +2 -0
- data/vendor/liburing/test/io_uring_passthrough.c +78 -62
- data/vendor/liburing/test/iopoll-overflow.c +5 -4
- data/vendor/liburing/test/iopoll.c +20 -10
- data/vendor/liburing/test/iowait.c +141 -0
- data/vendor/liburing/test/nvme.h +2 -0
- data/vendor/liburing/test/pipe-bug.c +11 -5
- data/vendor/liburing/test/pipe-eof.c +11 -1
- data/vendor/liburing/test/read-inc-file.c +150 -0
- data/vendor/liburing/test/read-write.c +21 -14
- data/vendor/liburing/test/recv-bundle-short-ooo.c +435 -0
- data/vendor/liburing/test/recv-multishot.c +2 -2
- data/vendor/liburing/test/reg-wait.c +449 -120
- data/vendor/liburing/test/regbuf-clone.c +53 -0
- data/vendor/liburing/test/resize-rings.c +25 -2
- data/vendor/liburing/test/rsrc_tags.c +67 -14
- data/vendor/liburing/test/send-zerocopy.c +52 -130
- data/vendor/liburing/test/sendmsg_iov_clean.c +216 -0
- data/vendor/liburing/test/socket-nb.c +158 -0
- data/vendor/liburing/test/sqwait.c +9 -11
- data/vendor/liburing/test/timeout.c +198 -0
- data/vendor/liburing/test/vec-regbuf.c +609 -0
- data/vendor/liburing/test/wait-timeout.c +1 -1
- data/vendor/liburing/test/wq-aff.c +5 -1
- data/vendor/liburing/test/zcrx.c +928 -0
- metadata +16 -32
- data/vendor/liburing/.github/workflows/codespell.yml +0 -25
- data/vendor/liburing/.github/workflows/shellcheck.yml +0 -20
@@ -0,0 +1,928 @@
|
|
1
|
+
/* SPDX-License-Identifier: MIT */
|
2
|
+
/*
|
3
|
+
* Simple test case showing using send and recv through io_uring
|
4
|
+
*/
|
5
|
+
#include <errno.h>
|
6
|
+
#include <stdio.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <string.h>
|
9
|
+
#include <unistd.h>
|
10
|
+
#include <arpa/inet.h>
|
11
|
+
#include <sys/mman.h>
|
12
|
+
#include <sys/socket.h>
|
13
|
+
#include <sys/types.h>
|
14
|
+
#include <pthread.h>
|
15
|
+
#include <net/if.h>
|
16
|
+
|
17
|
+
#include "liburing.h"
|
18
|
+
#include "helpers.h"
|
19
|
+
|
20
|
+
static unsigned int ifidx, rxq;
|
21
|
+
|
22
|
+
static long page_size;
|
23
|
+
|
24
|
+
/* the hw rxq must consume 128 of these pages, leaving 4 left */
|
25
|
+
#define AREA_PAGES 132
|
26
|
+
#define AREA_SZ (AREA_PAGES * page_size)
|
27
|
+
#define RQ_ENTRIES 128
|
28
|
+
/* this is one more than the # of free pages after filling hw rxq */
|
29
|
+
#define LOOP_COUNT 5
|
30
|
+
#define DEV_ENV_VAR "NETIF"
|
31
|
+
#define RXQ_ENV_VAR "NETRXQ"
|
32
|
+
#define RING_FLAGS (IORING_SETUP_DEFER_TASKRUN | \
|
33
|
+
IORING_SETUP_CQE32 | \
|
34
|
+
IORING_SETUP_SINGLE_ISSUER)
|
35
|
+
|
36
|
+
static char str[] = "iv5t4dl500w7wsrf14fsuq8thptto0z7i2q62z1p8dwrv5u4kaxpqhm2rb7bapddi5gfkh7f9695eh46t2o5yap2y43gstbsq3n90bg1i7zx1m4wojoqbuxhsrw4s4y3sh9qp57ovbaa2o9yaqa7d4to2vak1otvgkoxs5t0ovjbe6roginrjeh906kmjn1289jlho9a1bud02ex4xr3cvfcybpl6axnr117p0aesb3070wlvj91en7tpf8nyb1e";
|
37
|
+
|
38
|
+
#define MSG_SIZE 512
|
39
|
+
|
40
|
+
#define PORT 10202
|
41
|
+
#define HOST "127.0.0.1"
|
42
|
+
|
43
|
+
static int probe_zcrx(void *area)
|
44
|
+
{
|
45
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
46
|
+
.addr = (__u64)(unsigned long)area,
|
47
|
+
.len = AREA_SZ,
|
48
|
+
.flags = 0,
|
49
|
+
};
|
50
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
51
|
+
.if_idx = ifidx,
|
52
|
+
.if_rxq = rxq,
|
53
|
+
.rq_entries = RQ_ENTRIES,
|
54
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
55
|
+
};
|
56
|
+
struct io_uring ring;
|
57
|
+
int ret;
|
58
|
+
|
59
|
+
ret = t_create_ring(8, &ring, RING_FLAGS);
|
60
|
+
if (ret == T_SETUP_SKIP) {
|
61
|
+
fprintf(stderr, "required ring flags are not supported, skip\n");
|
62
|
+
return T_EXIT_SKIP;
|
63
|
+
}
|
64
|
+
if (ret) {
|
65
|
+
fprintf(stderr, "probe ring setup failure\n");
|
66
|
+
return T_EXIT_FAIL;
|
67
|
+
}
|
68
|
+
|
69
|
+
ret = io_uring_register_ifq(&ring, ®);
|
70
|
+
if (ret == -EINVAL) {
|
71
|
+
fprintf(stderr, "zcrx is not supported, skip\n");
|
72
|
+
return T_EXIT_SKIP;
|
73
|
+
}
|
74
|
+
if (ret) {
|
75
|
+
fprintf(stderr, "probe zcrx register fail %i\n", ret);
|
76
|
+
return T_EXIT_FAIL;
|
77
|
+
}
|
78
|
+
io_uring_queue_exit(&ring);
|
79
|
+
return T_EXIT_PASS;
|
80
|
+
}
|
81
|
+
|
82
|
+
static int try_register_ifq(struct io_uring_zcrx_ifq_reg *reg)
|
83
|
+
{
|
84
|
+
struct io_uring ring;
|
85
|
+
int ret;
|
86
|
+
|
87
|
+
ret = t_create_ring(8, &ring, RING_FLAGS);
|
88
|
+
if (ret != T_SETUP_OK) {
|
89
|
+
fprintf(stderr, "ring create failed: %d\n", ret);
|
90
|
+
exit(T_EXIT_FAIL);
|
91
|
+
}
|
92
|
+
|
93
|
+
ret = io_uring_register_ifq(&ring, reg);
|
94
|
+
io_uring_queue_exit(&ring);
|
95
|
+
return ret;
|
96
|
+
}
|
97
|
+
|
98
|
+
static int test_invalid_if(void *area)
|
99
|
+
{
|
100
|
+
int ret;
|
101
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
102
|
+
.addr = (__u64)(unsigned long)area,
|
103
|
+
.len = AREA_SZ,
|
104
|
+
.flags = 0,
|
105
|
+
};
|
106
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
107
|
+
.if_idx = -1,
|
108
|
+
.if_rxq = rxq,
|
109
|
+
.rq_entries = RQ_ENTRIES,
|
110
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
111
|
+
};
|
112
|
+
|
113
|
+
ret = try_register_ifq(®);
|
114
|
+
if (ret != -EINVAL && ret != -ENODEV) {
|
115
|
+
fprintf(stderr, "registered invalid IF %i\n", ret);
|
116
|
+
return T_EXIT_FAIL;
|
117
|
+
}
|
118
|
+
|
119
|
+
reg.if_idx = ifidx;
|
120
|
+
reg.if_rxq = -1;
|
121
|
+
|
122
|
+
ret = try_register_ifq(®);
|
123
|
+
if (ret != -EINVAL) {
|
124
|
+
fprintf(stderr, "registered invalid IFQ %i\n", ret);
|
125
|
+
return T_EXIT_FAIL;
|
126
|
+
}
|
127
|
+
return T_EXIT_PASS;
|
128
|
+
}
|
129
|
+
|
130
|
+
static int test_invalid_ifq_collision(void *area)
|
131
|
+
{
|
132
|
+
struct io_uring ring, ring2;
|
133
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
134
|
+
.addr = (__u64)(unsigned long)area,
|
135
|
+
.len = AREA_SZ,
|
136
|
+
.flags = 0,
|
137
|
+
};
|
138
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
139
|
+
.if_idx = ifidx,
|
140
|
+
.if_rxq = rxq,
|
141
|
+
.rq_entries = RQ_ENTRIES,
|
142
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
143
|
+
};
|
144
|
+
int ret;
|
145
|
+
|
146
|
+
ret = t_create_ring(8, &ring, RING_FLAGS);
|
147
|
+
if (ret != T_SETUP_OK) {
|
148
|
+
fprintf(stderr, "ring create failed: %d\n", ret);
|
149
|
+
return T_EXIT_FAIL;
|
150
|
+
}
|
151
|
+
ret = t_create_ring(8, &ring2, RING_FLAGS);
|
152
|
+
if (ret != T_SETUP_OK) {
|
153
|
+
fprintf(stderr, "ring2 create failed: %d\n", ret);
|
154
|
+
return T_EXIT_FAIL;
|
155
|
+
}
|
156
|
+
|
157
|
+
ret = io_uring_register_ifq(&ring, ®);
|
158
|
+
if (ret) {
|
159
|
+
fprintf(stderr, "initial registration failed %i\n", ret);
|
160
|
+
return T_EXIT_FAIL;
|
161
|
+
}
|
162
|
+
|
163
|
+
/* register taken ifq */
|
164
|
+
ret = io_uring_register_ifq(&ring, ®);
|
165
|
+
if (!ret) {
|
166
|
+
fprintf(stderr, "registered taken queue\n");
|
167
|
+
return T_EXIT_FAIL;
|
168
|
+
}
|
169
|
+
|
170
|
+
ret = io_uring_register_ifq(&ring2, ®);
|
171
|
+
if (!ret) {
|
172
|
+
fprintf(stderr, "registered taken queue ring2\n");
|
173
|
+
return T_EXIT_FAIL;
|
174
|
+
}
|
175
|
+
|
176
|
+
io_uring_queue_exit(&ring);
|
177
|
+
io_uring_queue_exit(&ring2);
|
178
|
+
return T_EXIT_PASS;
|
179
|
+
}
|
180
|
+
|
181
|
+
static int test_rq_setup(void *area)
|
182
|
+
{
|
183
|
+
int ret;
|
184
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
185
|
+
.addr = (__u64)(unsigned long)area,
|
186
|
+
.len = AREA_SZ,
|
187
|
+
.flags = 0,
|
188
|
+
};
|
189
|
+
|
190
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
191
|
+
.if_idx = ifidx,
|
192
|
+
.if_rxq = rxq,
|
193
|
+
.rq_entries = 0,
|
194
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
195
|
+
};
|
196
|
+
|
197
|
+
ret = try_register_ifq(®);
|
198
|
+
if (ret != -EINVAL) {
|
199
|
+
fprintf(stderr, "registered 0 rq entries\n");
|
200
|
+
return T_EXIT_FAIL;
|
201
|
+
}
|
202
|
+
|
203
|
+
reg.rq_entries = (__u32)-1;
|
204
|
+
|
205
|
+
ret = try_register_ifq(®);
|
206
|
+
if (ret != -EINVAL) {
|
207
|
+
fprintf(stderr, "registered unlimited nr of rq entries\n");
|
208
|
+
return T_EXIT_FAIL;
|
209
|
+
}
|
210
|
+
|
211
|
+
reg.rq_entries = RQ_ENTRIES - 1;
|
212
|
+
ret = try_register_ifq(®);
|
213
|
+
if (ret != 0) {
|
214
|
+
fprintf(stderr, "ifq registration failed %i\n", ret);
|
215
|
+
return T_EXIT_FAIL;
|
216
|
+
}
|
217
|
+
|
218
|
+
if (reg.rq_entries == RQ_ENTRIES - 1) {
|
219
|
+
fprintf(stderr, "registered non pow2 refill entries %i\n",
|
220
|
+
reg.rq_entries);
|
221
|
+
return T_EXIT_FAIL;
|
222
|
+
}
|
223
|
+
|
224
|
+
return T_EXIT_PASS;
|
225
|
+
}
|
226
|
+
|
227
|
+
static int test_null_area_reg_struct(void)
|
228
|
+
{
|
229
|
+
int ret;
|
230
|
+
|
231
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
232
|
+
.if_idx = ifidx,
|
233
|
+
.if_rxq = rxq,
|
234
|
+
.rq_entries = RQ_ENTRIES,
|
235
|
+
.area_ptr = (__u64)(unsigned long)0,
|
236
|
+
};
|
237
|
+
|
238
|
+
ret = try_register_ifq(®);
|
239
|
+
return ret ? T_EXIT_PASS : T_EXIT_FAIL;
|
240
|
+
}
|
241
|
+
|
242
|
+
static int test_null_area(void)
|
243
|
+
{
|
244
|
+
int ret;
|
245
|
+
|
246
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
247
|
+
.addr = (__u64)(unsigned long)0,
|
248
|
+
.len = AREA_SZ,
|
249
|
+
.flags = 0,
|
250
|
+
};
|
251
|
+
|
252
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
253
|
+
.if_idx = ifidx,
|
254
|
+
.if_rxq = rxq,
|
255
|
+
.rq_entries = RQ_ENTRIES,
|
256
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
257
|
+
};
|
258
|
+
|
259
|
+
ret = try_register_ifq(®);
|
260
|
+
return ret ? T_EXIT_PASS : T_EXIT_FAIL;
|
261
|
+
}
|
262
|
+
|
263
|
+
static int test_misaligned_area(void *area)
|
264
|
+
{
|
265
|
+
int ret;
|
266
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
267
|
+
.addr = (__u64)(unsigned long)(area + 1),
|
268
|
+
.len = AREA_SZ,
|
269
|
+
.flags = 0,
|
270
|
+
};
|
271
|
+
|
272
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
273
|
+
.if_idx = ifidx,
|
274
|
+
.if_rxq = rxq,
|
275
|
+
.rq_entries = RQ_ENTRIES,
|
276
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
277
|
+
};
|
278
|
+
|
279
|
+
if (!try_register_ifq(®))
|
280
|
+
return T_EXIT_FAIL;
|
281
|
+
|
282
|
+
area_reg.addr = (__u64)(unsigned long)area;
|
283
|
+
area_reg.len = AREA_SZ - 1;
|
284
|
+
ret = try_register_ifq(®);
|
285
|
+
return ret ? T_EXIT_PASS : T_EXIT_FAIL;
|
286
|
+
}
|
287
|
+
|
288
|
+
static int test_larger_than_alloc_area(void *area)
|
289
|
+
{
|
290
|
+
int ret;
|
291
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
292
|
+
.addr = (__u64)(unsigned long)area,
|
293
|
+
.len = AREA_SZ + 4096,
|
294
|
+
.flags = 0,
|
295
|
+
};
|
296
|
+
|
297
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
298
|
+
.if_idx = ifidx,
|
299
|
+
.if_rxq = rxq,
|
300
|
+
.rq_entries = RQ_ENTRIES,
|
301
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
302
|
+
};
|
303
|
+
|
304
|
+
ret = try_register_ifq(®);
|
305
|
+
return ret ? T_EXIT_PASS : T_EXIT_FAIL;
|
306
|
+
}
|
307
|
+
|
308
|
+
static int test_area_access(void)
|
309
|
+
{
|
310
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
311
|
+
.len = AREA_SZ,
|
312
|
+
.flags = 0,
|
313
|
+
};
|
314
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
315
|
+
.if_idx = ifidx,
|
316
|
+
.if_rxq = rxq,
|
317
|
+
.rq_entries = RQ_ENTRIES,
|
318
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
319
|
+
};
|
320
|
+
int i, ret;
|
321
|
+
void *area;
|
322
|
+
|
323
|
+
for (i = 0; i < 2; i++) {
|
324
|
+
int ro = i & 1;
|
325
|
+
int prot = ro ? PROT_READ : PROT_WRITE;
|
326
|
+
|
327
|
+
area = mmap(NULL, AREA_SZ, prot,
|
328
|
+
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
329
|
+
if (area == MAP_FAILED) {
|
330
|
+
perror("mmap");
|
331
|
+
return T_EXIT_FAIL;
|
332
|
+
}
|
333
|
+
|
334
|
+
area_reg.addr = (__u64)(unsigned long)area;
|
335
|
+
|
336
|
+
ret = try_register_ifq(®);
|
337
|
+
if (ret != -EFAULT) {
|
338
|
+
fprintf(stderr, "registered unaccessible memory\n");
|
339
|
+
return T_EXIT_FAIL;
|
340
|
+
}
|
341
|
+
|
342
|
+
munmap(area, AREA_SZ);
|
343
|
+
}
|
344
|
+
|
345
|
+
return T_EXIT_PASS;
|
346
|
+
}
|
347
|
+
|
348
|
+
static int create_ring_with_ifq(struct io_uring *ring, void *area, __u32 *id)
|
349
|
+
{
|
350
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
351
|
+
.addr = (__u64)(unsigned long)area,
|
352
|
+
.len = AREA_SZ,
|
353
|
+
.flags = 0,
|
354
|
+
};
|
355
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
356
|
+
.if_idx = ifidx,
|
357
|
+
.if_rxq = rxq,
|
358
|
+
.rq_entries = RQ_ENTRIES,
|
359
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
360
|
+
};
|
361
|
+
int ret;
|
362
|
+
|
363
|
+
ret = t_create_ring(128, ring, RING_FLAGS);
|
364
|
+
if (ret != T_SETUP_OK) {
|
365
|
+
fprintf(stderr, "ring create failed: %d\n", ret);
|
366
|
+
return T_EXIT_FAIL;
|
367
|
+
}
|
368
|
+
|
369
|
+
ret = io_uring_register_ifq(ring, ®);
|
370
|
+
if (ret) {
|
371
|
+
io_uring_queue_exit(ring);
|
372
|
+
fprintf(stderr, "ifq register failed %d\n", ret);
|
373
|
+
return T_EXIT_FAIL;
|
374
|
+
}
|
375
|
+
*id = reg.zcrx_id;
|
376
|
+
return 0;
|
377
|
+
}
|
378
|
+
|
379
|
+
static void test_io_uring_prep_zcrx(struct io_uring_sqe *sqe, int fd, int ifq)
|
380
|
+
{
|
381
|
+
io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, fd, NULL, 0, 0);
|
382
|
+
sqe->zcrx_ifq_idx = ifq;
|
383
|
+
sqe->ioprio |= IORING_RECV_MULTISHOT;
|
384
|
+
}
|
385
|
+
|
386
|
+
static struct io_uring_cqe *submit_and_wait_one(struct io_uring *ring)
|
387
|
+
{
|
388
|
+
struct io_uring_cqe *cqe;
|
389
|
+
int ret;
|
390
|
+
|
391
|
+
ret = io_uring_submit(ring);
|
392
|
+
if (ret != 1) {
|
393
|
+
fprintf(stderr, "sqe submit failed: %d\n", ret);
|
394
|
+
return NULL;
|
395
|
+
}
|
396
|
+
|
397
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
398
|
+
if (ret < 0) {
|
399
|
+
fprintf(stderr, "wait completion %d\n", ret);
|
400
|
+
return NULL;
|
401
|
+
}
|
402
|
+
|
403
|
+
return cqe;
|
404
|
+
}
|
405
|
+
|
406
|
+
static int test_invalid_zcrx_request(void *area)
|
407
|
+
{
|
408
|
+
struct io_uring_cqe *cqe;
|
409
|
+
struct io_uring_sqe *sqe;
|
410
|
+
struct io_uring ring;
|
411
|
+
__u32 zcrx_id;
|
412
|
+
int ret, fds[2];
|
413
|
+
|
414
|
+
ret = create_ring_with_ifq(&ring, area, &zcrx_id);
|
415
|
+
if (ret != T_SETUP_OK) {
|
416
|
+
fprintf(stderr, "ifq-ring create failed: %d\n", ret);
|
417
|
+
return T_EXIT_FAIL;
|
418
|
+
}
|
419
|
+
|
420
|
+
ret = t_create_socket_pair(fds, true);
|
421
|
+
if (ret) {
|
422
|
+
fprintf(stderr, "t_create_socket_pair failed: %d\n", ret);
|
423
|
+
return ret;
|
424
|
+
}
|
425
|
+
|
426
|
+
/* invalid file */
|
427
|
+
sqe = io_uring_get_sqe(&ring);
|
428
|
+
test_io_uring_prep_zcrx(sqe, ring.ring_fd, zcrx_id);
|
429
|
+
|
430
|
+
cqe = submit_and_wait_one(&ring);
|
431
|
+
if (!cqe) {
|
432
|
+
fprintf(stderr, "submit_and_wait_one failed\n");
|
433
|
+
return T_EXIT_FAIL;
|
434
|
+
}
|
435
|
+
if (cqe->flags & IORING_CQE_F_MORE) {
|
436
|
+
fprintf(stderr, "unexpected F_MORE for invalid fd\n");
|
437
|
+
return T_EXIT_FAIL;
|
438
|
+
}
|
439
|
+
if (cqe->res != -ENOTSOCK) {
|
440
|
+
fprintf(stderr, "zcrx for non-socket file\n");
|
441
|
+
return T_EXIT_FAIL;
|
442
|
+
}
|
443
|
+
io_uring_cqe_seen(&ring, cqe);
|
444
|
+
|
445
|
+
/* invalid ifq idx */
|
446
|
+
sqe = io_uring_get_sqe(&ring);
|
447
|
+
test_io_uring_prep_zcrx(sqe, fds[0], zcrx_id + 1);
|
448
|
+
|
449
|
+
cqe = submit_and_wait_one(&ring);
|
450
|
+
if (!cqe) {
|
451
|
+
fprintf(stderr, "submit_and_wait_one failed\n");
|
452
|
+
return T_EXIT_FAIL;
|
453
|
+
}
|
454
|
+
if (cqe->flags & IORING_CQE_F_MORE) {
|
455
|
+
fprintf(stderr, "unexpected F_MORE for invalid fd\n");
|
456
|
+
return T_EXIT_FAIL;
|
457
|
+
}
|
458
|
+
if (cqe->res != -EINVAL) {
|
459
|
+
fprintf(stderr, "zcrx recv with non-existent zcrx ifq\n");
|
460
|
+
return T_EXIT_FAIL;
|
461
|
+
}
|
462
|
+
io_uring_cqe_seen(&ring, cqe);
|
463
|
+
|
464
|
+
close(fds[0]);
|
465
|
+
close(fds[1]);
|
466
|
+
io_uring_queue_exit(&ring);
|
467
|
+
return 0;
|
468
|
+
}
|
469
|
+
|
470
|
+
struct recv_data {
|
471
|
+
pthread_barrier_t connect;
|
472
|
+
pthread_barrier_t startup;
|
473
|
+
pthread_barrier_t barrier;
|
474
|
+
pthread_barrier_t finish;
|
475
|
+
|
476
|
+
int accept_fd;
|
477
|
+
char buf[MSG_SIZE];
|
478
|
+
void *area;
|
479
|
+
void *ring_ptr;
|
480
|
+
unsigned int ring_sz;
|
481
|
+
struct io_uring_zcrx_rq rq_ring;
|
482
|
+
};
|
483
|
+
|
484
|
+
static int recv_prep(struct io_uring *ring, struct recv_data *rd, int *sock,
|
485
|
+
__u32 zcrx_id)
|
486
|
+
{
|
487
|
+
struct sockaddr_in saddr;
|
488
|
+
struct io_uring_sqe *sqe;
|
489
|
+
int sockfd, ret, val, use_fd;
|
490
|
+
socklen_t socklen;
|
491
|
+
|
492
|
+
memset(&saddr, 0, sizeof(saddr));
|
493
|
+
saddr.sin_family = AF_INET;
|
494
|
+
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
495
|
+
saddr.sin_port = htons(PORT);
|
496
|
+
|
497
|
+
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
498
|
+
if (sockfd < 0) {
|
499
|
+
perror("socket");
|
500
|
+
return 1;
|
501
|
+
}
|
502
|
+
|
503
|
+
val = 1;
|
504
|
+
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
|
505
|
+
|
506
|
+
ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
|
507
|
+
if (ret < 0) {
|
508
|
+
perror("bind");
|
509
|
+
goto err;
|
510
|
+
}
|
511
|
+
|
512
|
+
ret = listen(sockfd, 1);
|
513
|
+
if (ret < 0) {
|
514
|
+
perror("listen");
|
515
|
+
goto err;
|
516
|
+
}
|
517
|
+
|
518
|
+
pthread_barrier_wait(&rd->connect);
|
519
|
+
|
520
|
+
socklen = sizeof(saddr);
|
521
|
+
use_fd = accept(sockfd, (struct sockaddr *)&saddr, &socklen);
|
522
|
+
if (use_fd < 0) {
|
523
|
+
perror("accept");
|
524
|
+
goto err;
|
525
|
+
}
|
526
|
+
|
527
|
+
rd->accept_fd = use_fd;
|
528
|
+
pthread_barrier_wait(&rd->startup);
|
529
|
+
pthread_barrier_wait(&rd->barrier);
|
530
|
+
|
531
|
+
sqe = io_uring_get_sqe(ring);
|
532
|
+
io_uring_prep_rw(IORING_OP_RECV_ZC, sqe, use_fd, NULL, 0, 0);
|
533
|
+
sqe->zcrx_ifq_idx = zcrx_id;
|
534
|
+
sqe->ioprio |= IORING_RECV_MULTISHOT;
|
535
|
+
sqe->user_data = 2;
|
536
|
+
|
537
|
+
ret = io_uring_submit(ring);
|
538
|
+
if (ret <= 0) {
|
539
|
+
fprintf(stderr, "submit failed: %d\n", ret);
|
540
|
+
goto err;
|
541
|
+
}
|
542
|
+
|
543
|
+
*sock = sockfd;
|
544
|
+
return 0;
|
545
|
+
err:
|
546
|
+
close(sockfd);
|
547
|
+
return 1;
|
548
|
+
}
|
549
|
+
|
550
|
+
static struct io_uring_zcrx_rqe* get_refill_entry(struct io_uring_zcrx_rq *rq_ring)
|
551
|
+
{
|
552
|
+
unsigned mask = rq_ring->ring_entries - 1;
|
553
|
+
struct io_uring_zcrx_rqe* rqe;
|
554
|
+
|
555
|
+
rqe = &rq_ring->rqes[rq_ring->rq_tail & mask];
|
556
|
+
rq_ring->rq_tail++;
|
557
|
+
return rqe;
|
558
|
+
}
|
559
|
+
|
560
|
+
static void refill_garbage(struct recv_data *rd, uint64_t area_token)
|
561
|
+
{
|
562
|
+
struct io_uring_zcrx_rq *rq_ring = &rd->rq_ring;
|
563
|
+
struct io_uring_zcrx_rqe* rqe;
|
564
|
+
int i = 0;
|
565
|
+
|
566
|
+
/* invalid area */
|
567
|
+
rqe = get_refill_entry(rq_ring);
|
568
|
+
rqe->off = (area_token + 1) << IORING_ZCRX_AREA_SHIFT;
|
569
|
+
i++;
|
570
|
+
|
571
|
+
/* invalid area offset */
|
572
|
+
rqe = get_refill_entry(rq_ring);
|
573
|
+
rqe->off = AREA_SZ | (area_token << IORING_ZCRX_AREA_SHIFT);
|
574
|
+
rqe->off += AREA_SZ;
|
575
|
+
i++;
|
576
|
+
|
577
|
+
for (; i < rq_ring->ring_entries; i++) {
|
578
|
+
rqe = get_refill_entry(rq_ring);
|
579
|
+
rqe->off = ((uint64_t)1 << IORING_ZCRX_AREA_SHIFT) - 1;
|
580
|
+
}
|
581
|
+
|
582
|
+
io_uring_smp_store_release(rq_ring->ktail, rq_ring->rq_tail);
|
583
|
+
}
|
584
|
+
|
585
|
+
static int do_recv(struct io_uring *ring, struct recv_data *rd,
|
586
|
+
uint64_t refill_area_token)
|
587
|
+
{
|
588
|
+
struct io_uring_cqe *cqe;
|
589
|
+
struct io_uring_zcrx_cqe *zcqe;
|
590
|
+
int i, ret;
|
591
|
+
|
592
|
+
refill_garbage(rd, refill_area_token);
|
593
|
+
|
594
|
+
for (i = 0; i < LOOP_COUNT - 1; i++) {
|
595
|
+
uint64_t off, mask = (1ULL << IORING_ZCRX_AREA_SHIFT) - 1;
|
596
|
+
void *addr;
|
597
|
+
|
598
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
599
|
+
if (ret) {
|
600
|
+
fprintf(stdout, "wait_cqe: %d\n", ret);
|
601
|
+
return 1;
|
602
|
+
}
|
603
|
+
if (cqe->res == -EINVAL) {
|
604
|
+
fprintf(stdout, "recv not supported, skipping\n");
|
605
|
+
goto out;
|
606
|
+
}
|
607
|
+
if (cqe->res < 0) {
|
608
|
+
fprintf(stderr, "failed recv cqe: %d\n", cqe->res);
|
609
|
+
goto err;
|
610
|
+
}
|
611
|
+
if (cqe->res - 1 != strlen(str)) {
|
612
|
+
fprintf(stderr, "got wrong length: %d/%d\n", cqe->res,
|
613
|
+
(int) strlen(str) + 1);
|
614
|
+
goto err;
|
615
|
+
}
|
616
|
+
|
617
|
+
zcqe = (struct io_uring_zcrx_cqe *)(cqe + 1);
|
618
|
+
off = zcqe->off & mask;
|
619
|
+
addr = (char *) rd->area + off;
|
620
|
+
ret = strncmp(str, addr, sizeof(str));
|
621
|
+
if (ret != 0) {
|
622
|
+
fprintf(stderr, "recv incorrect payload: %s\n", (const char *)addr);
|
623
|
+
goto err;
|
624
|
+
}
|
625
|
+
|
626
|
+
io_uring_cqe_seen(ring, cqe);
|
627
|
+
}
|
628
|
+
|
629
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
630
|
+
if (ret) {
|
631
|
+
fprintf(stdout, "wait_cqe: %d\n", ret);
|
632
|
+
return 1;
|
633
|
+
}
|
634
|
+
if (cqe->res != -ENOMEM) {
|
635
|
+
fprintf(stdout, "final recv cqe did not return ENOMEM\n");
|
636
|
+
goto err;
|
637
|
+
}
|
638
|
+
|
639
|
+
out:
|
640
|
+
io_uring_cqe_seen(ring, cqe);
|
641
|
+
pthread_barrier_wait(&rd->finish);
|
642
|
+
return 0;
|
643
|
+
err:
|
644
|
+
io_uring_cqe_seen(ring, cqe);
|
645
|
+
pthread_barrier_wait(&rd->finish);
|
646
|
+
return 1;
|
647
|
+
}
|
648
|
+
|
649
|
+
static void *recv_fn(void *data)
|
650
|
+
{
|
651
|
+
struct recv_data *rd = data;
|
652
|
+
struct io_uring_params p = { };
|
653
|
+
struct io_uring ring;
|
654
|
+
int ret, sock;
|
655
|
+
struct io_uring_zcrx_area_reg area_reg = {
|
656
|
+
.addr = (__u64)(unsigned long)rd->area,
|
657
|
+
.len = AREA_SZ,
|
658
|
+
.flags = 0,
|
659
|
+
};
|
660
|
+
struct io_uring_zcrx_ifq_reg reg = {
|
661
|
+
.if_idx = ifidx,
|
662
|
+
.if_rxq = rxq,
|
663
|
+
.rq_entries = RQ_ENTRIES,
|
664
|
+
.area_ptr = (__u64)(unsigned long)&area_reg,
|
665
|
+
};
|
666
|
+
|
667
|
+
p.flags = RING_FLAGS;
|
668
|
+
ret = t_create_ring_params(8, &ring, &p);
|
669
|
+
if (ret == T_SETUP_SKIP) {
|
670
|
+
ret = 0;
|
671
|
+
goto err;
|
672
|
+
} else if (ret < 0) {
|
673
|
+
goto err;
|
674
|
+
}
|
675
|
+
|
676
|
+
ret = io_uring_register_ifq(&ring, ®);
|
677
|
+
if (ret != 0) {
|
678
|
+
fprintf(stderr, "register_ifq failed: %d\n", ret);
|
679
|
+
goto err_ring_exit;
|
680
|
+
}
|
681
|
+
|
682
|
+
/*
|
683
|
+
rd->ring_ptr = mmap(
|
684
|
+
0,
|
685
|
+
reg.offsets.mmap_sz,
|
686
|
+
PROT_READ | PROT_WRITE,
|
687
|
+
MAP_SHARED | MAP_POPULATE,
|
688
|
+
ring.enter_ring_fd,
|
689
|
+
IORING_OFF_RQ_RING
|
690
|
+
);
|
691
|
+
|
692
|
+
rd->ring_sz = reg.offsets.mmap_sz;
|
693
|
+
*/
|
694
|
+
rd->rq_ring.khead = (__u32*)((char*)rd->ring_ptr + reg.offsets.head);
|
695
|
+
rd->rq_ring.ktail = (__u32*)((char*)rd->ring_ptr + reg.offsets.tail);
|
696
|
+
rd->rq_ring.rqes = (struct io_uring_zcrx_rqe*)((char*)rd->ring_ptr + reg.offsets.rqes);
|
697
|
+
rd->rq_ring.rq_tail = 0;
|
698
|
+
rd->rq_ring.ring_entries = reg.rq_entries;
|
699
|
+
|
700
|
+
ret = recv_prep(&ring, rd, &sock, reg.zcrx_id);
|
701
|
+
if (ret) {
|
702
|
+
fprintf(stderr, "recv_prep failed: %d\n", ret);
|
703
|
+
goto err;
|
704
|
+
}
|
705
|
+
ret = do_recv(&ring, rd, area_reg.rq_area_token);
|
706
|
+
|
707
|
+
close(sock);
|
708
|
+
close(rd->accept_fd);
|
709
|
+
err_ring_exit:
|
710
|
+
io_uring_queue_exit(&ring);
|
711
|
+
err:
|
712
|
+
return (void *)(intptr_t)ret;
|
713
|
+
}
|
714
|
+
|
715
|
+
static int do_send(struct recv_data *rd)
|
716
|
+
{
|
717
|
+
struct sockaddr_in saddr;
|
718
|
+
struct iovec iov = {
|
719
|
+
.iov_base = str,
|
720
|
+
.iov_len = sizeof(str),
|
721
|
+
};
|
722
|
+
struct io_uring ring;
|
723
|
+
struct io_uring_cqe *cqe;
|
724
|
+
struct io_uring_sqe *sqe;
|
725
|
+
int i, sockfd, ret;
|
726
|
+
|
727
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
728
|
+
if (ret) {
|
729
|
+
fprintf(stderr, "queue init failed: %d\n", ret);
|
730
|
+
return 1;
|
731
|
+
}
|
732
|
+
|
733
|
+
memset(&saddr, 0, sizeof(saddr));
|
734
|
+
saddr.sin_family = AF_INET;
|
735
|
+
saddr.sin_port = htons(PORT);
|
736
|
+
inet_pton(AF_INET, HOST, &saddr.sin_addr);
|
737
|
+
|
738
|
+
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
739
|
+
if (sockfd < 0) {
|
740
|
+
perror("socket");
|
741
|
+
goto err2;
|
742
|
+
}
|
743
|
+
|
744
|
+
pthread_barrier_wait(&rd->connect);
|
745
|
+
|
746
|
+
ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
|
747
|
+
if (ret < 0) {
|
748
|
+
perror("connect");
|
749
|
+
goto err;
|
750
|
+
}
|
751
|
+
|
752
|
+
pthread_barrier_wait(&rd->startup);
|
753
|
+
|
754
|
+
for (i = 0; i < LOOP_COUNT; i++) {
|
755
|
+
sqe = io_uring_get_sqe(&ring);
|
756
|
+
io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0);
|
757
|
+
sqe->user_data = 1;
|
758
|
+
}
|
759
|
+
|
760
|
+
ret = io_uring_submit(&ring);
|
761
|
+
if (ret <= 0) {
|
762
|
+
fprintf(stderr, "submit failed: %d\n", ret);
|
763
|
+
goto err;
|
764
|
+
}
|
765
|
+
|
766
|
+
pthread_barrier_wait(&rd->barrier);
|
767
|
+
|
768
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
769
|
+
if (cqe->res == -EINVAL) {
|
770
|
+
fprintf(stdout, "send not supported, skipping\n");
|
771
|
+
goto err;
|
772
|
+
}
|
773
|
+
if (cqe->res != iov.iov_len) {
|
774
|
+
fprintf(stderr, "failed cqe: %d\n", cqe->res);
|
775
|
+
goto err;
|
776
|
+
}
|
777
|
+
|
778
|
+
pthread_barrier_wait(&rd->finish);
|
779
|
+
|
780
|
+
close(sockfd);
|
781
|
+
io_uring_queue_exit(&ring);
|
782
|
+
return 0;
|
783
|
+
|
784
|
+
err:
|
785
|
+
close(sockfd);
|
786
|
+
err2:
|
787
|
+
io_uring_queue_exit(&ring);
|
788
|
+
pthread_barrier_wait(&rd->finish);
|
789
|
+
return 1;
|
790
|
+
}
|
791
|
+
|
792
|
+
static int test_recv(void *area)
|
793
|
+
{
|
794
|
+
pthread_t recv_thread;
|
795
|
+
struct recv_data rd;
|
796
|
+
int ret;
|
797
|
+
void *retval;
|
798
|
+
|
799
|
+
memset(&rd, 0, sizeof(rd));
|
800
|
+
pthread_barrier_init(&rd.connect, NULL, 2);
|
801
|
+
pthread_barrier_init(&rd.startup, NULL, 2);
|
802
|
+
pthread_barrier_init(&rd.barrier, NULL, 2);
|
803
|
+
pthread_barrier_init(&rd.finish, NULL, 2);
|
804
|
+
rd.area = area;
|
805
|
+
|
806
|
+
ret = pthread_create(&recv_thread, NULL, recv_fn, &rd);
|
807
|
+
if (ret) {
|
808
|
+
fprintf(stderr, "Thread create failed: %d\n", ret);
|
809
|
+
return 1;
|
810
|
+
}
|
811
|
+
|
812
|
+
do_send(&rd);
|
813
|
+
pthread_join(recv_thread, &retval);
|
814
|
+
return (intptr_t)retval;
|
815
|
+
}
|
816
|
+
|
817
|
+
int main(int argc, char *argv[])
|
818
|
+
{
|
819
|
+
char *dev, *rxq_str, *rxq_end;
|
820
|
+
void *area_outer, *area;
|
821
|
+
int ret;
|
822
|
+
|
823
|
+
if (argc > 1)
|
824
|
+
return T_EXIT_SKIP;
|
825
|
+
|
826
|
+
page_size = sysconf(_SC_PAGESIZE);
|
827
|
+
if (page_size < 0) {
|
828
|
+
perror("sysconf(_SC_PAGESIZE)");
|
829
|
+
return T_EXIT_FAIL;
|
830
|
+
}
|
831
|
+
|
832
|
+
area_outer = mmap(NULL, AREA_SZ + 8192, PROT_NONE,
|
833
|
+
MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
|
834
|
+
if (area_outer == MAP_FAILED) {
|
835
|
+
perror("mmap");
|
836
|
+
return T_EXIT_FAIL;
|
837
|
+
}
|
838
|
+
|
839
|
+
area = mmap(area_outer, AREA_SZ, PROT_READ | PROT_WRITE,
|
840
|
+
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
841
|
+
if (area == MAP_FAILED) {
|
842
|
+
perror("mmap");
|
843
|
+
return T_EXIT_FAIL;
|
844
|
+
}
|
845
|
+
|
846
|
+
dev = getenv(DEV_ENV_VAR);
|
847
|
+
if (!dev)
|
848
|
+
return T_EXIT_SKIP;
|
849
|
+
|
850
|
+
ifidx = if_nametoindex(dev);
|
851
|
+
if (!ifidx)
|
852
|
+
return T_EXIT_SKIP;
|
853
|
+
|
854
|
+
rxq_str = getenv(RXQ_ENV_VAR);
|
855
|
+
if (!rxq_str)
|
856
|
+
return T_EXIT_SKIP;
|
857
|
+
|
858
|
+
rxq = strtol(rxq_str, &rxq_end, 10);
|
859
|
+
if (rxq_end == rxq_str || *rxq_end != '\0')
|
860
|
+
return T_EXIT_SKIP;
|
861
|
+
|
862
|
+
ret = probe_zcrx(area);
|
863
|
+
if (ret != T_EXIT_PASS)
|
864
|
+
return ret;
|
865
|
+
|
866
|
+
ret = test_rq_setup(area);
|
867
|
+
if (ret) {
|
868
|
+
fprintf(stderr, "test_invalid_reg_struct failed\n");
|
869
|
+
return ret;
|
870
|
+
}
|
871
|
+
|
872
|
+
ret = test_null_area_reg_struct();
|
873
|
+
if (ret) {
|
874
|
+
fprintf(stderr, "test_null_area_reg_struct failed\n");
|
875
|
+
return ret;
|
876
|
+
}
|
877
|
+
|
878
|
+
ret = test_null_area();
|
879
|
+
if (ret) {
|
880
|
+
fprintf(stderr, "test_null_area failed\n");
|
881
|
+
return ret;
|
882
|
+
}
|
883
|
+
|
884
|
+
ret = test_misaligned_area(area);
|
885
|
+
if (ret) {
|
886
|
+
fprintf(stderr, "test_misaligned_area failed\n");
|
887
|
+
return ret;
|
888
|
+
}
|
889
|
+
|
890
|
+
ret = test_larger_than_alloc_area(area);
|
891
|
+
if (ret) {
|
892
|
+
fprintf(stderr, "test_larger_than_alloc_area failed\n");
|
893
|
+
return ret;
|
894
|
+
}
|
895
|
+
|
896
|
+
ret = test_area_access();
|
897
|
+
if (ret) {
|
898
|
+
fprintf(stderr, "test_area_access failed\n");
|
899
|
+
return ret;
|
900
|
+
}
|
901
|
+
|
902
|
+
ret = test_invalid_if(area);
|
903
|
+
if (ret) {
|
904
|
+
fprintf(stderr, "test_invalid_if failed\n");
|
905
|
+
return ret;
|
906
|
+
}
|
907
|
+
|
908
|
+
ret = test_invalid_ifq_collision(area);
|
909
|
+
if (ret) {
|
910
|
+
fprintf(stderr, "test_invalid_ifq_collision failed\n");
|
911
|
+
return ret;
|
912
|
+
}
|
913
|
+
|
914
|
+
ret = test_invalid_zcrx_request(area);
|
915
|
+
if (ret) {
|
916
|
+
fprintf(stderr, "test_invalid_ifq_collision failed\n");
|
917
|
+
return ret;
|
918
|
+
}
|
919
|
+
|
920
|
+
ret = test_recv(area);
|
921
|
+
if (ret) {
|
922
|
+
fprintf(stderr, "test_recv failed\n");
|
923
|
+
return ret;
|
924
|
+
}
|
925
|
+
|
926
|
+
munmap(area, AREA_SZ);
|
927
|
+
return T_EXIT_PASS;
|
928
|
+
}
|