1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2019 Intel Corporation.
3465f4c12SZiye Yang * All rights reserved.
4465f4c12SZiye Yang */
5465f4c12SZiye Yang
6465f4c12SZiye Yang #include "spdk/stdinc.h"
7465f4c12SZiye Yang #include "spdk/util.h"
8465f4c12SZiye Yang
9465f4c12SZiye Yang #include "spdk_internal/mock.h"
10465f4c12SZiye Yang
11ae431e31SKonrad Sztyber #include "spdk_internal/cunit.h"
12465f4c12SZiye Yang
135379aa95SBen Walker #include "common/lib/test_env.c"
14465f4c12SZiye Yang #include "sock/uring/uring.c"
15465f4c12SZiye Yang
165379aa95SBen Walker DEFINE_STUB(spdk_sock_map_insert, int, (struct spdk_sock_map *map, int placement_id,
174e347038SBen Walker struct spdk_sock_group_impl *group), 0);
185379aa95SBen Walker DEFINE_STUB_V(spdk_sock_map_release, (struct spdk_sock_map *map, int placement_id));
195379aa95SBen Walker DEFINE_STUB(spdk_sock_map_lookup, int, (struct spdk_sock_map *map, int placement_id,
206301f891STomasz Zawadzki struct spdk_sock_group_impl **group, struct spdk_sock_group_impl *hint), 0);
212f9271b8SBen Walker DEFINE_STUB(spdk_sock_map_find_free, int, (struct spdk_sock_map *map), -1);
225379aa95SBen Walker DEFINE_STUB_V(spdk_sock_map_cleanup, (struct spdk_sock_map *map));
235379aa95SBen Walker
24*7521dc6fSKrzysztof Karas DEFINE_STUB_V(spdk_net_impl_register, (struct spdk_net_impl *impl));
25*7521dc6fSKrzysztof Karas DEFINE_STUB(spdk_sock_set_default_impl, int, (const char *impl_name), 0);
26465f4c12SZiye Yang DEFINE_STUB(spdk_sock_close, int, (struct spdk_sock **s), 0);
27465f4c12SZiye Yang DEFINE_STUB(io_uring_submit, int, (struct io_uring *ring), 0);
28465f4c12SZiye Yang DEFINE_STUB(io_uring_queue_init, int, (unsigned entries, struct io_uring *ring, unsigned flags), 0);
29465f4c12SZiye Yang DEFINE_STUB_V(io_uring_queue_exit, (struct io_uring *ring));
30257bd5f6SBen Walker DEFINE_STUB(spdk_sock_group_provide_buf, int, (struct spdk_sock_group *group, void *buf,
31257bd5f6SBen Walker size_t len, void *ctx), 0);
32257bd5f6SBen Walker DEFINE_STUB(spdk_sock_group_get_buf, size_t, (struct spdk_sock_group *group, void **buf,
33257bd5f6SBen Walker void **ctx), 0);
34465f4c12SZiye Yang
35465f4c12SZiye Yang static void
_req_cb(void * cb_arg,int len)36465f4c12SZiye Yang _req_cb(void *cb_arg, int len)
37465f4c12SZiye Yang {
38465f4c12SZiye Yang *(bool *)cb_arg = true;
39465f4c12SZiye Yang CU_ASSERT(len == 0);
40465f4c12SZiye Yang }
41465f4c12SZiye Yang
42465f4c12SZiye Yang static void
flush_client(void)43465f4c12SZiye Yang flush_client(void)
44465f4c12SZiye Yang {
45465f4c12SZiye Yang struct spdk_uring_sock_group_impl group = {};
46465f4c12SZiye Yang struct spdk_uring_sock usock = {};
47465f4c12SZiye Yang struct spdk_sock *sock = &usock.base;
48465f4c12SZiye Yang struct spdk_sock_request *req1, *req2;
49465f4c12SZiye Yang bool cb_arg1, cb_arg2;
50465f4c12SZiye Yang int rc;
51465f4c12SZiye Yang
52465f4c12SZiye Yang /* Set up data structures */
53465f4c12SZiye Yang TAILQ_INIT(&sock->queued_reqs);
54465f4c12SZiye Yang TAILQ_INIT(&sock->pending_reqs);
55465f4c12SZiye Yang sock->group_impl = &group.base;
56465f4c12SZiye Yang
57465f4c12SZiye Yang req1 = calloc(1, sizeof(struct spdk_sock_request) + 3 * sizeof(struct iovec));
58465f4c12SZiye Yang SPDK_CU_ASSERT_FATAL(req1 != NULL);
59465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = (void *)100;
60465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 64;
61465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_base = (void *)200;
62465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_len = 64;
63465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 2)->iov_base = (void *)300;
64465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 2)->iov_len = 64;
65465f4c12SZiye Yang req1->iovcnt = 3;
66465f4c12SZiye Yang req1->cb_fn = _req_cb;
67465f4c12SZiye Yang req1->cb_arg = &cb_arg1;
68465f4c12SZiye Yang
69465f4c12SZiye Yang req2 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
70465f4c12SZiye Yang SPDK_CU_ASSERT_FATAL(req2 != NULL);
71465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = (void *)100;
72465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 32;
73465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_base = (void *)200;
74465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_len = 32;
75465f4c12SZiye Yang req2->iovcnt = 2;
76465f4c12SZiye Yang req2->cb_fn = _req_cb;
77465f4c12SZiye Yang req2->cb_arg = &cb_arg2;
78465f4c12SZiye Yang
79465f4c12SZiye Yang /* Simple test - a request with a 3 element iovec
80465f4c12SZiye Yang * that gets submitted in a single sendmsg. */
81465f4c12SZiye Yang spdk_sock_request_queue(sock, req1);
82465f4c12SZiye Yang MOCK_SET(sendmsg, 192);
83465f4c12SZiye Yang cb_arg1 = false;
845433004eSBen Walker rc = uring_sock_flush(sock);
855433004eSBen Walker CU_ASSERT(rc == 192);
86465f4c12SZiye Yang CU_ASSERT(cb_arg1 == true);
87465f4c12SZiye Yang CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
88465f4c12SZiye Yang
89465f4c12SZiye Yang /* Two requests, where both can fully send. */
90465f4c12SZiye Yang spdk_sock_request_queue(sock, req1);
91465f4c12SZiye Yang spdk_sock_request_queue(sock, req2);
92465f4c12SZiye Yang MOCK_SET(sendmsg, 256);
93465f4c12SZiye Yang cb_arg1 = false;
94465f4c12SZiye Yang cb_arg2 = false;
955433004eSBen Walker rc = uring_sock_flush(sock);
965433004eSBen Walker CU_ASSERT(rc == 256);
97465f4c12SZiye Yang CU_ASSERT(cb_arg1 == true);
98465f4c12SZiye Yang CU_ASSERT(cb_arg2 == true);
99465f4c12SZiye Yang CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
100465f4c12SZiye Yang
101465f4c12SZiye Yang /* Two requests. Only first one can send */
102465f4c12SZiye Yang spdk_sock_request_queue(sock, req1);
103465f4c12SZiye Yang spdk_sock_request_queue(sock, req2);
104465f4c12SZiye Yang MOCK_SET(sendmsg, 192);
105465f4c12SZiye Yang cb_arg1 = false;
106465f4c12SZiye Yang cb_arg2 = false;
1075433004eSBen Walker rc = uring_sock_flush(sock);
1085433004eSBen Walker CU_ASSERT(rc == 192);
109465f4c12SZiye Yang CU_ASSERT(cb_arg1 == true);
110465f4c12SZiye Yang CU_ASSERT(cb_arg2 == false);
111465f4c12SZiye Yang CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req2);
112465f4c12SZiye Yang TAILQ_REMOVE(&sock->queued_reqs, req2, internal.link);
113465f4c12SZiye Yang CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
114465f4c12SZiye Yang
115465f4c12SZiye Yang /* One request. Partial send. */
116465f4c12SZiye Yang spdk_sock_request_queue(sock, req1);
117465f4c12SZiye Yang MOCK_SET(sendmsg, 10);
118465f4c12SZiye Yang cb_arg1 = false;
1195433004eSBen Walker rc = uring_sock_flush(sock);
1205433004eSBen Walker CU_ASSERT(rc == 10);
121465f4c12SZiye Yang CU_ASSERT(cb_arg1 == false);
122465f4c12SZiye Yang CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
123465f4c12SZiye Yang
124465f4c12SZiye Yang /* Do a second flush that partial sends again. */
125465f4c12SZiye Yang MOCK_SET(sendmsg, 52);
126465f4c12SZiye Yang cb_arg1 = false;
1275433004eSBen Walker rc = uring_sock_flush(sock);
1285433004eSBen Walker CU_ASSERT(rc == 52);
129465f4c12SZiye Yang CU_ASSERT(cb_arg1 == false);
130465f4c12SZiye Yang CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
131465f4c12SZiye Yang
132465f4c12SZiye Yang /* Flush the rest of the data */
133465f4c12SZiye Yang MOCK_SET(sendmsg, 130);
134465f4c12SZiye Yang cb_arg1 = false;
1355433004eSBen Walker rc = uring_sock_flush(sock);
1365433004eSBen Walker CU_ASSERT(rc == 130);
137465f4c12SZiye Yang CU_ASSERT(cb_arg1 == true);
138465f4c12SZiye Yang CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
139465f4c12SZiye Yang
140465f4c12SZiye Yang free(req1);
141465f4c12SZiye Yang free(req2);
142465f4c12SZiye Yang }
143465f4c12SZiye Yang
144465f4c12SZiye Yang static void
flush_server(void)145465f4c12SZiye Yang flush_server(void)
146465f4c12SZiye Yang {
147465f4c12SZiye Yang struct spdk_uring_sock_group_impl group = {};
148465f4c12SZiye Yang struct spdk_uring_sock usock = {};
149465f4c12SZiye Yang struct spdk_sock *sock = &usock.base;
150465f4c12SZiye Yang struct spdk_sock_request *req1, *req2;
151465f4c12SZiye Yang bool cb_arg1, cb_arg2;
152465f4c12SZiye Yang int rc;
153465f4c12SZiye Yang
154465f4c12SZiye Yang /* Set up data structures */
155465f4c12SZiye Yang TAILQ_INIT(&sock->queued_reqs);
156465f4c12SZiye Yang TAILQ_INIT(&sock->pending_reqs);
157465f4c12SZiye Yang sock->group_impl = &group.base;
158465f4c12SZiye Yang usock.write_task.sock = &usock;
159465f4c12SZiye Yang usock.group = &group;
160465f4c12SZiye Yang
161465f4c12SZiye Yang req1 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
162465f4c12SZiye Yang SPDK_CU_ASSERT_FATAL(req1 != NULL);
163465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = (void *)100;
164465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 64;
165465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_base = (void *)200;
166465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req1, 1)->iov_len = 64;
167465f4c12SZiye Yang req1->iovcnt = 2;
168465f4c12SZiye Yang req1->cb_fn = _req_cb;
169465f4c12SZiye Yang req1->cb_arg = &cb_arg1;
170465f4c12SZiye Yang
171465f4c12SZiye Yang req2 = calloc(1, sizeof(struct spdk_sock_request) + 2 * sizeof(struct iovec));
172465f4c12SZiye Yang SPDK_CU_ASSERT_FATAL(req2 != NULL);
173465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = (void *)100;
174465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 32;
175465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_base = (void *)200;
176465f4c12SZiye Yang SPDK_SOCK_REQUEST_IOV(req2, 1)->iov_len = 32;
177465f4c12SZiye Yang req2->iovcnt = 2;
178465f4c12SZiye Yang req2->cb_fn = _req_cb;
179465f4c12SZiye Yang req2->cb_arg = &cb_arg2;
180465f4c12SZiye Yang
181465f4c12SZiye Yang /* we should not call _sock_flush directly, since it will finally
182c9c7c281SJosh Soref * call liburing related functions */
183465f4c12SZiye Yang
184465f4c12SZiye Yang /* Simple test - a request with a 2 element iovec
185465f4c12SZiye Yang * that is fully completed. */
186465f4c12SZiye Yang spdk_sock_request_queue(sock, req1);
187465f4c12SZiye Yang cb_arg1 = false;
1889bff828fSRichael Zhuang rc = spdk_sock_prep_reqs(sock, usock.write_task.iovs, 0, NULL, NULL);
189465f4c12SZiye Yang CU_ASSERT(rc == 2);
1906453cbe7SKonrad Sztyber sock_complete_write_reqs(sock, 128, 0);
191465f4c12SZiye Yang CU_ASSERT(cb_arg1 == true);
192465f4c12SZiye Yang CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
193465f4c12SZiye Yang
194465f4c12SZiye Yang /* Two requests, where both can be fully completed. */
195465f4c12SZiye Yang spdk_sock_request_queue(sock, req1);
196465f4c12SZiye Yang spdk_sock_request_queue(sock, req2);
197465f4c12SZiye Yang cb_arg1 = false;
198465f4c12SZiye Yang cb_arg2 = false;
1999bff828fSRichael Zhuang rc = spdk_sock_prep_reqs(sock, usock.write_task.iovs, 0, NULL, NULL);
200465f4c12SZiye Yang CU_ASSERT(rc == 4);
2016453cbe7SKonrad Sztyber sock_complete_write_reqs(sock, 192, 0);
202465f4c12SZiye Yang CU_ASSERT(cb_arg1 == true);
203465f4c12SZiye Yang CU_ASSERT(cb_arg2 == true);
204465f4c12SZiye Yang CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
205465f4c12SZiye Yang
206465f4c12SZiye Yang
207465f4c12SZiye Yang /* One request that is partially sent. */
208465f4c12SZiye Yang spdk_sock_request_queue(sock, req1);
209465f4c12SZiye Yang cb_arg1 = false;
2109bff828fSRichael Zhuang rc = spdk_sock_prep_reqs(sock, usock.write_task.iovs, 0, NULL, NULL);
211465f4c12SZiye Yang CU_ASSERT(rc == 2);
2126453cbe7SKonrad Sztyber sock_complete_write_reqs(sock, 92, 0);
213465f4c12SZiye Yang CU_ASSERT(rc == 2);
214465f4c12SZiye Yang CU_ASSERT(cb_arg1 == false);
215465f4c12SZiye Yang CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
216465f4c12SZiye Yang
217465f4c12SZiye Yang /* Get the second time partial sent result. */
2186453cbe7SKonrad Sztyber sock_complete_write_reqs(sock, 10, 0);
219465f4c12SZiye Yang CU_ASSERT(cb_arg1 == false);
220465f4c12SZiye Yang CU_ASSERT(TAILQ_FIRST(&sock->queued_reqs) == req1);
221465f4c12SZiye Yang
222465f4c12SZiye Yang /* Data is finally sent. */
2236453cbe7SKonrad Sztyber sock_complete_write_reqs(sock, 26, 0);
224465f4c12SZiye Yang CU_ASSERT(cb_arg1 == true);
225465f4c12SZiye Yang CU_ASSERT(TAILQ_EMPTY(&sock->queued_reqs));
226465f4c12SZiye Yang
227465f4c12SZiye Yang free(req1);
228465f4c12SZiye Yang free(req2);
229465f4c12SZiye Yang }
230465f4c12SZiye Yang
231465f4c12SZiye Yang int
main(int argc,char ** argv)232465f4c12SZiye Yang main(int argc, char **argv)
233465f4c12SZiye Yang {
234465f4c12SZiye Yang CU_pSuite suite = NULL;
235465f4c12SZiye Yang unsigned int num_failures;
236465f4c12SZiye Yang
23778b696bcSVitaliy Mysak CU_initialize_registry();
238465f4c12SZiye Yang
239465f4c12SZiye Yang suite = CU_add_suite("uring", NULL, NULL);
240465f4c12SZiye Yang
24178b696bcSVitaliy Mysak
242dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, flush_client);
243dcf0ca15SVitaliy Mysak CU_ADD_TEST(suite, flush_server);
244465f4c12SZiye Yang
245465f4c12SZiye Yang
246ea941caeSKonrad Sztyber num_failures = spdk_ut_run_tests(argc, argv, NULL);
247465f4c12SZiye Yang
248465f4c12SZiye Yang CU_cleanup_registry();
249465f4c12SZiye Yang
250465f4c12SZiye Yang return num_failures;
251465f4c12SZiye Yang }
252