blob: 36f1251a158b8acec4ae07b6a7dfdd740ab34827 [file] [log] [blame]
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +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
Damjan Marion2cdc2bd2018-04-26 18:39:56 +020018#define _GNU_SOURCE
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020019#include <stdint.h>
20#include <net/if.h>
21#include <sys/types.h>
22#include <fcntl.h>
23#include <sys/ioctl.h>
24#include <sys/socket.h>
25#include <sys/un.h>
26#include <sys/uio.h>
27#include <sys/mman.h>
28#include <sys/prctl.h>
29#include <inttypes.h>
30#include <string.h>
31#include <stdio.h>
32#include <netdb.h>
33#include <linux/ip.h>
34#include <linux/icmp.h>
35#include <arpa/inet.h>
36#include <stdlib.h>
37#include <netinet/if_ether.h>
38#include <net/if_arp.h>
39#include <asm/byteorder.h>
40#include <byteswap.h>
41#include <string.h>
42#include <errno.h>
43#include <sys/stat.h>
44#include <sys/eventfd.h>
45#include <sys/timerfd.h>
46#include <sys/epoll.h>
47#include <signal.h>
Jakub Grajciar435f5002018-04-20 09:20:50 +020048#include <linux/memfd.h>
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020049
50/* memif protocol msg, ring and descriptor definitions */
51#include <memif.h>
52/* memif api */
53#include <libmemif.h>
54/* socket messaging functions */
55#include <socket.h>
56/* private structs and functions */
57#include <memif_private.h>
58
Jakub Grajciar568cc462018-09-05 12:11:35 +020059#define ERRLIST_LEN 40
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020060#define MAX_ERRBUF_LEN 256
61
62#if __x86_x64__
63#define MEMIF_MEMORY_BARRIER() __builtin_ia32_sfence ()
64#else
Milan Lenco0a47c992017-10-12 14:19:31 +020065#define MEMIF_MEMORY_BARRIER() __sync_synchronize ()
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020066#endif /* __x86_x64__ */
67
68libmemif_main_t libmemif_main;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020069
70static char memif_buf[MAX_ERRBUF_LEN];
71
72const char *memif_errlist[ERRLIST_LEN] = { /* MEMIF_ERR_SUCCESS */
73 "Success.",
74 /* MEMIF_ERR_SYSCALL */
75 "Unspecified syscall error (build with -DMEMIF_DBG or make debug).",
Jakub Grajciar568cc462018-09-05 12:11:35 +020076 /* MEMIF_ERR_CONNREFUSED */
77 "Connection refused",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020078 /* MEMIF_ERR_ACCES */
Paul Vinciguerra62237662020-05-29 23:03:06 -040079 "Permission to resource denied.",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020080 /* MEMIF_ERR_NO_FILE */
81 "Socket file does not exist",
82 /* MEMIF_ERR_FILE_LIMIT */
83 "System limit on total numer of open files reached.",
84 /* MEMIF_ERR_PROC_FILE_LIMIT */
85 "Per-process limit on total number of open files reached.",
86 /* MEMIF_ERR_ALREADY */
87 "Connection already requested.",
88 /* MEMIF_ERR_AGAIN */
89 "File descriptor refers to file other than socket, or operation would block.",
90 /* MEMIF_ERR_BAD_FD */
91 "Bad file descriptor.",
92 /* MEMIF_ERR_NOMEM */
93 "Out of memory.",
94 /* MEMIF_ERR_INVAL_ARG */
95 "Invalid argument.",
96 /* MEMIF_ERR_NOCONN */
Paul Vinciguerra62237662020-05-29 23:03:06 -040097 "Memif connection handle does not point to existing connection",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020098 /* MEMIF_ERR_CONN */
99 "Memif connection handle points to existing connection",
100 /* MEMIF_ERR_CB_FDUPDATE */
101 "Callback memif_control_fd_update_t returned error",
102 /* MEMIF_ERR_FILE_NOT_SOCK */
103 "File specified by socket filename exists and is not socket.",
104 /* MEMIF_ERR_NO_SHMFD */
105 "Missing shared memory file descriptor. (internal error)",
106 /* MEMIF_ERR_COOKIE */
107 "Invalid cookie on ring. (internal error)",
108 /* MEMIF_ERR_NOBUF_RING */
109 "Ring buffer full.",
110 /* MEMIF_ERR_NOBUF */
111 "Not enough memif buffers. There are unreceived data in shared memory.",
112 /* MEMIF_ERR_NOBUF_DET */
Paul Vinciguerraf4fbfd62020-05-15 23:13:36 -0400113 "Not enough space for memif details in supplied buffer. String data might be malformed.",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200114 /* MEMIF_ERR_INT_WRITE */
115 "Send interrupt error.",
116 /* MEMIF_ERR_MFMSG */
117 "Malformed message received on control channel.",
118 /* MEMIF_ERR_QID */
119 "Invalid queue id",
120 /* MEMIF_ERR_PROTO */
121 "Incompatible memory interface protocol version.",
122 /* MEMIF_ERR_ID */
123 "Unmatched interface id.",
124 /* MEMIF_ERR_ACCSLAVE */
Paul Vinciguerraf4fbfd62020-05-15 23:13:36 -0400125 "Slave cannot accept connection request.",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200126 /* MEMIF_ERR_ALRCONN */
127 "Interface is already connected.",
128 /* MEMIF_ERR_MODE */
129 "Mode mismatch.",
130 /* MEMIF_ERR_SECRET */
131 "Secret mismatch.",
132 /* MEMIF_ERR_NOSECRET */
133 "Secret required.",
134 /* MEMIF_ERR_MAXREG */
135 "Limit on total number of regions reached.",
136 /* MEMIF_ERR_MAXRING */
137 "Limit on total number of ring reached.",
138 /* MEMIF_ERR_NO_INTFD */
139 "Missing interrupt file descriptor. (internal error)",
140 /* MEMIF_ERR_DISCONNECT */
141 "Interface received disconnect request.",
142 /* MEMIF_ERR_DISCONNECTED */
143 "Interface is disconnected.",
144 /* MEMIF_ERR_UNKNOWN_MSG */
Milan Lenco0a47c992017-10-12 14:19:31 +0200145 "Unknown message type received on control channel. (internal error)",
146 /* MEMIF_ERR_POLL_CANCEL */
Damjan Marion6d56fa42017-11-03 12:24:37 +0100147 "Memif event polling was canceled.",
148 /* MEMIF_ERR_MAX_RING */
Jakub Grajciar3744fc72018-03-29 13:15:10 +0200149 "Maximum log2 ring size is 15",
Jakub Grajciarab7c2b02018-03-28 10:21:05 +0200150 /* MEMIF_ERR_PRIVHDR */
151 "Private headers not supported."
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200152};
153
154#define MEMIF_ERR_UNDEFINED "undefined error"
155
156char *
157memif_strerror (int err_code)
158{
159 if (err_code >= ERRLIST_LEN)
160 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000161 strlcpy (memif_buf, MEMIF_ERR_UNDEFINED, sizeof (memif_buf));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200162 }
163 else
164 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000165 strlcpy (memif_buf, memif_errlist[err_code], sizeof (memif_buf));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200166 }
167 return memif_buf;
168}
169
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200170uint16_t
171memif_get_version ()
172{
173 return MEMIF_VERSION;
174}
175
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200176#define DBG_TX_BUF (0)
177#define DBG_RX_BUF (1)
178
179#ifdef MEMIF_DBG_SHM
180static void
181print_bytes (void *data, uint16_t len, uint8_t q)
182{
183 if (q == DBG_TX_BUF)
184 printf ("\nTX:\n\t");
185 else
186 printf ("\nRX:\n\t");
187 int i;
188 for (i = 0; i < len; i++)
189 {
190 if (i % 8 == 0)
191 printf ("\n%d:\t", i);
192 printf ("%02X ", ((uint8_t *) (data))[i]);
193 }
194 printf ("\n\n");
195}
Jakub Grajciarba3c4e82017-09-18 11:21:40 +0200196#endif /* MEMIF_DBG_SHM */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200197
198int
199memif_syscall_error_handler (int err_code)
200{
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200201 DBG ("%s", strerror (err_code));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200202
203 if (err_code == 0)
204 return MEMIF_ERR_SUCCESS;
205 if (err_code == EACCES)
206 return MEMIF_ERR_ACCES;
207 if (err_code == ENFILE)
208 return MEMIF_ERR_FILE_LIMIT;
209 if (err_code == EMFILE)
210 return MEMIF_ERR_PROC_FILE_LIMIT;
211 if (err_code == ENOMEM)
212 return MEMIF_ERR_NOMEM;
Damjan Marion6d56fa42017-11-03 12:24:37 +0100213/* connection refused if master does not exist
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200214 this error would spam the user until master was created */
Jakub Grajciar568cc462018-09-05 12:11:35 +0200215/*
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200216 if (err_code == ECONNREFUSED)
217 return MEMIF_ERR_SUCCESS;
Jakub Grajciar568cc462018-09-05 12:11:35 +0200218*/
219 if (err_code == ECONNREFUSED)
220 return MEMIF_ERR_CONNREFUSED;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200221 if (err_code == EALREADY)
222 return MEMIF_ERR_ALREADY;
223 if (err_code == EAGAIN)
224 return MEMIF_ERR_AGAIN;
225 if (err_code == EBADF)
226 return MEMIF_ERR_BAD_FD;
227 if (err_code == ENOENT)
228 return MEMIF_ERR_NO_FILE;
229
230 /* other syscall errors */
231 return MEMIF_ERR_SYSCALL;
232}
233
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200234/* Always valid */
235libmemif_main_t *
236get_libmemif_main (memif_socket_t * ms)
237{
238 if (ms != NULL && ms->lm != NULL)
239 return ms->lm;
240 return &libmemif_main;
241}
242
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200243static int
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200244memif_add_epoll_fd (libmemif_main_t * lm, int fd, uint32_t events)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200245{
246 if (fd < 0)
247 {
248 DBG ("invalid fd %d", fd);
249 return -1;
250 }
251 struct epoll_event evt;
252 memset (&evt, 0, sizeof (evt));
253 evt.events = events;
254 evt.data.fd = fd;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200255 if (epoll_ctl (lm->epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200256 {
257 DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
258 return -1;
259 }
260 DBG ("fd %d added to epoll", fd);
261 return 0;
262}
263
264static int
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200265memif_mod_epoll_fd (libmemif_main_t * lm, int fd, uint32_t events)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200266{
267 if (fd < 0)
268 {
269 DBG ("invalid fd %d", fd);
270 return -1;
271 }
272 struct epoll_event evt;
273 memset (&evt, 0, sizeof (evt));
274 evt.events = events;
275 evt.data.fd = fd;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200276 if (epoll_ctl (lm->epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200277 {
278 DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
279 return -1;
280 }
Paul Vinciguerraf4fbfd62020-05-15 23:13:36 -0400281 DBG ("fd %d modified on epoll", fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200282 return 0;
283}
284
285static int
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200286memif_del_epoll_fd (libmemif_main_t * lm, int fd)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200287{
288 if (fd < 0)
289 {
290 DBG ("invalid fd %d", fd);
291 return -1;
292 }
293 struct epoll_event evt;
294 memset (&evt, 0, sizeof (evt));
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200295 if (epoll_ctl (lm->epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200296 {
297 DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
298 return -1;
299 }
300 DBG ("fd %d removed from epoll", fd);
301 return 0;
302}
303
304int
Jakub Grajciar12df4972019-07-01 14:24:48 +0200305memif_control_fd_update (int fd, uint8_t events, void *private_ctx)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200306{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200307 libmemif_main_t *lm;
308
Jakub Grajciar6f090fa2019-11-14 10:47:25 +0100309 lm = (private_ctx == NULL) ? &libmemif_main : (libmemif_main_t *) private_ctx;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200310
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200311 if (events & MEMIF_FD_EVENT_DEL)
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200312 return memif_del_epoll_fd (lm, fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200313
314 uint32_t evt = 0;
315 if (events & MEMIF_FD_EVENT_READ)
316 evt |= EPOLLIN;
317 if (events & MEMIF_FD_EVENT_WRITE)
318 evt |= EPOLLOUT;
319
320 if (events & MEMIF_FD_EVENT_MOD)
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200321 return memif_mod_epoll_fd (lm, fd, evt);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200322
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200323 return memif_add_epoll_fd (lm, fd, evt);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200324}
325
326int
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200327add_list_elt (libmemif_main_t * lm, memif_list_elt_t * e,
328 memif_list_elt_t ** list, uint16_t * len)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200329{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200330 memif_list_elt_t *tmp;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200331 int i;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200332
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200333 for (i = 0; i < *len; i++)
334 {
335 if ((*list)[i].data_struct == NULL)
336 {
337 (*list)[i].key = e->key;
338 (*list)[i].data_struct = e->data_struct;
339 return i;
340 }
341 }
Jakub Grajciar12df4972019-07-01 14:24:48 +0200342
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200343 tmp = lm->realloc (*list, sizeof (memif_list_elt_t) * *len * 2);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200344 if (tmp == NULL)
345 return -1;
346
347 for (i = *len; i < *len * 2; i++)
348 {
349 tmp[i].key = -1;
350 tmp[i].data_struct = NULL;
351 }
352
353 tmp[*len].key = e->key;
354 tmp[*len].data_struct = e->data_struct;
355 i = *len;
356 *len = *len * 2;
357 *list = tmp;
358
359 return i;
360}
361
362int
363get_list_elt (memif_list_elt_t ** e, memif_list_elt_t * list, uint16_t len,
364 int key)
365{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200366 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200367 if (key == -1)
368 {
369 *e = NULL;
370 return -1;
371 }
Jakub Grajciar12df4972019-07-01 14:24:48 +0200372
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200373 for (i = 0; i < len; i++)
374 {
375 if (list[i].key == key)
376 {
377 *e = &list[i];
378 return 0;
379 }
380 }
381 *e = NULL;
382 return -1;
383}
384
385/* does not free memory, only marks element as free */
386int
387free_list_elt (memif_list_elt_t * list, uint16_t len, int key)
388{
389 int i;
390 for (i = 0; i < len; i++)
391 {
392 if (list[i].key == key)
393 {
394 list[i].key = -1;
395 list[i].data_struct = NULL;
396 return 0;
397 }
398 }
399
400 return -1;
401}
402
403int
404free_list_elt_ctx (memif_list_elt_t * list, uint16_t len,
405 memif_connection_t * ctx)
406{
407 int i;
408 for (i = 0; i < len; i++)
409 {
410 if (list[i].key == -1)
411 {
412 if (list[i].data_struct == ctx)
413 {
414 list[i].data_struct = NULL;
415 return 0;
416 }
417 }
418 }
419
420 return -1;
421}
422
423static void
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200424memif_control_fd_update_register (libmemif_main_t * lm,
425 memif_control_fd_update_t * cb)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200426{
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200427 lm->control_fd_update = cb;
428}
429
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200430void
431memif_register_external_region (memif_add_external_region_t * ar,
432 memif_get_external_region_addr_t * gr,
433 memif_del_external_region_t * dr,
434 memif_get_external_buffer_offset_t * go)
435{
436 libmemif_main_t *lm = &libmemif_main;
437 lm->add_external_region = ar;
438 lm->get_external_region_addr = gr;
439 lm->del_external_region = dr;
440 lm->get_external_buffer_offset = go;
441}
442
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200443static void
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200444memif_alloc_register (libmemif_main_t * lm, memif_alloc_t * ma)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200445{
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200446 lm->alloc = ma;
447}
448
449static void
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200450memif_realloc_register (libmemif_main_t * lm, memif_realloc_t * mr)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200451{
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200452 lm->realloc = mr;
453}
454
455static void
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200456memif_free_register (libmemif_main_t * lm, memif_free_t * mf)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200457{
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200458 lm->free = mf;
459}
460
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200461int
Jakub Grajciar12df4972019-07-01 14:24:48 +0200462memif_set_connection_request_timer (struct itimerspec timer)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100463{
464 libmemif_main_t *lm = &libmemif_main;
465 int err = MEMIF_ERR_SUCCESS;
466
467 lm->arm = timer;
468
469 /* overwrite timer, if already armed */
470 if (lm->disconn_slaves != 0)
471 {
472 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
473 {
474 err = memif_syscall_error_handler (errno);
475 }
476 }
477 return err;
478}
479
480int
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200481memif_per_thread_set_connection_request_timer (memif_per_thread_main_handle_t
482 pt_main,
483 struct itimerspec timer)
484{
485 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
486 int err = MEMIF_ERR_SUCCESS;
487
488 lm->arm = timer;
489
490 /* overwrite timer, if already armed */
491 if (lm->disconn_slaves != 0)
492 {
493 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
494 {
495 err = memif_syscall_error_handler (errno);
496 }
497 }
498 return err;
499}
500
501int
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200502memif_init (memif_control_fd_update_t * on_control_fd_update, char *app_name,
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200503 memif_alloc_t * memif_alloc, memif_realloc_t * memif_realloc,
504 memif_free_t * memif_free)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200505{
506 int err = MEMIF_ERR_SUCCESS; /* 0 */
507 libmemif_main_t *lm = &libmemif_main;
Jakub Grajciar19418712018-03-13 13:57:50 +0100508 memset (lm, 0, sizeof (libmemif_main_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200509
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200510 /* register custom memory management */
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200511 if (memif_alloc != NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200512 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200513 memif_alloc_register (lm, memif_alloc);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200514 }
515 else
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200516 memif_alloc_register (lm, malloc);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200517
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200518 if (memif_realloc != NULL)
519 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200520 memif_realloc_register (lm, memif_realloc);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200521 }
522 else
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200523 memif_realloc_register (lm, realloc);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200524
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200525 if (memif_free != NULL)
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200526 memif_free_register (lm, memif_free);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200527 else
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200528 memif_free_register (lm, free);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200529
530 if (app_name != NULL)
531 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000532 strlcpy ((char *) lm->app_name, app_name, sizeof (lm->app_name));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200533 }
534 else
535 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000536 strlcpy ((char *) lm->app_name, MEMIF_DEFAULT_APP_NAME,
537 sizeof (lm->app_name));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200538 }
539
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200540 lm->poll_cancel_fd = -1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200541 /* register control fd update callback */
542 if (on_control_fd_update != NULL)
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200543 memif_control_fd_update_register (lm, on_control_fd_update);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200544 else
545 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200546 lm->epfd = epoll_create (1);
547 memif_control_fd_update_register (lm, memif_control_fd_update);
548 if ((lm->poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
Milan Lenco0a47c992017-10-12 14:19:31 +0200549 {
550 err = errno;
551 DBG ("eventfd: %s", strerror (err));
552 return memif_syscall_error_handler (err);
553 }
Jakub Grajciar6f090fa2019-11-14 10:47:25 +0100554 lm->control_fd_update (lm->poll_cancel_fd, MEMIF_FD_EVENT_READ, lm->private_ctx);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200555 DBG ("libmemif event polling initialized");
556 }
557
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200558 lm->control_list_len = 2;
559 lm->interrupt_list_len = 2;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200560 lm->socket_list_len = 1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200561 lm->pending_list_len = 1;
562
563 lm->control_list =
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200564 lm->alloc (sizeof (memif_list_elt_t) * lm->control_list_len);
565 if (lm->control_list == NULL)
566 {
567 err = MEMIF_ERR_NOMEM;
568 goto error;
569 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200570 lm->interrupt_list =
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200571 lm->alloc (sizeof (memif_list_elt_t) * lm->interrupt_list_len);
572 if (lm->interrupt_list == NULL)
573 {
574 err = MEMIF_ERR_NOMEM;
575 goto error;
576 }
Jakub Grajciar12df4972019-07-01 14:24:48 +0200577 lm->socket_list =
578 lm->alloc (sizeof (memif_list_elt_t) * lm->socket_list_len);
579 if (lm->socket_list == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200580 {
581 err = MEMIF_ERR_NOMEM;
582 goto error;
583 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200584 lm->pending_list =
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200585 lm->alloc (sizeof (memif_list_elt_t) * lm->pending_list_len);
586 if (lm->pending_list == NULL)
587 {
588 err = MEMIF_ERR_NOMEM;
589 goto error;
590 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200591
592 int i;
593 for (i = 0; i < lm->control_list_len; i++)
594 {
595 lm->control_list[i].key = -1;
596 lm->control_list[i].data_struct = NULL;
597 }
598 for (i = 0; i < lm->interrupt_list_len; i++)
599 {
600 lm->interrupt_list[i].key = -1;
601 lm->interrupt_list[i].data_struct = NULL;
602 }
Jakub Grajciar12df4972019-07-01 14:24:48 +0200603 for (i = 0; i < lm->socket_list_len; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200604 {
Jakub Grajciar12df4972019-07-01 14:24:48 +0200605 lm->socket_list[i].key = -1;
606 lm->socket_list[i].data_struct = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200607 }
608 for (i = 0; i < lm->pending_list_len; i++)
609 {
610 lm->pending_list[i].key = -1;
611 lm->pending_list[i].data_struct = NULL;
612 }
613
614 lm->disconn_slaves = 0;
615
616 lm->timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
617 if (lm->timerfd < 0)
618 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200619 err = memif_syscall_error_handler (errno);
620 goto error;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200621 }
622
Jakub Grajciar84b83772019-03-04 12:42:19 +0100623 lm->arm.it_value.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
624 lm->arm.it_value.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
625 lm->arm.it_interval.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
626 lm->arm.it_interval.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200627
Jakub Grajciar6f090fa2019-11-14 10:47:25 +0100628 if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ, lm->private_ctx) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200629 {
630 DBG ("callback type memif_control_fd_update_t error!");
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200631 err = MEMIF_ERR_CB_FDUPDATE;
632 goto error;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200633 }
634
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200635 /* Create default socket */
636 err = memif_create_socket ((memif_socket_handle_t *) &
637 lm->default_socket,
638 MEMIF_DEFAULT_SOCKET_PATH, NULL);
639 if (err != MEMIF_ERR_SUCCESS)
640 goto error;
641
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200642 return err;
643
644error:
645 memif_cleanup ();
646 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200647}
648
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200649int
650memif_per_thread_init (memif_per_thread_main_handle_t * pt_main,
651 void *private_ctx,
652 memif_control_fd_update_t * on_control_fd_update,
653 char *app_name, memif_alloc_t * memif_alloc,
654 memif_realloc_t * memif_realloc,
655 memif_free_t * memif_free)
656{
657 memif_err_t err = MEMIF_ERR_SUCCESS;
658 int i;
659 libmemif_main_t *lm;
660
661 /* Allocate unique libmemif main */
662 if (memif_alloc != NULL)
663 lm = memif_alloc (sizeof (libmemif_main_t));
664 else
665 lm = malloc (sizeof (libmemif_main_t));
666
667 if (lm == NULL)
668 return MEMIF_ERR_NOMEM;
669
670 memset (lm, 0, sizeof (libmemif_main_t));
671
672 /* register custom memory management */
673 if (memif_alloc != NULL)
674 {
675 memif_alloc_register (lm, memif_alloc);
676 }
677 else
678 memif_alloc_register (lm, malloc);
679
680 if (memif_realloc != NULL)
681 {
682 memif_realloc_register (lm, memif_realloc);
683 }
684 else
685 memif_realloc_register (lm, realloc);
686
687 if (memif_free != NULL)
688 memif_free_register (lm, memif_free);
689 else
690 memif_free_register (lm, free);
691
692 lm->private_ctx = private_ctx;
693
694 /* set app name */
695 if (app_name != NULL)
696 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000697 strlcpy ((char *) lm->app_name, app_name, MEMIF_NAME_LEN);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200698 }
699 else
700 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000701 strlcpy ((char *) lm->app_name, MEMIF_DEFAULT_APP_NAME,
702 sizeof (lm->app_name));
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200703 }
704
705 lm->poll_cancel_fd = -1;
706 /* register control fd update callback */
707 if (on_control_fd_update != NULL)
708 memif_control_fd_update_register (lm, on_control_fd_update);
709 else
710 {
Jakub Grajciar6f090fa2019-11-14 10:47:25 +0100711 /* private_ctx only used internally by memif_control_fd_update
712 * pointer to this libmemif main
713 */
714 lm->private_ctx = lm;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200715 lm->epfd = epoll_create (1);
716 memif_control_fd_update_register (lm, memif_control_fd_update);
717 if ((lm->poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
718 {
719 err = errno;
720 DBG ("eventfd: %s", strerror (err));
721 return memif_syscall_error_handler (err);
722 }
723 lm->control_fd_update (lm->poll_cancel_fd, MEMIF_FD_EVENT_READ,
724 lm->private_ctx);
725 DBG ("libmemif event polling initialized");
726 }
727
728 /* Initialize lists */
729 lm->control_list_len = 2;
730 lm->interrupt_list_len = 2;
731 lm->socket_list_len = 1;
732 lm->pending_list_len = 1;
733
734 lm->control_list =
735 lm->alloc (sizeof (memif_list_elt_t) * lm->control_list_len);
736 if (lm->control_list == NULL)
737 {
738 err = MEMIF_ERR_NOMEM;
739 goto error;
740 }
741 lm->interrupt_list =
742 lm->alloc (sizeof (memif_list_elt_t) * lm->interrupt_list_len);
743 if (lm->interrupt_list == NULL)
744 {
745 err = MEMIF_ERR_NOMEM;
746 goto error;
747 }
748 lm->socket_list =
749 lm->alloc (sizeof (memif_list_elt_t) * lm->socket_list_len);
750 if (lm->socket_list == NULL)
751 {
752 err = MEMIF_ERR_NOMEM;
753 goto error;
754 }
755 lm->pending_list =
756 lm->alloc (sizeof (memif_list_elt_t) * lm->pending_list_len);
757 if (lm->pending_list == NULL)
758 {
759 err = MEMIF_ERR_NOMEM;
760 goto error;
761 }
762
763 for (i = 0; i < lm->control_list_len; i++)
764 {
765 lm->control_list[i].key = -1;
766 lm->control_list[i].data_struct = NULL;
767 }
768 for (i = 0; i < lm->interrupt_list_len; i++)
769 {
770 lm->interrupt_list[i].key = -1;
771 lm->interrupt_list[i].data_struct = NULL;
772 }
773 for (i = 0; i < lm->socket_list_len; i++)
774 {
775 lm->socket_list[i].key = -1;
776 lm->socket_list[i].data_struct = NULL;
777 }
778 for (i = 0; i < lm->pending_list_len; i++)
779 {
780 lm->pending_list[i].key = -1;
781 lm->pending_list[i].data_struct = NULL;
782 }
783
784 /* Initialize autoconnect */
785 lm->disconn_slaves = 0;
786
787 lm->timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
788 if (lm->timerfd < 0)
789 {
790 err = memif_syscall_error_handler (errno);
791 goto error;
792 }
793
794 lm->arm.it_value.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
795 lm->arm.it_value.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
796 lm->arm.it_interval.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
797 lm->arm.it_interval.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
798
799 if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ,
800 lm->private_ctx) < 0)
801 {
802 DBG ("callback type memif_control_fd_update_t error!");
803 err = MEMIF_ERR_CB_FDUPDATE;
804 goto error;
805 }
806
807 *pt_main = lm;
808
809 return err;
810
811error:
812 *pt_main = lm;
813 memif_per_thread_cleanup (pt_main);
814 return err;
815}
816
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200817static inline memif_ring_t *
818memif_get_ring (memif_connection_t * conn, memif_ring_type_t type,
819 uint16_t ring_num)
820{
821 if (&conn->regions[0] == NULL)
822 return NULL;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200823 void *p = conn->regions[0].addr;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200824 int ring_size =
825 sizeof (memif_ring_t) +
826 sizeof (memif_desc_t) * (1 << conn->run_args.log2_ring_size);
827 p += (ring_num + type * conn->run_args.num_s2m_rings) * ring_size;
828
829 return (memif_ring_t *) p;
830}
831
832int
833memif_set_rx_mode (memif_conn_handle_t c, memif_rx_mode_t rx_mode,
834 uint16_t qid)
835{
836 memif_connection_t *conn = (memif_connection_t *) c;
837 if (conn == NULL)
838 return MEMIF_ERR_NOCONN;
839 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +0200840 (conn->args.is_master) ? conn->run_args.num_s2m_rings : conn->
841 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200842 if (qid >= num)
843 return MEMIF_ERR_QID;
844
845 conn->rx_queues[qid].ring->flags = rx_mode;
846 DBG ("rx_mode flag: %u", conn->rx_queues[qid].ring->flags);
847 return MEMIF_ERR_SUCCESS;
848}
849
Jakub Grajciar12df4972019-07-01 14:24:48 +0200850static int
851memif_socket_start_listening (memif_socket_t * ms)
852{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200853 libmemif_main_t *lm = get_libmemif_main (ms);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200854 memif_list_elt_t elt;
855 struct stat file_stat;
856 struct sockaddr_un un = { 0 };
857 int on = 1;
858 int err = MEMIF_ERR_SUCCESS;
859
860 if (ms->type == MEMIF_SOCKET_TYPE_CLIENT)
861 return MEMIF_ERR_INVAL_ARG;
862
863 /* check if file exists */
864 if (stat ((char *) ms->filename, &file_stat) == 0)
865 {
866 if (S_ISSOCK (file_stat.st_mode))
867 unlink ((char *) ms->filename);
868 else
869 return memif_syscall_error_handler (errno);
870 }
871
872 ms->fd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
873 if (ms->fd < 0)
874 {
875 err = memif_syscall_error_handler (errno);
876 goto error;
877 }
878
879 DBG ("socket %d created", ms->fd);
880 un.sun_family = AF_UNIX;
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000881 strlcpy ((char *) un.sun_path, (char *) ms->filename, sizeof (un.sun_path));
Jakub Grajciar12df4972019-07-01 14:24:48 +0200882 if (setsockopt (ms->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
883 {
884 err = memif_syscall_error_handler (errno);
885 goto error;
886 }
887 if (bind (ms->fd, (struct sockaddr *) &un, sizeof (un)) < 0)
888 {
889 err = memif_syscall_error_handler (errno);
890 goto error;
891 }
892 if (listen (ms->fd, 1) < 0)
893 {
894 err = memif_syscall_error_handler (errno);
895 goto error;
896 }
897 if (stat ((char *) ms->filename, &file_stat) < 0)
898 {
899 err = memif_syscall_error_handler (errno);
900 goto error;
901 }
902
903 /* add socket to libmemif main */
904 elt.key = ms->fd;
905 elt.data_struct = ms;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200906 add_list_elt (lm, &elt, &lm->socket_list, &lm->socket_list_len);
Jakub Grajciar6f090fa2019-11-14 10:47:25 +0100907 /* if lm->private_ctx == lm event polling is done by libmemif */
908 lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_READ, lm->private_ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200909
910 ms->type = MEMIF_SOCKET_TYPE_LISTENER;
911
912 return err;
913
914error:
915 if (ms->fd > 0)
916 {
917 close (ms->fd);
918 ms->fd = -1;
919 }
920 return err;
921}
922
923int
924memif_create_socket (memif_socket_handle_t * sock, const char *filename,
925 void *private_ctx)
926{
927 libmemif_main_t *lm = &libmemif_main;
928 memif_socket_t *ms = (memif_socket_t *) * sock;
929 int i, err = MEMIF_ERR_SUCCESS;
930
931 for (i = 0; i < lm->socket_list_len; i++)
932 {
933 if ((ms = (memif_socket_t *) lm->socket_list[i].data_struct) != NULL)
934 {
935 if (strncmp ((char *) ms->filename, filename,
936 strlen ((char *) ms->filename)) == 0)
937 return MEMIF_ERR_INVAL_ARG;
938 }
939 }
940
941 /* allocate memif_socket_t */
942 ms = NULL;
943 ms = lm->alloc (sizeof (memif_socket_t));
944 if (ms == NULL)
945 {
946 err = MEMIF_ERR_NOMEM;
947 goto error;
948 }
949 memset (ms, 0, sizeof (memif_socket_t));
950 /* set filename */
Jakub Grajciar57084e52021-03-01 08:45:17 +0100951 memset (ms->filename, 0, sizeof (ms->filename));
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000952 strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
Jakub Grajciar12df4972019-07-01 14:24:48 +0200953
954 ms->type = MEMIF_SOCKET_TYPE_NONE;
955
956 ms->interface_list_len = 1;
957 ms->interface_list =
958 lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
959 if (ms->interface_list == NULL)
960 {
961 err = MEMIF_ERR_NOMEM;
962 goto error;
963 }
964 ms->interface_list[0].key = -1;
965 ms->interface_list[0].data_struct = NULL;
966
967 *sock = ms;
968
969 return err;
970
971error:
972 if (ms != NULL)
973 {
Jakub Grajciar12df4972019-07-01 14:24:48 +0200974 if (ms->fd > 0)
975 {
976 close (ms->fd);
977 ms->fd = -1;
978 }
979 if (ms->interface_list != NULL)
980 {
981 lm->free (ms->interface_list);
982 ms->interface_list = NULL;
983 ms->interface_list_len = 0;
984 }
985 lm->free (ms);
986 *sock = ms = NULL;
987 }
988 return err;
989}
990
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200991int
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200992memif_per_thread_create_socket (memif_per_thread_main_handle_t pt_main,
993 memif_socket_handle_t * sock,
994 const char *filename, void *private_ctx)
995{
996 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
997 memif_socket_t *ms = (memif_socket_t *) * sock;
998 int i, err = MEMIF_ERR_SUCCESS;
999
1000 if (lm == NULL)
1001 return MEMIF_ERR_INVAL_ARG;
1002
1003 for (i = 0; i < lm->socket_list_len; i++)
1004 {
1005 if ((ms = (memif_socket_t *) lm->socket_list[i].data_struct) != NULL)
1006 {
1007 if (strncmp ((char *) ms->filename, filename,
1008 strlen ((char *) ms->filename)) == 0)
1009 return MEMIF_ERR_INVAL_ARG;
1010 }
1011 }
1012
1013 /* allocate memif_socket_t */
1014 ms = NULL;
1015 ms = lm->alloc (sizeof (memif_socket_t));
1016 if (ms == NULL)
1017 {
1018 err = MEMIF_ERR_NOMEM;
1019 goto error;
1020 }
1021 memset (ms, 0, sizeof (memif_socket_t));
1022 ms->lm = lm;
1023 /* set filename */
Jakub Grajciar57084e52021-03-01 08:45:17 +01001024 memset (ms->filename, 0, sizeof (ms->filename));
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001025 strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001026
1027 ms->type = MEMIF_SOCKET_TYPE_NONE;
1028
1029 ms->interface_list_len = 1;
1030 ms->interface_list =
1031 lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
1032 if (ms->interface_list == NULL)
1033 {
1034 err = MEMIF_ERR_NOMEM;
1035 goto error;
1036 }
1037 ms->interface_list[0].key = -1;
1038 ms->interface_list[0].data_struct = NULL;
1039
1040 *sock = ms;
1041
1042 return err;
1043
1044error:
1045 if (ms != NULL)
1046 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001047 if (ms->fd > 0)
1048 {
1049 close (ms->fd);
1050 ms->fd = -1;
1051 }
1052 if (ms->interface_list != NULL)
1053 {
1054 lm->free (ms->interface_list);
1055 ms->interface_list = NULL;
1056 ms->interface_list_len = 0;
1057 }
1058 lm->free (ms);
1059 *sock = ms = NULL;
1060 }
1061 return err;
1062}
1063
1064int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001065memif_create (memif_conn_handle_t * c, memif_conn_args_t * args,
1066 memif_connection_update_t * on_connect,
1067 memif_connection_update_t * on_disconnect,
1068 memif_interrupt_t * on_interrupt, void *private_ctx)
1069{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001070 libmemif_main_t *lm = get_libmemif_main (args->socket);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001071 int err, index = 0;
1072 memif_list_elt_t elt;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001073 memif_connection_t *conn = (memif_connection_t *) * c;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001074 memif_socket_t *ms;
1075
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001076 if (conn != NULL)
1077 {
1078 DBG ("This handle already points to existing memif.");
1079 return MEMIF_ERR_CONN;
1080 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001081
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001082 conn = (memif_connection_t *) lm->alloc (sizeof (memif_connection_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001083 if (conn == NULL)
1084 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001085 err = MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001086 goto error;
1087 }
1088 memset (conn, 0, sizeof (memif_connection_t));
1089
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001090 conn->args.interface_id = args->interface_id;
1091
1092 if (args->log2_ring_size == 0)
1093 args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
Damjan Marion6d56fa42017-11-03 12:24:37 +01001094 else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
1095 {
1096 err = MEMIF_ERR_MAX_RING;
1097 goto error;
1098 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001099 if (args->buffer_size == 0)
1100 args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
1101 if (args->num_s2m_rings == 0)
1102 args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
1103 if (args->num_m2s_rings == 0)
1104 args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
1105
1106 conn->args.num_s2m_rings = args->num_s2m_rings;
1107 conn->args.num_m2s_rings = args->num_m2s_rings;
1108 conn->args.buffer_size = args->buffer_size;
1109 conn->args.log2_ring_size = args->log2_ring_size;
1110 conn->args.is_master = args->is_master;
1111 conn->args.mode = args->mode;
1112 conn->msg_queue = NULL;
1113 conn->regions = NULL;
1114 conn->tx_queues = NULL;
1115 conn->rx_queues = NULL;
1116 conn->fd = -1;
1117 conn->on_connect = on_connect;
1118 conn->on_disconnect = on_disconnect;
1119 conn->on_interrupt = on_interrupt;
1120 conn->private_ctx = private_ctx;
1121 memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
1122
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001123 strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
1124 sizeof (conn->args.interface_name));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001125
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001126 if ((strlen ((char *) args->secret)) > 0)
1127 strlcpy ((char *) conn->args.secret, (char *) args->secret,
1128 sizeof (conn->args.secret));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001129
Jakub Grajciar12df4972019-07-01 14:24:48 +02001130 if (args->socket != NULL)
1131 conn->args.socket = args->socket;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001132 else if (lm->default_socket != NULL)
1133 conn->args.socket = lm->default_socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001134 else
1135 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001136 err = MEMIF_ERR_INVAL_ARG;
1137 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001138 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001139
Jakub Grajciar12df4972019-07-01 14:24:48 +02001140 ms = (memif_socket_t *) conn->args.socket;
1141
1142 if ((conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_CLIENT) ||
1143 (!conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_LISTENER))
1144 {
1145 err = MEMIF_ERR_INVAL_ARG;
1146 goto error;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001147 }
1148
Jakub Grajciar12df4972019-07-01 14:24:48 +02001149 elt.key = conn->args.interface_id;
1150 elt.data_struct = conn;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001151 add_list_elt (lm, &elt, &ms->interface_list, &ms->interface_list_len);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001152 ms->use_count++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001153
1154 if (conn->args.is_master)
1155 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001156 if (ms->type == MEMIF_SOCKET_TYPE_NONE)
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001157 {
1158 err = memif_socket_start_listening (ms);
1159 if (err != MEMIF_ERR_SUCCESS)
1160 goto error;
1161 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001162 }
1163 else
1164 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001165 elt.key = -1;
1166 elt.data_struct = conn;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001167 if ((index =
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001168 add_list_elt (lm, &elt, &lm->control_list,
1169 &lm->control_list_len)) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001170 {
1171 err = MEMIF_ERR_NOMEM;
1172 goto error;
1173 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001174
Jakub Grajciar84b83772019-03-04 12:42:19 +01001175 conn->index = index;
1176
Paul Vinciguerraf4fbfd62020-05-15 23:13:36 -04001177 /* try connecting to master */
Jakub Grajciar12df4972019-07-01 14:24:48 +02001178 err = memif_request_connection (conn);
Jakub Grajciar272e2e42019-07-24 10:33:11 +02001179 if ((err != MEMIF_ERR_SUCCESS) && (lm->disconn_slaves == 0))
Jakub Grajciar84b83772019-03-04 12:42:19 +01001180 {
1181 /* connection failed, arm reconnect timer (if not armed) */
1182 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1183 {
1184 err = memif_syscall_error_handler (errno);
1185 goto error;
1186 }
1187 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001188 lm->disconn_slaves++;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001189 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001190
Jakub Grajciar12df4972019-07-01 14:24:48 +02001191 *c = conn;
1192
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001193 return 0;
1194
1195error:
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001196 if (conn != NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001197 lm->free (conn);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001198 *c = conn = NULL;
1199 return err;
1200}
1201
1202int
Jakub Grajciar12df4972019-07-01 14:24:48 +02001203memif_request_connection (memif_conn_handle_t c)
Jakub Grajciar84b83772019-03-04 12:42:19 +01001204{
Jakub Grajciar84b83772019-03-04 12:42:19 +01001205 memif_connection_t *conn = (memif_connection_t *) c;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001206 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001207 memif_socket_t *ms;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001208 int err = MEMIF_ERR_SUCCESS;
1209 int sockfd = -1;
1210 struct sockaddr_un sun;
1211
Jakub Grajciar12df4972019-07-01 14:24:48 +02001212 if (conn == NULL)
1213 return MEMIF_ERR_NOCONN;
1214
1215 ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001216 lm = get_libmemif_main (ms);
1217
Jakub Grajciar12df4972019-07-01 14:24:48 +02001218
1219 if (conn->args.is_master || ms->type == MEMIF_SOCKET_TYPE_LISTENER)
Jakub Grajciar84b83772019-03-04 12:42:19 +01001220 return MEMIF_ERR_INVAL_ARG;
1221 if (conn->fd > 0)
1222 return MEMIF_ERR_ALRCONN;
1223
1224 sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
1225 if (sockfd < 0)
1226 {
1227 err = memif_syscall_error_handler (errno);
1228 goto error;
1229 }
1230
1231 sun.sun_family = AF_UNIX;
1232
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001233 strlcpy (sun.sun_path, (char *) ms->filename, sizeof (sun.sun_path));
Jakub Grajciar84b83772019-03-04 12:42:19 +01001234
1235 if (connect (sockfd, (struct sockaddr *) &sun,
Jakub Grajciar12df4972019-07-01 14:24:48 +02001236 sizeof (struct sockaddr_un)) == 0)
Jakub Grajciar84b83772019-03-04 12:42:19 +01001237 {
1238 conn->fd = sockfd;
1239 conn->read_fn = memif_conn_fd_read_ready;
1240 conn->write_fn = memif_conn_fd_write_ready;
1241 conn->error_fn = memif_conn_fd_error;
1242
1243 lm->control_list[conn->index].key = conn->fd;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001244 lm->control_fd_update (sockfd,
Jakub Grajciar12df4972019-07-01 14:24:48 +02001245 MEMIF_FD_EVENT_READ |
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001246 MEMIF_FD_EVENT_WRITE, lm->private_ctx);
Jakub Grajciar84b83772019-03-04 12:42:19 +01001247
1248 lm->disconn_slaves--;
1249 if (lm->disconn_slaves == 0)
1250 {
1251 if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1252 {
1253 err = memif_syscall_error_handler (errno);
1254 return err;
1255 }
1256 }
1257 }
1258 else
1259 {
Jakub Grajciar272e2e42019-07-24 10:33:11 +02001260 err = memif_syscall_error_handler (errno);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001261 strcpy ((char *) conn->remote_disconnect_string, memif_strerror (err));
Jakub Grajciar84b83772019-03-04 12:42:19 +01001262 goto error;
1263 }
1264
Jakub Grajciar12df4972019-07-01 14:24:48 +02001265 ms->type = MEMIF_SOCKET_TYPE_CLIENT;
1266
1267 return err;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001268
1269error:
1270 if (sockfd > 0)
1271 close (sockfd);
1272 sockfd = -1;
1273 return err;
1274}
1275
1276int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001277memif_control_fd_handler (int fd, uint8_t events)
1278{
Jakub Grajciar84b83772019-03-04 12:42:19 +01001279 int i, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001280 uint16_t num;
1281 memif_list_elt_t *e = NULL;
1282 memif_connection_t *conn;
1283 libmemif_main_t *lm = &libmemif_main;
1284 if (fd == lm->timerfd)
1285 {
1286 uint64_t b;
1287 ssize_t size;
1288 size = read (fd, &b, sizeof (b));
msardara8f554b72018-12-11 18:36:55 +01001289
1290 if (size == -1)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001291 goto error;
msardara8f554b72018-12-11 18:36:55 +01001292
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001293 for (i = 0; i < lm->control_list_len; i++)
1294 {
1295 if ((lm->control_list[i].key < 0)
1296 && (lm->control_list[i].data_struct != NULL))
1297 {
1298 conn = lm->control_list[i].data_struct;
1299 if (conn->args.is_master)
1300 continue;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001301 err = memif_request_connection (conn);
1302 if (err != MEMIF_ERR_SUCCESS)
1303 DBG ("memif_request_connection: %s", memif_strerror (err));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001304 }
1305 }
1306 }
1307 else
1308 {
1309 get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1310 if (e != NULL)
1311 {
1312 if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1313 {
1314 num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001315 (((memif_connection_t *) e->data_struct)->
1316 args.is_master) ? ((memif_connection_t *) e->
1317 data_struct)->run_args.
1318 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1319 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001320 for (i = 0; i < num; i++)
1321 {
Jakub Grajciar568cc462018-09-05 12:11:35 +02001322 if (((memif_connection_t *) e->data_struct)->
1323 rx_queues[i].int_fd == fd)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001324 {
Jakub Grajciar568cc462018-09-05 12:11:35 +02001325 ((memif_connection_t *) e->data_struct)->
1326 on_interrupt ((void *) e->data_struct,
1327 ((memif_connection_t *) e->
1328 data_struct)->private_ctx, i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001329 return MEMIF_ERR_SUCCESS;
1330 }
1331 }
1332 }
1333 return MEMIF_ERR_SUCCESS;
1334 }
Jakub Grajciar12df4972019-07-01 14:24:48 +02001335 get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1336 if (e != NULL
1337 && ((memif_socket_t *) e->data_struct)->type ==
1338 MEMIF_SOCKET_TYPE_LISTENER)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001339 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001340 err =
1341 memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
Jakub Grajciar84b83772019-03-04 12:42:19 +01001342 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001343 }
1344
1345 get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1346 if (e != NULL)
1347 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001348 err = memif_read_ready (lm, fd);
1349 return err;
1350 }
1351
1352 get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1353 if (e != NULL)
1354 {
1355 if (events & MEMIF_FD_EVENT_READ)
1356 {
1357 err =
1358 ((memif_connection_t *) e->data_struct)->
1359 read_fn (e->data_struct);
1360 if (err != MEMIF_ERR_SUCCESS)
1361 return err;
1362 }
1363 if (events & MEMIF_FD_EVENT_WRITE)
1364 {
1365 err =
1366 ((memif_connection_t *) e->data_struct)->
1367 write_fn (e->data_struct);
1368 if (err != MEMIF_ERR_SUCCESS)
1369 return err;
1370 }
1371 if (events & MEMIF_FD_EVENT_ERROR)
1372 {
1373 err =
1374 ((memif_connection_t *) e->data_struct)->
1375 error_fn (e->data_struct);
1376 if (err != MEMIF_ERR_SUCCESS)
1377 return err;
1378 }
1379 }
1380 }
1381
1382 return MEMIF_ERR_SUCCESS; /* 0 */
1383
1384error:
1385 return err;
1386}
1387
1388int
1389memif_per_thread_control_fd_handler (memif_per_thread_main_handle_t pt_main,
1390 int fd, uint8_t events)
1391{
1392 int i, err = MEMIF_ERR_SUCCESS; /* 0 */
1393 uint16_t num;
1394 memif_list_elt_t *e = NULL;
1395 memif_connection_t *conn;
1396 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1397
1398 if (fd == lm->timerfd)
1399 {
1400 uint64_t b;
1401 ssize_t size;
1402 size = read (fd, &b, sizeof (b));
1403
1404 if (size == -1)
1405 goto error;
1406
1407 for (i = 0; i < lm->control_list_len; i++)
1408 {
1409 if ((lm->control_list[i].key < 0)
1410 && (lm->control_list[i].data_struct != NULL))
1411 {
1412 conn = lm->control_list[i].data_struct;
1413 if (conn->args.is_master)
1414 continue;
1415 err = memif_request_connection (conn);
1416 if (err != MEMIF_ERR_SUCCESS)
1417 DBG ("memif_request_connection: %s", memif_strerror (err));
1418 }
1419 }
1420 }
1421 else
1422 {
1423 get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1424 if (e != NULL)
1425 {
1426 if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1427 {
1428 num =
1429 (((memif_connection_t *) e->data_struct)->
1430 args.is_master) ? ((memif_connection_t *) e->
1431 data_struct)->run_args.
1432 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1433 run_args.num_m2s_rings;
1434 for (i = 0; i < num; i++)
1435 {
1436 if (((memif_connection_t *) e->data_struct)->
1437 rx_queues[i].int_fd == fd)
1438 {
1439 ((memif_connection_t *) e->data_struct)->
1440 on_interrupt ((void *) e->data_struct,
1441 ((memif_connection_t *) e->
1442 data_struct)->private_ctx, i);
1443 return MEMIF_ERR_SUCCESS;
1444 }
1445 }
1446 }
1447 return MEMIF_ERR_SUCCESS;
1448 }
1449 get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1450 if (e != NULL
1451 && ((memif_socket_t *) e->data_struct)->type ==
1452 MEMIF_SOCKET_TYPE_LISTENER)
1453 {
1454 err =
1455 memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
1456 return err;
1457 }
1458
1459 get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1460 if (e != NULL)
1461 {
1462 err = memif_read_ready (lm, fd);
Jakub Grajciar84b83772019-03-04 12:42:19 +01001463 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001464 }
1465
1466 get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1467 if (e != NULL)
1468 {
1469 if (events & MEMIF_FD_EVENT_READ)
1470 {
1471 err =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001472 ((memif_connection_t *) e->data_struct)->
1473 read_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001474 if (err != MEMIF_ERR_SUCCESS)
1475 return err;
1476 }
1477 if (events & MEMIF_FD_EVENT_WRITE)
1478 {
1479 err =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001480 ((memif_connection_t *) e->data_struct)->
1481 write_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001482 if (err != MEMIF_ERR_SUCCESS)
1483 return err;
1484 }
1485 if (events & MEMIF_FD_EVENT_ERROR)
1486 {
1487 err =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001488 ((memif_connection_t *) e->data_struct)->
1489 error_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001490 if (err != MEMIF_ERR_SUCCESS)
1491 return err;
1492 }
1493 }
1494 }
1495
1496 return MEMIF_ERR_SUCCESS; /* 0 */
1497
1498error:
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001499 return err;
1500}
1501
1502int
1503memif_poll_event (int timeout)
1504{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001505 libmemif_main_t *lm = &libmemif_main;
msardara8f554b72018-12-11 18:36:55 +01001506 struct epoll_event evt;
1507 int en = 0, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001508 uint32_t events = 0;
Milan Lenco0a47c992017-10-12 14:19:31 +02001509 uint64_t counter = 0;
1510 ssize_t r = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001511 memset (&evt, 0, sizeof (evt));
1512 evt.events = EPOLLIN | EPOLLOUT;
1513 sigset_t sigset;
1514 sigemptyset (&sigset);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001515 en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001516 if (en < 0)
1517 {
Milan Lenco0a47c992017-10-12 14:19:31 +02001518 err = errno;
1519 DBG ("epoll_pwait: %s", strerror (err));
1520 return memif_syscall_error_handler (err);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001521 }
1522 if (en > 0)
1523 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001524 if (evt.data.fd == lm->poll_cancel_fd)
1525 {
1526 r = read (evt.data.fd, &counter, sizeof (counter));
1527 if (r == -1)
1528 return MEMIF_ERR_DISCONNECTED;
1529
1530 return MEMIF_ERR_POLL_CANCEL;
1531 }
1532 if (evt.events & EPOLLIN)
1533 events |= MEMIF_FD_EVENT_READ;
1534 if (evt.events & EPOLLOUT)
1535 events |= MEMIF_FD_EVENT_WRITE;
1536 if (evt.events & EPOLLERR)
1537 events |= MEMIF_FD_EVENT_ERROR;
1538 err = memif_control_fd_handler (evt.data.fd, events);
1539 return err;
1540 }
1541 return 0;
1542}
1543
1544int
1545memif_per_thread_poll_event (memif_per_thread_main_handle_t pt_main,
1546 int timeout)
1547{
1548 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1549 struct epoll_event evt;
1550 int en = 0, err = MEMIF_ERR_SUCCESS; /* 0 */
1551 uint32_t events = 0;
1552 uint64_t counter = 0;
1553 ssize_t r = 0;
1554 memset (&evt, 0, sizeof (evt));
1555 evt.events = EPOLLIN | EPOLLOUT;
1556 sigset_t sigset;
1557 sigemptyset (&sigset);
1558 en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
1559 if (en < 0)
1560 {
1561 err = errno;
1562 DBG ("epoll_pwait: %s", strerror (err));
1563 return memif_syscall_error_handler (err);
1564 }
1565 if (en > 0)
1566 {
1567 if (evt.data.fd == lm->poll_cancel_fd)
Milan Lenco0a47c992017-10-12 14:19:31 +02001568 {
1569 r = read (evt.data.fd, &counter, sizeof (counter));
msardara8f554b72018-12-11 18:36:55 +01001570 if (r == -1)
1571 return MEMIF_ERR_DISCONNECTED;
1572
Milan Lenco0a47c992017-10-12 14:19:31 +02001573 return MEMIF_ERR_POLL_CANCEL;
1574 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001575 if (evt.events & EPOLLIN)
1576 events |= MEMIF_FD_EVENT_READ;
1577 if (evt.events & EPOLLOUT)
1578 events |= MEMIF_FD_EVENT_WRITE;
1579 if (evt.events & EPOLLERR)
1580 events |= MEMIF_FD_EVENT_ERROR;
1581 err = memif_control_fd_handler (evt.data.fd, events);
1582 return err;
1583 }
1584 return 0;
1585}
1586
Milan Lenco0a47c992017-10-12 14:19:31 +02001587int
1588memif_cancel_poll_event ()
1589{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001590 libmemif_main_t *lm = &libmemif_main;
Milan Lenco0a47c992017-10-12 14:19:31 +02001591 uint64_t counter = 1;
1592 ssize_t w = 0;
1593
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001594 if (lm->poll_cancel_fd == -1)
Milan Lenco0a47c992017-10-12 14:19:31 +02001595 return 0;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001596 w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
1597 if (w < sizeof (counter))
1598 return MEMIF_ERR_INT_WRITE;
1599
1600 return 0;
1601}
1602
1603int
1604memif_per_thread_cancel_poll_event (memif_per_thread_main_handle_t pt_main)
1605{
1606 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1607 uint64_t counter = 1;
1608 ssize_t w = 0;
1609
1610 if (lm == NULL)
1611 return MEMIF_ERR_INVAL_ARG;
1612
1613 if (lm->poll_cancel_fd == -1)
1614 return 0;
1615 w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
Milan Lenco0a47c992017-10-12 14:19:31 +02001616 if (w < sizeof (counter))
1617 return MEMIF_ERR_INT_WRITE;
1618
1619 return 0;
1620}
1621
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001622static void
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001623memif_msg_queue_free (libmemif_main_t * lm, memif_msg_queue_elt_t ** e)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001624{
1625 if (*e == NULL)
1626 return;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001627 memif_msg_queue_free (lm, &(*e)->next);
1628 lm->free (*e);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001629 *e = NULL;
1630 return;
1631}
1632
1633/* send disconnect msg and close interface */
1634int
1635memif_disconnect_internal (memif_connection_t * c)
1636{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001637 int err = MEMIF_ERR_SUCCESS, i; /* 0 */
1638 memif_queue_t *mq;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001639 libmemif_main_t *lm;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001640 memif_list_elt_t *e;
1641
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001642 if (c == NULL)
1643 {
1644 DBG ("no connection");
1645 return MEMIF_ERR_NOCONN;
1646 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001647
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001648 lm = get_libmemif_main (c->args.socket);
1649
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001650 c->on_disconnect ((void *) c, c->private_ctx);
1651
1652 if (c->fd > 0)
1653 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02001654 memif_msg_send_disconnect (c->fd, (uint8_t *) "interface deleted", 0);
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001655 lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001656 close (c->fd);
1657 }
1658 get_list_elt (&e, lm->control_list, lm->control_list_len, c->fd);
1659 if (e != NULL)
1660 {
1661 if (c->args.is_master)
1662 free_list_elt (lm->control_list, lm->control_list_len, c->fd);
1663 e->key = c->fd = -1;
1664 }
1665
1666 if (c->tx_queues != NULL)
1667 {
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001668 for (i = 0; i < c->tx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001669 {
1670 mq = &c->tx_queues[i];
1671 if (mq != NULL)
1672 {
1673 if (mq->int_fd > 0)
1674 close (mq->int_fd);
1675 free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1676 mq->int_fd);
1677 mq->int_fd = -1;
1678 }
1679 }
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001680 lm->free (c->tx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001681 c->tx_queues = NULL;
1682 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001683 c->tx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001684
1685 if (c->rx_queues != NULL)
1686 {
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001687 for (i = 0; i < c->rx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001688 {
1689 mq = &c->rx_queues[i];
1690 if (mq != NULL)
1691 {
1692 if (mq->int_fd > 0)
1693 {
1694 if (c->on_interrupt != NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001695 lm->control_fd_update (mq->int_fd, MEMIF_FD_EVENT_DEL,
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001696 lm->private_ctx);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001697 close (mq->int_fd);
1698 }
1699 free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1700 mq->int_fd);
1701 mq->int_fd = -1;
1702 }
1703 }
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001704 lm->free (c->rx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001705 c->rx_queues = NULL;
1706 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001707 c->rx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001708
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001709 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001710 {
Jakub Grajciar412e7b62018-09-27 10:26:35 +02001711 if (&c->regions[i] == NULL)
1712 continue;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001713 if (c->regions[i].is_external != 0)
1714 {
1715 lm->del_external_region (c->regions[i].addr,
1716 c->regions[i].region_size,
1717 c->regions[i].fd, c->private_ctx);
1718 }
1719 else
1720 {
1721 if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1722 return memif_syscall_error_handler (errno);
1723 if (c->regions[i].fd > 0)
1724 close (c->regions[i].fd);
1725 c->regions[i].fd = -1;
1726 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001727 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001728 lm->free (c->regions);
1729 c->regions = NULL;
1730 c->regions_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001731
1732 memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1733
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001734 memif_msg_queue_free (lm, &c->msg_queue);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001735
1736 if (!(c->args.is_master))
1737 {
1738 if (lm->disconn_slaves == 0)
1739 {
1740 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1741 {
1742 err = memif_syscall_error_handler (errno);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001743 DBG ("timerfd_settime: arm");
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001744 }
1745 }
1746 lm->disconn_slaves++;
1747 }
1748
1749 return err;
1750}
1751
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001752const char *
1753memif_get_socket_filename (memif_socket_handle_t sock)
1754{
1755 memif_socket_t *ms = (memif_socket_t *) sock;
1756
1757 if (ms == NULL)
1758 return NULL;
1759
1760 return (char *) ms->filename;
1761}
1762
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001763int
Jakub Grajciar12df4972019-07-01 14:24:48 +02001764memif_delete_socket (memif_socket_handle_t * sock)
1765{
1766 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001767 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001768
1769 /* check if socket is in use */
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001770 if (ms == NULL || ms->use_count > 0)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001771 return MEMIF_ERR_INVAL_ARG;
1772
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001773 lm = get_libmemif_main (ms);
1774
Jakub Grajciar12df4972019-07-01 14:24:48 +02001775 lm->free (ms->interface_list);
1776 ms->interface_list = NULL;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001777 lm->free (ms);
1778 *sock = ms = NULL;
1779
1780 return MEMIF_ERR_SUCCESS;
1781}
1782
1783int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001784memif_delete (memif_conn_handle_t * conn)
1785{
1786 memif_connection_t *c = (memif_connection_t *) * conn;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001787 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001788 memif_socket_t *ms = NULL;
1789 int err = MEMIF_ERR_SUCCESS;
1790
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001791 if (c == NULL)
1792 {
1793 DBG ("no connection");
1794 return MEMIF_ERR_NOCONN;
1795 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001796
1797 if (c->fd > 0)
1798 {
1799 DBG ("DISCONNECTING");
1800 err = memif_disconnect_internal (c);
1801 if (err == MEMIF_ERR_NOCONN)
1802 return err;
1803 }
1804
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001805 lm = get_libmemif_main (c->args.socket);
1806
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001807 free_list_elt_ctx (lm->control_list, lm->control_list_len, c);
1808
Jakub Grajciar12df4972019-07-01 14:24:48 +02001809 ms = (memif_socket_t *) c->args.socket;
1810 ms->use_count--;
1811 free_list_elt (ms->interface_list, ms->interface_list_len,
1812 c->args.interface_id);
1813 if (ms->use_count <= 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001814 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001815 /* stop listening on this socket */
1816 if (ms->type == MEMIF_SOCKET_TYPE_LISTENER)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001817 {
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001818 lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001819 free_list_elt (lm->socket_list, lm->socket_list_len, ms->fd);
1820 close (ms->fd);
1821 ms->fd = -1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001822 }
Jakub Grajciar12df4972019-07-01 14:24:48 +02001823 /* socket not in use */
1824 ms->type = MEMIF_SOCKET_TYPE_NONE;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001825 }
Jakub Grajciar12df4972019-07-01 14:24:48 +02001826
1827 if (!c->args.is_master)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001828 {
1829 lm->disconn_slaves--;
1830 if (lm->disconn_slaves <= 0)
1831 {
1832 if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1833 {
1834 err = memif_syscall_error_handler (errno);
1835 DBG ("timerfd_settime: disarm");
1836 }
1837 }
1838 }
1839
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001840 lm->free (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001841 c = NULL;
1842
1843 *conn = c;
1844 return err;
1845}
1846
1847int
1848memif_connect1 (memif_connection_t * c)
1849{
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001850 libmemif_main_t *lm;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001851 memif_region_t *mr;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001852 memif_queue_t *mq;
1853 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001854
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001855 if (c == NULL)
1856 return MEMIF_ERR_INVAL_ARG;
1857
1858 lm = get_libmemif_main (c->args.socket);
1859
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001860 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001861 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001862 mr = &c->regions[i];
1863 if (mr != NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001864 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001865 if (!mr->addr)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001866 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001867 if (mr->is_external)
1868 {
1869 if (lm->get_external_region_addr == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001870 return MEMIF_ERR_INVAL_ARG;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001871 mr->addr =
1872 lm->get_external_region_addr (mr->region_size, mr->fd,
1873 c->private_ctx);
1874 }
1875 else
1876 {
1877 if (mr->fd < 0)
1878 return MEMIF_ERR_NO_SHMFD;
1879
1880 if ((mr->addr =
1881 mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1882 MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
1883 {
1884 return memif_syscall_error_handler (errno);
1885 }
1886 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001887 }
1888 }
1889 }
1890
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001891 for (i = 0; i < c->rx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001892 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001893 mq = &c->rx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001894 if (mq != NULL)
1895 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001896 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001897 if (mq->ring->cookie != MEMIF_COOKIE)
1898 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001899 DBG ("wrong cookie on rx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001900 return MEMIF_ERR_COOKIE;
1901 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001902 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001903 }
1904 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001905
1906 for (i = 0; i < c->tx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001907 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001908 mq = &c->tx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001909 if (mq != NULL)
1910 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001911 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001912 if (mq->ring->cookie != MEMIF_COOKIE)
1913 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001914 DBG ("wrong cookie on tx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001915 return MEMIF_ERR_COOKIE;
1916 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001917 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001918 }
1919 }
1920
Jakub Grajciar12df4972019-07-01 14:24:48 +02001921 lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD,
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001922 lm->private_ctx);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001923
1924 return 0;
1925}
1926
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001927static inline int
1928memif_add_region (libmemif_main_t * lm, memif_connection_t * conn,
1929 uint8_t has_buffers)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001930{
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001931 memif_region_t *r;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001932
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001933 r =
1934 lm->realloc (conn->regions,
1935 sizeof (memif_region_t) * ++conn->regions_num);
1936 if (r == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001937 return MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001938
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001939 conn->regions = r;
1940 r = &conn->regions[conn->regions_num - 1];
1941 memset (r, 0, sizeof (memif_region_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001942
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001943 if (has_buffers != 0)
1944 {
1945 r->buffer_offset = 0;
1946 }
1947 else
1948 {
1949 r->buffer_offset =
1950 (conn->run_args.num_s2m_rings +
1951 conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1952 sizeof (memif_desc_t) *
Jakub Grajciar568cc462018-09-05 12:11:35 +02001953 (1 << conn->
1954 run_args.log2_ring_size));
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001955 }
1956
1957 r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001958 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1959 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1960
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001961 if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001962 return memif_syscall_error_handler (errno);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001963
1964 if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1965 return memif_syscall_error_handler (errno);
1966
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001967 if ((ftruncate (r->fd, r->region_size)) == -1)
1968 return memif_syscall_error_handler (errno);
1969
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001970 if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1971 MAP_SHARED, r->fd, 0)) == MAP_FAILED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001972 return memif_syscall_error_handler (errno);
1973
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001974 return MEMIF_ERR_SUCCESS;
1975}
1976
1977static inline int
1978memif_init_queues (libmemif_main_t * lm, memif_connection_t * conn)
1979{
1980 int i, j;
1981 memif_ring_t *ring;
1982
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001983 for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1984 {
1985 ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1986 DBG ("RING: %p I: %d", ring, i);
1987 ring->head = ring->tail = 0;
1988 ring->cookie = MEMIF_COOKIE;
1989 ring->flags = 0;
1990 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1991 {
1992 uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001993 ring->desc[j].region = 1;
1994 ring->desc[j].offset =
1995 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001996 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001997 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001998 }
1999 }
2000 for (i = 0; i < conn->run_args.num_m2s_rings; i++)
2001 {
2002 ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
2003 DBG ("RING: %p I: %d", ring, i);
2004 ring->head = ring->tail = 0;
2005 ring->cookie = MEMIF_COOKIE;
2006 ring->flags = 0;
2007 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
2008 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002009 uint16_t slot = (i + conn->run_args.num_s2m_rings) *
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002010 (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002011 ring->desc[j].region = 1;
2012 ring->desc[j].offset =
2013 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002014 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002015 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002016 }
2017 }
2018 memif_queue_t *mq;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002019 DBG ("alloc: %p", lm->alloc);
2020 DBG ("size: %lu", sizeof (memif_queue_t) * conn->run_args.num_s2m_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002021 mq =
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002022 (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2023 conn->run_args.num_s2m_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002024 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002025 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002026
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002027 int x;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002028 memif_list_elt_t e;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002029 for (x = 0; x < conn->run_args.num_s2m_rings; x++)
2030 {
2031 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2032 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002033 e.key = mq[x].int_fd;
2034 e.data_struct = conn;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002035 add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002036
2037 mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
2038 DBG ("RING: %p I: %d", mq[x].ring, x);
2039 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2040 mq[x].region = 0;
2041 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002042 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2043 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002044 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002045 }
2046 conn->tx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01002047 conn->tx_queues_num = conn->run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002048
2049 mq =
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002050 (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2051 conn->run_args.num_m2s_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002052 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002053 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002054
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002055 for (x = 0; x < conn->run_args.num_m2s_rings; x++)
2056 {
2057 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2058 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002059 e.key = mq[x].int_fd;
2060 e.data_struct = conn;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002061 add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002062
2063 mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
2064 DBG ("RING: %p I: %d", mq[x].ring, x);
2065 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2066 mq[x].region = 0;
2067 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002068 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2069 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002070 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002071 }
2072 conn->rx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01002073 conn->rx_queues_num = conn->run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002074
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002075 return MEMIF_ERR_SUCCESS;
2076}
2077
2078int
2079memif_init_regions_and_queues (memif_connection_t * conn)
2080{
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002081 memif_region_t *r;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002082 libmemif_main_t *lm;
2083
2084 if (conn == NULL)
2085 return MEMIF_ERR_INVAL_ARG;
2086
2087 lm = get_libmemif_main (conn->args.socket);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002088
2089 /* region 0. rings */
2090 memif_add_region (lm, conn, /* has_buffers */ 0);
2091
2092 /* region 1. buffers */
2093 if (lm->add_external_region)
2094 {
2095 r =
2096 (memif_region_t *) lm->realloc (conn->regions,
2097 sizeof (memif_region_t) *
2098 ++conn->regions_num);
2099 if (r == NULL)
2100 return MEMIF_ERR_NOMEM;
2101 conn->regions = r;
2102
2103 conn->regions[1].region_size =
2104 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
2105 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
2106 conn->regions[1].buffer_offset = 0;
2107 lm->add_external_region (&conn->regions[1].addr,
2108 conn->regions[1].region_size,
2109 &conn->regions[1].fd, conn->private_ctx);
2110 conn->regions[1].is_external = 1;
2111 }
2112 else
2113 {
2114 memif_add_region (lm, conn, 1);
2115 }
2116
2117 memif_init_queues (lm, conn);
2118
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002119 return 0;
2120}
2121
Jakub Grajciar47e68de2021-01-08 15:32:43 +01002122int
2123memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
2124 memif_buffer_t *buf)
2125{
2126 memif_connection_t *c = (memif_connection_t *) conn;
2127 if (EXPECT_FALSE (c == NULL))
2128 return MEMIF_ERR_NOCONN;
2129 if (EXPECT_FALSE (qid >= c->tx_queues_num))
2130 return MEMIF_ERR_QID;
2131 if (EXPECT_FALSE (buf == NULL))
2132 return MEMIF_ERR_INVAL_ARG;
2133
2134 uint16_t ring_size, ns;
2135 memif_queue_t *mq = &c->tx_queues[qid];
2136 memif_ring_t *ring = mq->ring;
2137
2138 ring_size = (1 << mq->log2_ring_size);
2139 if (c->args.is_master)
2140 ns = ring->head - mq->next_buf;
2141 else
2142 ns = ring_size - mq->next_buf + ring->tail;
2143
2144 if ((mq->next_buf - buf->desc_index) > ns)
2145 return MEMIF_ERR_INVAL_ARG;
2146
2147 mq->next_buf = buf->desc_index;
2148
2149 return MEMIF_ERR_SUCCESS;
2150}
2151
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002152static void
2153memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
2154 memif_buffer_t *buf, uint16_t slot)
2155{
2156 uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
2157 uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
2158 memif_desc_t *from_d, *to_d, tmp_d;
2159
2160 /* Get the descriptors */
2161 from_d = &from_q->ring->desc[buf->desc_index & from_mask];
2162 to_d = &to_q->ring->desc[slot & to_mask];
2163
2164 /* Swap descriptors */
2165 tmp_d = *from_d;
2166 *from_d = *to_d;
2167 *to_d = tmp_d;
2168
2169 /* Update descriptor index and queue for clients buffer */
2170 buf->desc_index = slot;
2171 buf->queue = to_q;
2172}
2173
2174int
2175memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
2176 memif_buffer_t *buf_b)
2177{
2178 memif_connection_t *c = (memif_connection_t *) conn;
2179 if (EXPECT_FALSE (c == NULL))
2180 return MEMIF_ERR_NOCONN;
2181 if (EXPECT_FALSE (c->args.is_master))
2182 return MEMIF_ERR_INVAL_ARG;
2183 if ((buf_a == NULL) || (buf_b == NULL))
2184 return MEMIF_ERR_INVAL_ARG;
2185
2186 int err;
2187 /* store buf_a information */
2188 uint16_t index_a = buf_a->desc_index;
2189 memif_queue_t *mq_a = buf_a->queue;
2190
2191 /* swap buffers, buf_a was updated with new desc_index and queue */
2192 memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
2193 (memif_queue_t *) buf_b->queue, buf_a,
2194 buf_b->desc_index);
2195
2196 /* update buf_b desc_index and queue */
2197 buf_b->desc_index = index_a;
2198 buf_b->queue = mq_a;
2199
2200 return MEMIF_ERR_SUCCESS;
2201}
2202
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002203int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002204memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
2205 memif_buffer_t * bufs, uint16_t count,
2206 uint16_t * count_out)
2207{
2208 memif_connection_t *c = (memif_connection_t *) conn;
2209 if (EXPECT_FALSE (c == NULL))
2210 return MEMIF_ERR_NOCONN;
2211 if (EXPECT_FALSE (c->fd < 0))
2212 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002213 if (EXPECT_FALSE (qid >= c->tx_queues_num))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002214 return MEMIF_ERR_QID;
2215 if (EXPECT_FALSE (!count_out))
2216 return MEMIF_ERR_INVAL_ARG;
2217 if (EXPECT_FALSE (c->args.is_master))
2218 return MEMIF_ERR_INVAL_ARG;
2219
2220 memif_queue_t *mq = &c->tx_queues[qid];
2221 memif_ring_t *ring = mq->ring;
2222 memif_buffer_t *b0;
2223 uint16_t mask = (1 << mq->log2_ring_size) - 1;
2224 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002225 uint16_t ns;
2226 memif_queue_t *bmq;
msardara8f554b72018-12-11 18:36:55 +01002227 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002228 *count_out = 0;
2229
2230 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002231
2232 /* can only be called by slave */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002233 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002234
2235 b0 = bufs;
2236
2237 while (count && ns)
2238 {
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002239 /* Swaps the descriptors, updates next_buf pointer and updates client
2240 * memif buffer */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002241
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002242 memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
2243 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002244
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002245 mq->next_buf++; /* mark the buffer as allocated */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002246 count--;
2247 ns--;
2248 b0++;
2249 *count_out += 1;
2250 }
2251
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002252 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2253 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002254
2255 if (count)
2256 {
2257 DBG ("ring buffer full! qid: %u", qid);
2258 err = MEMIF_ERR_NOBUF_RING;
2259 }
2260
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002261 return err;
2262}
2263
2264int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002265memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
2266 memif_buffer_t * bufs, uint16_t count,
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002267 uint16_t * count_out, uint16_t size)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002268{
2269 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002270 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002271 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002272 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002273 return MEMIF_ERR_DISCONNECTED;
2274 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002275 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2276 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002277 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002278 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002279 if (EXPECT_FALSE (!count_out))
2280 return MEMIF_ERR_INVAL_ARG;
2281
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002282 libmemif_main_t *lm = get_libmemif_main (c->args.socket);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002283 memif_queue_t *mq = &c->tx_queues[qid];
2284 memif_ring_t *ring = mq->ring;
msardara8f554b72018-12-11 18:36:55 +01002285 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002286 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002287 uint32_t offset_mask = c->run_args.buffer_size - 1;
Chun Li5dca5462018-02-07 09:51:35 +08002288 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002289 uint16_t ns;
msardara8f554b72018-12-11 18:36:55 +01002290 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002291 uint16_t dst_left, src_left;
2292 uint16_t saved_count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002293 uint16_t saved_next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002294 memif_buffer_t *saved_b;
2295 *count_out = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002296
Chun Li5dca5462018-02-07 09:51:35 +08002297 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002298
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002299 if (c->args.is_master)
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002300 ns = ring->head - mq->next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002301 else
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002302 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar04b68bd2017-10-30 10:34:54 +01002303
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002304 while (count && ns)
2305 {
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002306 b0 = (bufs + *count_out);
2307
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002308 saved_b = b0;
2309 saved_count = count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002310 saved_next_buf = mq->next_buf;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002311
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002312 b0->desc_index = mq->next_buf;
2313 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002314
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002315 /* slave can produce buffer with original length */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002316 dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
2317 c->run_args.buffer_size;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002318 src_left = size;
2319
2320 while (src_left)
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002321 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002322 if (EXPECT_FALSE (dst_left == 0))
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002323 {
2324 if (count && ns)
2325 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002326 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002327 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002328 ns--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002329
2330 ring->desc[b0->desc_index & mask].flags |=
2331 MEMIF_DESC_FLAG_NEXT;
2332 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
2333
2334 b0 = (bufs + *count_out);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002335 b0->desc_index = mq->next_buf;
2336 dst_left = (c->args.is_master) ?
2337 ring->desc[mq->next_buf & mask].length :
2338 c->run_args.buffer_size;
2339 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002340 }
2341 else
2342 {
2343 /* rollback allocated chain buffers */
2344 memset (saved_b, 0, sizeof (memif_buffer_t)
2345 * (saved_count - count + 1));
2346 *count_out -= saved_count - count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002347 mq->next_buf = saved_next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002348 goto no_ns;
2349 }
2350 }
2351 b0->len = memif_min (dst_left, src_left);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002352
2353 /* slave resets buffer offset */
2354 if (c->args.is_master == 0)
2355 {
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002356 memif_desc_t *d = &ring->desc[mq->next_buf & mask];
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002357 if (lm->get_external_buffer_offset)
2358 d->offset = lm->get_external_buffer_offset (c->private_ctx);
2359 else
2360 d->offset = d->offset - (d->offset & offset_mask);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002361 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002362 b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002363
2364 src_left -= b0->len;
2365 dst_left -= b0->len;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002366 }
2367
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002368 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002369 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002370 ns--;
2371 count--;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002372 }
2373
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002374no_ns:
2375
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002376 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2377 mq->next_buf);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002378
2379 if (count)
2380 {
2381 DBG ("ring buffer full! qid: %u", qid);
2382 err = MEMIF_ERR_NOBUF_RING;
2383 }
2384
2385 return err;
2386}
2387
2388int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002389memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
2390 uint16_t headroom)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002391{
2392 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002393 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002394 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002395 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002396 return MEMIF_ERR_DISCONNECTED;
2397 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002398 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2399 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002400 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002401 return MEMIF_ERR_QID;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002402 libmemif_main_t *lm = get_libmemif_main (c->args.socket);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002403 memif_queue_t *mq = &c->rx_queues[qid];
2404 memif_ring_t *ring = mq->ring;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002405 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002406 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002407 uint16_t slot, counter = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002408
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002409 if (c->args.is_master)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002410 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002411 MEMIF_MEMORY_BARRIER ();
2412 ring->tail =
2413 (ring->tail + count <=
2414 mq->last_head) ? ring->tail + count : mq->last_head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002415 return MEMIF_ERR_SUCCESS;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002416 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002417
2418 uint16_t head = ring->head;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002419 slot = head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002420 uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002421 count = (count < ns) ? count : ns;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002422
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002423 memif_desc_t *d;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002424 while (counter < count)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002425 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002426 d = &ring->desc[slot & mask];
2427 d->region = 1;
2428 d->length = c->run_args.buffer_size - headroom;
2429 if (lm->get_external_buffer_offset)
2430 d->offset = lm->get_external_buffer_offset (c->private_ctx);
2431 else
2432 d->offset = d->offset - (d->offset & offset_mask) + headroom;
2433 slot++;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002434 counter++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002435 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002436
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002437 MEMIF_MEMORY_BARRIER ();
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002438 ring->head = slot;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002439
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002440 return MEMIF_ERR_SUCCESS; /* 0 */
2441}
2442
2443int
2444memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
2445 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
2446{
2447 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002448 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002449 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002450 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002451 return MEMIF_ERR_DISCONNECTED;
2452 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002453 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2454 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002455 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002456 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002457 if (EXPECT_FALSE (!tx))
2458 return MEMIF_ERR_INVAL_ARG;
2459
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002460 memif_queue_t *mq = &c->tx_queues[qid];
2461 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002462 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar14217482021-01-14 13:23:48 +01002463 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002464 memif_buffer_t *b0;
Jakub Grajciar14217482021-01-14 13:23:48 +01002465 memif_desc_t *d;
2466 int64_t data_offset;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002467 *tx = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002468 int err = MEMIF_ERR_SUCCESS;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002469
2470 if (EXPECT_FALSE (count == 0))
2471 return MEMIF_ERR_SUCCESS;
2472
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002473 uint16_t index;
2474 if (c->args.is_master)
2475 index = ring->tail;
2476 else
2477 index = ring->head;
2478
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002479 while (count)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002480 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002481 b0 = (bufs + *tx);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002482 /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
2483 */
2484 if ((b0->desc_index & mask) != (index & mask))
2485 {
2486 err = MEMIF_ERR_INVAL_ARG;
2487 goto done;
2488 }
Jakub Grajciar14217482021-01-14 13:23:48 +01002489 d = &ring->desc[b0->desc_index & mask];
2490 d->length = b0->len;
2491 if (!c->args.is_master)
2492 {
2493 // reset headroom
2494 d->offset = d->offset - (d->offset & offset_mask);
2495 // calculate offset from user data
2496 data_offset = b0->data - (d->offset + c->regions[d->region].addr);
2497 if (data_offset != 0)
2498 {
2499 /* verify data offset */
2500 if ((data_offset < 0) ||
2501 (data_offset > (d->offset + offset_mask)))
2502 {
2503 printf ("%ld\n", data_offset);
2504 err = MEMIF_ERR_INVAL_ARG;
2505 goto done;
2506 }
2507 d->offset += data_offset;
2508 }
2509 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002510
2511#ifdef MEMIF_DBG_SHM
2512 printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
2513 printf ("data: %p\n",
2514 memif_get_buffer (c, ring, b0->desc_index & mask));
2515 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002516 print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
2517 ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002518#endif /* MEMIF_DBG_SHM */
2519
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002520 *tx += 1;
2521 count--;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002522 index++;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002523 }
2524
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002525done:
Milan Lenco0a47c992017-10-12 14:19:31 +02002526 MEMIF_MEMORY_BARRIER ();
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002527 if (c->args.is_master)
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002528 ring->tail = b0->desc_index + 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002529 else
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002530 ring->head = b0->desc_index + 1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002531
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002532 if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
2533 {
2534 uint64_t a = 1;
2535 int r = write (mq->int_fd, &a, sizeof (a));
2536 if (r < 0)
2537 return MEMIF_ERR_INT_WRITE;
2538 }
2539
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002540 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002541}
2542
2543int
2544memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
2545 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
2546{
2547 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002548 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002549 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002550 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002551 return MEMIF_ERR_DISCONNECTED;
2552 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002553 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2554 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002555 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002556 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002557 if (EXPECT_FALSE (!rx))
2558 return MEMIF_ERR_INVAL_ARG;
2559
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002560 memif_queue_t *mq = &c->rx_queues[qid];
2561 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002562 uint16_t cur_slot, last_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002563 uint16_t ns;
2564 uint16_t mask = (1 << mq->log2_ring_size) - 1;
msardara8f554b72018-12-11 18:36:55 +01002565 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002566 *rx = 0;
2567
2568 uint64_t b;
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01002569 ssize_t r;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002570
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002571 cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
2572 last_slot = (c->args.is_master) ? ring->head : ring->tail;
2573 if (cur_slot == last_slot)
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01002574 {
2575 r = read (mq->int_fd, &b, sizeof (b));
2576 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2577 return memif_syscall_error_handler (errno);
2578
2579 return MEMIF_ERR_SUCCESS;
2580 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002581
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002582 ns = last_slot - cur_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002583
2584 while (ns && count)
2585 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002586 b0 = (bufs + *rx);
2587
2588 b0->desc_index = cur_slot;
2589 b0->data = memif_get_buffer (c, ring, cur_slot & mask);
2590 b0->len = ring->desc[cur_slot & mask].length;
2591 /* slave resets buffer length */
2592 if (c->args.is_master == 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002593 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002594 ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002595 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002596
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002597 if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
2598 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002599 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002600 ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
2601 }
Jakub Grajciar14217482021-01-14 13:23:48 +01002602
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002603 b0->queue = mq;
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02002604#ifdef MEMIF_DBG_SHM
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002605 printf ("data: %p\n", b0->data);
2606 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002607 printf ("queue: %p\n", b0->queue);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002608 print_bytes (b0->data, b0->len, DBG_RX_BUF);
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02002609#endif /* MEMIF_DBG_SHM */
2610 ns--;
2611 *rx += 1;
2612
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002613 count--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002614 cur_slot++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002615 }
2616
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002617 if (c->args.is_master)
2618 mq->last_head = cur_slot;
2619 else
2620 mq->last_tail = cur_slot;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002621
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002622 if (ns)
2623 {
2624 DBG ("not enough buffers!");
2625 return MEMIF_ERR_NOBUF;
2626 }
2627
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01002628 r = read (mq->int_fd, &b, sizeof (b));
2629 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2630 return memif_syscall_error_handler (errno);
2631
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002632 return MEMIF_ERR_SUCCESS; /* 0 */
2633}
2634
2635int
2636memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
2637 char *buf, ssize_t buflen)
2638{
2639 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002640 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002641 memif_socket_t *ms;
2642 int err = MEMIF_ERR_SUCCESS, i;
2643 ssize_t l0 = 0, l1;
2644
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002645 if (c == NULL)
2646 return MEMIF_ERR_NOCONN;
2647
Jakub Grajciar12df4972019-07-01 14:24:48 +02002648 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002649 lm = get_libmemif_main (ms);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002650
2651 l1 = strlen ((char *) c->args.interface_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002652 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002653 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002654 md->if_name =
2655 (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002656 l0 += l1 + 1;
2657 }
2658 else
2659 err = MEMIF_ERR_NOBUF_DET;
2660
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002661 l1 = strlen ((char *) lm->app_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002662 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002663 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02002664 md->inst_name = (uint8_t *) strcpy (buf + l0, (char *) lm->app_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002665 l0 += l1 + 1;
2666 }
2667 else
2668 err = MEMIF_ERR_NOBUF_DET;
2669
2670 l1 = strlen ((char *) c->remote_if_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002671 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002672 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002673 md->remote_if_name =
2674 (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002675 l0 += l1 + 1;
2676 }
2677 else
2678 err = MEMIF_ERR_NOBUF_DET;
2679
2680 l1 = strlen ((char *) c->remote_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002681 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002682 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002683 md->remote_inst_name =
2684 (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002685 l0 += l1 + 1;
2686 }
2687 else
2688 err = MEMIF_ERR_NOBUF_DET;
2689
2690 md->id = c->args.interface_id;
2691
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002692 if (strlen ((char *) c->args.secret) > 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002693 {
2694 l1 = strlen ((char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02002695 if (l0 + l1 < buflen)
2696 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02002697 md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02002698 l0 += l1 + 1;
2699 }
2700 else
2701 err = MEMIF_ERR_NOBUF_DET;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002702 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002703
2704 md->role = (c->args.is_master) ? 0 : 1;
2705 md->mode = c->args.mode;
2706
Jakub Grajciar12df4972019-07-01 14:24:48 +02002707 l1 = strlen ((char *) ms->filename);
Milan Lenco0a47c992017-10-12 14:19:31 +02002708 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002709 {
2710 md->socket_filename =
Jakub Grajciar12df4972019-07-01 14:24:48 +02002711 (uint8_t *) strcpy (buf + l0, (char *) ms->filename);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002712 l0 += l1 + 1;
2713 }
2714 else
2715 err = MEMIF_ERR_NOBUF_DET;
2716
Jakub Grajciar568cc462018-09-05 12:11:35 +02002717 l1 = strlen ((char *) c->remote_disconnect_string);
2718 if (l0 + l1 < buflen)
2719 {
2720 md->error =
2721 (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
2722 l0 += l1 + 1;
2723 }
2724 else
2725 err = MEMIF_ERR_NOBUF_DET;
2726
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002727 md->regions_num = c->regions_num;
2728 l1 = sizeof (memif_region_details_t) * md->regions_num;
2729 if (l0 + l1 <= buflen)
2730 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002731 md->regions = (memif_region_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002732 for (i = 0; i < md->regions_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002733 {
2734 md->regions[i].index = i;
2735 md->regions[i].addr = c->regions[i].addr;
2736 md->regions[i].size = c->regions[i].region_size;
2737 md->regions[i].fd = c->regions[i].fd;
2738 md->regions[i].is_external = c->regions[i].is_external;
2739 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002740 l0 += l1;
2741 }
2742 else
2743 err = MEMIF_ERR_NOBUF_DET;
2744
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002745 md->rx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002746 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2747 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002748
2749 l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2750 if (l0 + l1 <= buflen)
2751 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002752 md->rx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002753 for (i = 0; i < md->rx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002754 {
2755 md->rx_queues[i].region = c->rx_queues[i].region;
2756 md->rx_queues[i].qid = i;
2757 md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2758 md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2759 md->rx_queues[i].head = c->rx_queues[i].ring->head;
2760 md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2761 md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2762 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002763 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002764 }
2765 else
2766 err = MEMIF_ERR_NOBUF_DET;
2767
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002768 md->tx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002769 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2770 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002771
2772 l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2773 if (l0 + l1 <= buflen)
2774 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002775 md->tx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002776 for (i = 0; i < md->tx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002777 {
2778 md->tx_queues[i].region = c->tx_queues[i].region;
2779 md->tx_queues[i].qid = i;
2780 md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2781 md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2782 md->tx_queues[i].head = c->tx_queues[i].ring->head;
2783 md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2784 md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2785 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002786 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002787 }
2788 else
2789 err = MEMIF_ERR_NOBUF_DET;
2790
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002791 md->link_up_down = (c->fd > 0) ? 1 : 0;
2792
2793 return err; /* 0 */
2794}
2795
2796int
2797memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2798{
2799 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002800 uint8_t num;
2801
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002802 *efd = -1;
2803 if (c == NULL)
2804 return MEMIF_ERR_NOCONN;
2805 if (c->fd < 0)
2806 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002807
2808 num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002809 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2810 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002811 if (qid >= num)
2812 return MEMIF_ERR_QID;
2813
2814 *efd = c->rx_queues[qid].int_fd;
2815
2816 return MEMIF_ERR_SUCCESS;
2817}
2818
2819int
2820memif_cleanup ()
2821{
2822 libmemif_main_t *lm = &libmemif_main;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002823 int err;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002824
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002825 err = memif_delete_socket ((memif_socket_handle_t *) & lm->default_socket);
2826 if (err != MEMIF_ERR_SUCCESS)
2827 return err;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002828
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002829 if (lm->control_list)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002830 lm->free (lm->control_list);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002831 lm->control_list = NULL;
2832 if (lm->interrupt_list)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002833 lm->free (lm->interrupt_list);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002834 lm->interrupt_list = NULL;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002835 if (lm->socket_list)
2836 lm->free (lm->socket_list);
2837 lm->socket_list = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002838 if (lm->pending_list)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002839 lm->free (lm->pending_list);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002840 lm->pending_list = NULL;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002841 if (lm->poll_cancel_fd != -1)
2842 close (lm->poll_cancel_fd);
2843
2844 return MEMIF_ERR_SUCCESS; /* 0 */
2845}
2846
2847int
2848memif_per_thread_cleanup (memif_per_thread_main_handle_t * pt_main)
2849{
2850 libmemif_main_t *lm = (libmemif_main_t *) * pt_main;
2851
2852 if (lm == NULL)
2853 return MEMIF_ERR_INVAL_ARG;
2854
2855 /* No default socket in case of per thread */
2856
2857 if (lm->control_list)
2858 lm->free (lm->control_list);
2859 lm->control_list = NULL;
2860 if (lm->interrupt_list)
2861 lm->free (lm->interrupt_list);
2862 lm->interrupt_list = NULL;
2863 if (lm->socket_list)
2864 lm->free (lm->socket_list);
2865 lm->socket_list = NULL;
2866 if (lm->pending_list)
2867 lm->free (lm->pending_list);
2868 lm->pending_list = NULL;
2869 if (lm->poll_cancel_fd != -1)
2870 close (lm->poll_cancel_fd);
2871
2872 lm->free (lm);
2873
2874 *pt_main = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002875
2876 return MEMIF_ERR_SUCCESS; /* 0 */
2877}