blob: 1eb6929137e3ec6827b23917f4f86ac4fb652aaf [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 */
951 ms->filename = lm->alloc (strlen (filename) + sizeof (char));
952 if (ms->filename == NULL)
953 {
954 err = MEMIF_ERR_NOMEM;
955 goto error;
956 }
957 memset (ms->filename, 0, strlen (filename) + sizeof (char));
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000958 strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
Jakub Grajciar12df4972019-07-01 14:24:48 +0200959
960 ms->type = MEMIF_SOCKET_TYPE_NONE;
961
962 ms->interface_list_len = 1;
963 ms->interface_list =
964 lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
965 if (ms->interface_list == NULL)
966 {
967 err = MEMIF_ERR_NOMEM;
968 goto error;
969 }
970 ms->interface_list[0].key = -1;
971 ms->interface_list[0].data_struct = NULL;
972
973 *sock = ms;
974
975 return err;
976
977error:
978 if (ms != NULL)
979 {
980 if (ms->filename != NULL)
981 {
982 lm->free (ms->filename);
983 ms->filename = NULL;
984 }
985 if (ms->fd > 0)
986 {
987 close (ms->fd);
988 ms->fd = -1;
989 }
990 if (ms->interface_list != NULL)
991 {
992 lm->free (ms->interface_list);
993 ms->interface_list = NULL;
994 ms->interface_list_len = 0;
995 }
996 lm->free (ms);
997 *sock = ms = NULL;
998 }
999 return err;
1000}
1001
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001002int
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001003memif_per_thread_create_socket (memif_per_thread_main_handle_t pt_main,
1004 memif_socket_handle_t * sock,
1005 const char *filename, void *private_ctx)
1006{
1007 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1008 memif_socket_t *ms = (memif_socket_t *) * sock;
1009 int i, err = MEMIF_ERR_SUCCESS;
1010
1011 if (lm == NULL)
1012 return MEMIF_ERR_INVAL_ARG;
1013
1014 for (i = 0; i < lm->socket_list_len; i++)
1015 {
1016 if ((ms = (memif_socket_t *) lm->socket_list[i].data_struct) != NULL)
1017 {
1018 if (strncmp ((char *) ms->filename, filename,
1019 strlen ((char *) ms->filename)) == 0)
1020 return MEMIF_ERR_INVAL_ARG;
1021 }
1022 }
1023
1024 /* allocate memif_socket_t */
1025 ms = NULL;
1026 ms = lm->alloc (sizeof (memif_socket_t));
1027 if (ms == NULL)
1028 {
1029 err = MEMIF_ERR_NOMEM;
1030 goto error;
1031 }
1032 memset (ms, 0, sizeof (memif_socket_t));
1033 ms->lm = lm;
1034 /* set filename */
1035 ms->filename = lm->alloc (strlen (filename) + sizeof (char));
1036 if (ms->filename == NULL)
1037 {
1038 err = MEMIF_ERR_NOMEM;
1039 goto error;
1040 }
1041 memset (ms->filename, 0, strlen (filename) + sizeof (char));
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001042 strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001043
1044 ms->type = MEMIF_SOCKET_TYPE_NONE;
1045
1046 ms->interface_list_len = 1;
1047 ms->interface_list =
1048 lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
1049 if (ms->interface_list == NULL)
1050 {
1051 err = MEMIF_ERR_NOMEM;
1052 goto error;
1053 }
1054 ms->interface_list[0].key = -1;
1055 ms->interface_list[0].data_struct = NULL;
1056
1057 *sock = ms;
1058
1059 return err;
1060
1061error:
1062 if (ms != NULL)
1063 {
1064 if (ms->filename != NULL)
1065 {
1066 lm->free (ms->filename);
1067 ms->filename = NULL;
1068 }
1069 if (ms->fd > 0)
1070 {
1071 close (ms->fd);
1072 ms->fd = -1;
1073 }
1074 if (ms->interface_list != NULL)
1075 {
1076 lm->free (ms->interface_list);
1077 ms->interface_list = NULL;
1078 ms->interface_list_len = 0;
1079 }
1080 lm->free (ms);
1081 *sock = ms = NULL;
1082 }
1083 return err;
1084}
1085
1086int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001087memif_create (memif_conn_handle_t * c, memif_conn_args_t * args,
1088 memif_connection_update_t * on_connect,
1089 memif_connection_update_t * on_disconnect,
1090 memif_interrupt_t * on_interrupt, void *private_ctx)
1091{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001092 libmemif_main_t *lm = get_libmemif_main (args->socket);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001093 int err, index = 0;
1094 memif_list_elt_t elt;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001095 memif_connection_t *conn = (memif_connection_t *) * c;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001096 memif_socket_t *ms;
1097
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001098 if (conn != NULL)
1099 {
1100 DBG ("This handle already points to existing memif.");
1101 return MEMIF_ERR_CONN;
1102 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001103
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001104 conn = (memif_connection_t *) lm->alloc (sizeof (memif_connection_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001105 if (conn == NULL)
1106 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001107 err = MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001108 goto error;
1109 }
1110 memset (conn, 0, sizeof (memif_connection_t));
1111
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001112 conn->args.interface_id = args->interface_id;
1113
1114 if (args->log2_ring_size == 0)
1115 args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
Damjan Marion6d56fa42017-11-03 12:24:37 +01001116 else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
1117 {
1118 err = MEMIF_ERR_MAX_RING;
1119 goto error;
1120 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001121 if (args->buffer_size == 0)
1122 args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
1123 if (args->num_s2m_rings == 0)
1124 args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
1125 if (args->num_m2s_rings == 0)
1126 args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
1127
1128 conn->args.num_s2m_rings = args->num_s2m_rings;
1129 conn->args.num_m2s_rings = args->num_m2s_rings;
1130 conn->args.buffer_size = args->buffer_size;
1131 conn->args.log2_ring_size = args->log2_ring_size;
1132 conn->args.is_master = args->is_master;
1133 conn->args.mode = args->mode;
1134 conn->msg_queue = NULL;
1135 conn->regions = NULL;
1136 conn->tx_queues = NULL;
1137 conn->rx_queues = NULL;
1138 conn->fd = -1;
1139 conn->on_connect = on_connect;
1140 conn->on_disconnect = on_disconnect;
1141 conn->on_interrupt = on_interrupt;
1142 conn->private_ctx = private_ctx;
1143 memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
1144
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001145 strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
1146 sizeof (conn->args.interface_name));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001147
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001148 if ((strlen ((char *) args->secret)) > 0)
1149 strlcpy ((char *) conn->args.secret, (char *) args->secret,
1150 sizeof (conn->args.secret));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001151
Jakub Grajciar12df4972019-07-01 14:24:48 +02001152 if (args->socket != NULL)
1153 conn->args.socket = args->socket;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001154 else if (lm->default_socket != NULL)
1155 conn->args.socket = lm->default_socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001156 else
1157 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001158 err = MEMIF_ERR_INVAL_ARG;
1159 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001160 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001161
Jakub Grajciar12df4972019-07-01 14:24:48 +02001162 ms = (memif_socket_t *) conn->args.socket;
1163
1164 if ((conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_CLIENT) ||
1165 (!conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_LISTENER))
1166 {
1167 err = MEMIF_ERR_INVAL_ARG;
1168 goto error;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001169 }
1170
Jakub Grajciar12df4972019-07-01 14:24:48 +02001171 elt.key = conn->args.interface_id;
1172 elt.data_struct = conn;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001173 add_list_elt (lm, &elt, &ms->interface_list, &ms->interface_list_len);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001174 ms->use_count++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001175
1176 if (conn->args.is_master)
1177 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001178 if (ms->type == MEMIF_SOCKET_TYPE_NONE)
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001179 {
1180 err = memif_socket_start_listening (ms);
1181 if (err != MEMIF_ERR_SUCCESS)
1182 goto error;
1183 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001184 }
1185 else
1186 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001187 elt.key = -1;
1188 elt.data_struct = conn;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001189 if ((index =
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001190 add_list_elt (lm, &elt, &lm->control_list,
1191 &lm->control_list_len)) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001192 {
1193 err = MEMIF_ERR_NOMEM;
1194 goto error;
1195 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001196
Jakub Grajciar84b83772019-03-04 12:42:19 +01001197 conn->index = index;
1198
Paul Vinciguerraf4fbfd62020-05-15 23:13:36 -04001199 /* try connecting to master */
Jakub Grajciar12df4972019-07-01 14:24:48 +02001200 err = memif_request_connection (conn);
Jakub Grajciar272e2e42019-07-24 10:33:11 +02001201 if ((err != MEMIF_ERR_SUCCESS) && (lm->disconn_slaves == 0))
Jakub Grajciar84b83772019-03-04 12:42:19 +01001202 {
1203 /* connection failed, arm reconnect timer (if not armed) */
1204 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1205 {
1206 err = memif_syscall_error_handler (errno);
1207 goto error;
1208 }
1209 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001210 lm->disconn_slaves++;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001211 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001212
Jakub Grajciar12df4972019-07-01 14:24:48 +02001213 *c = conn;
1214
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001215 return 0;
1216
1217error:
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001218 if (conn != NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001219 lm->free (conn);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001220 *c = conn = NULL;
1221 return err;
1222}
1223
1224int
Jakub Grajciar12df4972019-07-01 14:24:48 +02001225memif_request_connection (memif_conn_handle_t c)
Jakub Grajciar84b83772019-03-04 12:42:19 +01001226{
Jakub Grajciar84b83772019-03-04 12:42:19 +01001227 memif_connection_t *conn = (memif_connection_t *) c;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001228 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001229 memif_socket_t *ms;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001230 int err = MEMIF_ERR_SUCCESS;
1231 int sockfd = -1;
1232 struct sockaddr_un sun;
1233
Jakub Grajciar12df4972019-07-01 14:24:48 +02001234 if (conn == NULL)
1235 return MEMIF_ERR_NOCONN;
1236
1237 ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001238 lm = get_libmemif_main (ms);
1239
Jakub Grajciar12df4972019-07-01 14:24:48 +02001240
1241 if (conn->args.is_master || ms->type == MEMIF_SOCKET_TYPE_LISTENER)
Jakub Grajciar84b83772019-03-04 12:42:19 +01001242 return MEMIF_ERR_INVAL_ARG;
1243 if (conn->fd > 0)
1244 return MEMIF_ERR_ALRCONN;
1245
1246 sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
1247 if (sockfd < 0)
1248 {
1249 err = memif_syscall_error_handler (errno);
1250 goto error;
1251 }
1252
1253 sun.sun_family = AF_UNIX;
1254
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +00001255 strlcpy (sun.sun_path, (char *) ms->filename, sizeof (sun.sun_path));
Jakub Grajciar84b83772019-03-04 12:42:19 +01001256
1257 if (connect (sockfd, (struct sockaddr *) &sun,
Jakub Grajciar12df4972019-07-01 14:24:48 +02001258 sizeof (struct sockaddr_un)) == 0)
Jakub Grajciar84b83772019-03-04 12:42:19 +01001259 {
1260 conn->fd = sockfd;
1261 conn->read_fn = memif_conn_fd_read_ready;
1262 conn->write_fn = memif_conn_fd_write_ready;
1263 conn->error_fn = memif_conn_fd_error;
1264
1265 lm->control_list[conn->index].key = conn->fd;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001266 lm->control_fd_update (sockfd,
Jakub Grajciar12df4972019-07-01 14:24:48 +02001267 MEMIF_FD_EVENT_READ |
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001268 MEMIF_FD_EVENT_WRITE, lm->private_ctx);
Jakub Grajciar84b83772019-03-04 12:42:19 +01001269
1270 lm->disconn_slaves--;
1271 if (lm->disconn_slaves == 0)
1272 {
1273 if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1274 {
1275 err = memif_syscall_error_handler (errno);
1276 return err;
1277 }
1278 }
1279 }
1280 else
1281 {
Jakub Grajciar272e2e42019-07-24 10:33:11 +02001282 err = memif_syscall_error_handler (errno);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001283 strcpy ((char *) conn->remote_disconnect_string, memif_strerror (err));
Jakub Grajciar84b83772019-03-04 12:42:19 +01001284 goto error;
1285 }
1286
Jakub Grajciar12df4972019-07-01 14:24:48 +02001287 ms->type = MEMIF_SOCKET_TYPE_CLIENT;
1288
1289 return err;
Jakub Grajciar84b83772019-03-04 12:42:19 +01001290
1291error:
1292 if (sockfd > 0)
1293 close (sockfd);
1294 sockfd = -1;
1295 return err;
1296}
1297
1298int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001299memif_control_fd_handler (int fd, uint8_t events)
1300{
Jakub Grajciar84b83772019-03-04 12:42:19 +01001301 int i, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001302 uint16_t num;
1303 memif_list_elt_t *e = NULL;
1304 memif_connection_t *conn;
1305 libmemif_main_t *lm = &libmemif_main;
1306 if (fd == lm->timerfd)
1307 {
1308 uint64_t b;
1309 ssize_t size;
1310 size = read (fd, &b, sizeof (b));
msardara8f554b72018-12-11 18:36:55 +01001311
1312 if (size == -1)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001313 goto error;
msardara8f554b72018-12-11 18:36:55 +01001314
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001315 for (i = 0; i < lm->control_list_len; i++)
1316 {
1317 if ((lm->control_list[i].key < 0)
1318 && (lm->control_list[i].data_struct != NULL))
1319 {
1320 conn = lm->control_list[i].data_struct;
1321 if (conn->args.is_master)
1322 continue;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001323 err = memif_request_connection (conn);
1324 if (err != MEMIF_ERR_SUCCESS)
1325 DBG ("memif_request_connection: %s", memif_strerror (err));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001326 }
1327 }
1328 }
1329 else
1330 {
1331 get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1332 if (e != NULL)
1333 {
1334 if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1335 {
1336 num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001337 (((memif_connection_t *) e->data_struct)->
1338 args.is_master) ? ((memif_connection_t *) e->
1339 data_struct)->run_args.
1340 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1341 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001342 for (i = 0; i < num; i++)
1343 {
Jakub Grajciar568cc462018-09-05 12:11:35 +02001344 if (((memif_connection_t *) e->data_struct)->
1345 rx_queues[i].int_fd == fd)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001346 {
Jakub Grajciar568cc462018-09-05 12:11:35 +02001347 ((memif_connection_t *) e->data_struct)->
1348 on_interrupt ((void *) e->data_struct,
1349 ((memif_connection_t *) e->
1350 data_struct)->private_ctx, i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001351 return MEMIF_ERR_SUCCESS;
1352 }
1353 }
1354 }
1355 return MEMIF_ERR_SUCCESS;
1356 }
Jakub Grajciar12df4972019-07-01 14:24:48 +02001357 get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1358 if (e != NULL
1359 && ((memif_socket_t *) e->data_struct)->type ==
1360 MEMIF_SOCKET_TYPE_LISTENER)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001361 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001362 err =
1363 memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
Jakub Grajciar84b83772019-03-04 12:42:19 +01001364 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001365 }
1366
1367 get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1368 if (e != NULL)
1369 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001370 err = memif_read_ready (lm, fd);
1371 return err;
1372 }
1373
1374 get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1375 if (e != NULL)
1376 {
1377 if (events & MEMIF_FD_EVENT_READ)
1378 {
1379 err =
1380 ((memif_connection_t *) e->data_struct)->
1381 read_fn (e->data_struct);
1382 if (err != MEMIF_ERR_SUCCESS)
1383 return err;
1384 }
1385 if (events & MEMIF_FD_EVENT_WRITE)
1386 {
1387 err =
1388 ((memif_connection_t *) e->data_struct)->
1389 write_fn (e->data_struct);
1390 if (err != MEMIF_ERR_SUCCESS)
1391 return err;
1392 }
1393 if (events & MEMIF_FD_EVENT_ERROR)
1394 {
1395 err =
1396 ((memif_connection_t *) e->data_struct)->
1397 error_fn (e->data_struct);
1398 if (err != MEMIF_ERR_SUCCESS)
1399 return err;
1400 }
1401 }
1402 }
1403
1404 return MEMIF_ERR_SUCCESS; /* 0 */
1405
1406error:
1407 return err;
1408}
1409
1410int
1411memif_per_thread_control_fd_handler (memif_per_thread_main_handle_t pt_main,
1412 int fd, uint8_t events)
1413{
1414 int i, err = MEMIF_ERR_SUCCESS; /* 0 */
1415 uint16_t num;
1416 memif_list_elt_t *e = NULL;
1417 memif_connection_t *conn;
1418 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1419
1420 if (fd == lm->timerfd)
1421 {
1422 uint64_t b;
1423 ssize_t size;
1424 size = read (fd, &b, sizeof (b));
1425
1426 if (size == -1)
1427 goto error;
1428
1429 for (i = 0; i < lm->control_list_len; i++)
1430 {
1431 if ((lm->control_list[i].key < 0)
1432 && (lm->control_list[i].data_struct != NULL))
1433 {
1434 conn = lm->control_list[i].data_struct;
1435 if (conn->args.is_master)
1436 continue;
1437 err = memif_request_connection (conn);
1438 if (err != MEMIF_ERR_SUCCESS)
1439 DBG ("memif_request_connection: %s", memif_strerror (err));
1440 }
1441 }
1442 }
1443 else
1444 {
1445 get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1446 if (e != NULL)
1447 {
1448 if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1449 {
1450 num =
1451 (((memif_connection_t *) e->data_struct)->
1452 args.is_master) ? ((memif_connection_t *) e->
1453 data_struct)->run_args.
1454 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1455 run_args.num_m2s_rings;
1456 for (i = 0; i < num; i++)
1457 {
1458 if (((memif_connection_t *) e->data_struct)->
1459 rx_queues[i].int_fd == fd)
1460 {
1461 ((memif_connection_t *) e->data_struct)->
1462 on_interrupt ((void *) e->data_struct,
1463 ((memif_connection_t *) e->
1464 data_struct)->private_ctx, i);
1465 return MEMIF_ERR_SUCCESS;
1466 }
1467 }
1468 }
1469 return MEMIF_ERR_SUCCESS;
1470 }
1471 get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1472 if (e != NULL
1473 && ((memif_socket_t *) e->data_struct)->type ==
1474 MEMIF_SOCKET_TYPE_LISTENER)
1475 {
1476 err =
1477 memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
1478 return err;
1479 }
1480
1481 get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1482 if (e != NULL)
1483 {
1484 err = memif_read_ready (lm, fd);
Jakub Grajciar84b83772019-03-04 12:42:19 +01001485 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001486 }
1487
1488 get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1489 if (e != NULL)
1490 {
1491 if (events & MEMIF_FD_EVENT_READ)
1492 {
1493 err =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001494 ((memif_connection_t *) e->data_struct)->
1495 read_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001496 if (err != MEMIF_ERR_SUCCESS)
1497 return err;
1498 }
1499 if (events & MEMIF_FD_EVENT_WRITE)
1500 {
1501 err =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001502 ((memif_connection_t *) e->data_struct)->
1503 write_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001504 if (err != MEMIF_ERR_SUCCESS)
1505 return err;
1506 }
1507 if (events & MEMIF_FD_EVENT_ERROR)
1508 {
1509 err =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001510 ((memif_connection_t *) e->data_struct)->
1511 error_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001512 if (err != MEMIF_ERR_SUCCESS)
1513 return err;
1514 }
1515 }
1516 }
1517
1518 return MEMIF_ERR_SUCCESS; /* 0 */
1519
1520error:
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001521 return err;
1522}
1523
1524int
1525memif_poll_event (int timeout)
1526{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001527 libmemif_main_t *lm = &libmemif_main;
msardara8f554b72018-12-11 18:36:55 +01001528 struct epoll_event evt;
1529 int en = 0, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001530 uint32_t events = 0;
Milan Lenco0a47c992017-10-12 14:19:31 +02001531 uint64_t counter = 0;
1532 ssize_t r = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001533 memset (&evt, 0, sizeof (evt));
1534 evt.events = EPOLLIN | EPOLLOUT;
1535 sigset_t sigset;
1536 sigemptyset (&sigset);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001537 en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001538 if (en < 0)
1539 {
Milan Lenco0a47c992017-10-12 14:19:31 +02001540 err = errno;
1541 DBG ("epoll_pwait: %s", strerror (err));
1542 return memif_syscall_error_handler (err);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001543 }
1544 if (en > 0)
1545 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001546 if (evt.data.fd == lm->poll_cancel_fd)
1547 {
1548 r = read (evt.data.fd, &counter, sizeof (counter));
1549 if (r == -1)
1550 return MEMIF_ERR_DISCONNECTED;
1551
1552 return MEMIF_ERR_POLL_CANCEL;
1553 }
1554 if (evt.events & EPOLLIN)
1555 events |= MEMIF_FD_EVENT_READ;
1556 if (evt.events & EPOLLOUT)
1557 events |= MEMIF_FD_EVENT_WRITE;
1558 if (evt.events & EPOLLERR)
1559 events |= MEMIF_FD_EVENT_ERROR;
1560 err = memif_control_fd_handler (evt.data.fd, events);
1561 return err;
1562 }
1563 return 0;
1564}
1565
1566int
1567memif_per_thread_poll_event (memif_per_thread_main_handle_t pt_main,
1568 int timeout)
1569{
1570 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1571 struct epoll_event evt;
1572 int en = 0, err = MEMIF_ERR_SUCCESS; /* 0 */
1573 uint32_t events = 0;
1574 uint64_t counter = 0;
1575 ssize_t r = 0;
1576 memset (&evt, 0, sizeof (evt));
1577 evt.events = EPOLLIN | EPOLLOUT;
1578 sigset_t sigset;
1579 sigemptyset (&sigset);
1580 en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
1581 if (en < 0)
1582 {
1583 err = errno;
1584 DBG ("epoll_pwait: %s", strerror (err));
1585 return memif_syscall_error_handler (err);
1586 }
1587 if (en > 0)
1588 {
1589 if (evt.data.fd == lm->poll_cancel_fd)
Milan Lenco0a47c992017-10-12 14:19:31 +02001590 {
1591 r = read (evt.data.fd, &counter, sizeof (counter));
msardara8f554b72018-12-11 18:36:55 +01001592 if (r == -1)
1593 return MEMIF_ERR_DISCONNECTED;
1594
Milan Lenco0a47c992017-10-12 14:19:31 +02001595 return MEMIF_ERR_POLL_CANCEL;
1596 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001597 if (evt.events & EPOLLIN)
1598 events |= MEMIF_FD_EVENT_READ;
1599 if (evt.events & EPOLLOUT)
1600 events |= MEMIF_FD_EVENT_WRITE;
1601 if (evt.events & EPOLLERR)
1602 events |= MEMIF_FD_EVENT_ERROR;
1603 err = memif_control_fd_handler (evt.data.fd, events);
1604 return err;
1605 }
1606 return 0;
1607}
1608
Milan Lenco0a47c992017-10-12 14:19:31 +02001609int
1610memif_cancel_poll_event ()
1611{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001612 libmemif_main_t *lm = &libmemif_main;
Milan Lenco0a47c992017-10-12 14:19:31 +02001613 uint64_t counter = 1;
1614 ssize_t w = 0;
1615
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001616 if (lm->poll_cancel_fd == -1)
Milan Lenco0a47c992017-10-12 14:19:31 +02001617 return 0;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001618 w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
1619 if (w < sizeof (counter))
1620 return MEMIF_ERR_INT_WRITE;
1621
1622 return 0;
1623}
1624
1625int
1626memif_per_thread_cancel_poll_event (memif_per_thread_main_handle_t pt_main)
1627{
1628 libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1629 uint64_t counter = 1;
1630 ssize_t w = 0;
1631
1632 if (lm == NULL)
1633 return MEMIF_ERR_INVAL_ARG;
1634
1635 if (lm->poll_cancel_fd == -1)
1636 return 0;
1637 w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
Milan Lenco0a47c992017-10-12 14:19:31 +02001638 if (w < sizeof (counter))
1639 return MEMIF_ERR_INT_WRITE;
1640
1641 return 0;
1642}
1643
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001644static void
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001645memif_msg_queue_free (libmemif_main_t * lm, memif_msg_queue_elt_t ** e)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001646{
1647 if (*e == NULL)
1648 return;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001649 memif_msg_queue_free (lm, &(*e)->next);
1650 lm->free (*e);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001651 *e = NULL;
1652 return;
1653}
1654
1655/* send disconnect msg and close interface */
1656int
1657memif_disconnect_internal (memif_connection_t * c)
1658{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001659 int err = MEMIF_ERR_SUCCESS, i; /* 0 */
1660 memif_queue_t *mq;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001661 libmemif_main_t *lm;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001662 memif_list_elt_t *e;
1663
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001664 if (c == NULL)
1665 {
1666 DBG ("no connection");
1667 return MEMIF_ERR_NOCONN;
1668 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001669
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001670 lm = get_libmemif_main (c->args.socket);
1671
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001672 c->on_disconnect ((void *) c, c->private_ctx);
1673
1674 if (c->fd > 0)
1675 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02001676 memif_msg_send_disconnect (c->fd, (uint8_t *) "interface deleted", 0);
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001677 lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001678 close (c->fd);
1679 }
1680 get_list_elt (&e, lm->control_list, lm->control_list_len, c->fd);
1681 if (e != NULL)
1682 {
1683 if (c->args.is_master)
1684 free_list_elt (lm->control_list, lm->control_list_len, c->fd);
1685 e->key = c->fd = -1;
1686 }
1687
1688 if (c->tx_queues != NULL)
1689 {
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001690 for (i = 0; i < c->tx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001691 {
1692 mq = &c->tx_queues[i];
1693 if (mq != NULL)
1694 {
1695 if (mq->int_fd > 0)
1696 close (mq->int_fd);
1697 free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1698 mq->int_fd);
1699 mq->int_fd = -1;
1700 }
1701 }
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001702 lm->free (c->tx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001703 c->tx_queues = NULL;
1704 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001705 c->tx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001706
1707 if (c->rx_queues != NULL)
1708 {
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001709 for (i = 0; i < c->rx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001710 {
1711 mq = &c->rx_queues[i];
1712 if (mq != NULL)
1713 {
1714 if (mq->int_fd > 0)
1715 {
1716 if (c->on_interrupt != NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001717 lm->control_fd_update (mq->int_fd, MEMIF_FD_EVENT_DEL,
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001718 lm->private_ctx);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001719 close (mq->int_fd);
1720 }
1721 free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1722 mq->int_fd);
1723 mq->int_fd = -1;
1724 }
1725 }
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001726 lm->free (c->rx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001727 c->rx_queues = NULL;
1728 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001729 c->rx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001730
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001731 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001732 {
Jakub Grajciar412e7b62018-09-27 10:26:35 +02001733 if (&c->regions[i] == NULL)
1734 continue;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001735 if (c->regions[i].is_external != 0)
1736 {
1737 lm->del_external_region (c->regions[i].addr,
1738 c->regions[i].region_size,
1739 c->regions[i].fd, c->private_ctx);
1740 }
1741 else
1742 {
1743 if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1744 return memif_syscall_error_handler (errno);
1745 if (c->regions[i].fd > 0)
1746 close (c->regions[i].fd);
1747 c->regions[i].fd = -1;
1748 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001749 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001750 lm->free (c->regions);
1751 c->regions = NULL;
1752 c->regions_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001753
1754 memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1755
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001756 memif_msg_queue_free (lm, &c->msg_queue);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001757
1758 if (!(c->args.is_master))
1759 {
1760 if (lm->disconn_slaves == 0)
1761 {
1762 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1763 {
1764 err = memif_syscall_error_handler (errno);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001765 DBG ("timerfd_settime: arm");
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001766 }
1767 }
1768 lm->disconn_slaves++;
1769 }
1770
1771 return err;
1772}
1773
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001774const char *
1775memif_get_socket_filename (memif_socket_handle_t sock)
1776{
1777 memif_socket_t *ms = (memif_socket_t *) sock;
1778
1779 if (ms == NULL)
1780 return NULL;
1781
1782 return (char *) ms->filename;
1783}
1784
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001785int
Jakub Grajciar12df4972019-07-01 14:24:48 +02001786memif_delete_socket (memif_socket_handle_t * sock)
1787{
1788 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001789 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001790
1791 /* check if socket is in use */
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001792 if (ms == NULL || ms->use_count > 0)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001793 return MEMIF_ERR_INVAL_ARG;
1794
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001795 lm = get_libmemif_main (ms);
1796
Jakub Grajciar12df4972019-07-01 14:24:48 +02001797 lm->free (ms->interface_list);
1798 ms->interface_list = NULL;
1799 lm->free (ms->filename);
1800 ms->filename = NULL;
1801 lm->free (ms);
1802 *sock = ms = NULL;
1803
1804 return MEMIF_ERR_SUCCESS;
1805}
1806
1807int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001808memif_delete (memif_conn_handle_t * conn)
1809{
1810 memif_connection_t *c = (memif_connection_t *) * conn;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001811 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001812 memif_socket_t *ms = NULL;
1813 int err = MEMIF_ERR_SUCCESS;
1814
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001815 if (c == NULL)
1816 {
1817 DBG ("no connection");
1818 return MEMIF_ERR_NOCONN;
1819 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001820
1821 if (c->fd > 0)
1822 {
1823 DBG ("DISCONNECTING");
1824 err = memif_disconnect_internal (c);
1825 if (err == MEMIF_ERR_NOCONN)
1826 return err;
1827 }
1828
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001829 lm = get_libmemif_main (c->args.socket);
1830
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001831 free_list_elt_ctx (lm->control_list, lm->control_list_len, c);
1832
Jakub Grajciar12df4972019-07-01 14:24:48 +02001833 ms = (memif_socket_t *) c->args.socket;
1834 ms->use_count--;
1835 free_list_elt (ms->interface_list, ms->interface_list_len,
1836 c->args.interface_id);
1837 if (ms->use_count <= 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001838 {
Jakub Grajciar12df4972019-07-01 14:24:48 +02001839 /* stop listening on this socket */
1840 if (ms->type == MEMIF_SOCKET_TYPE_LISTENER)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001841 {
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001842 lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001843 free_list_elt (lm->socket_list, lm->socket_list_len, ms->fd);
1844 close (ms->fd);
1845 ms->fd = -1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001846 }
Jakub Grajciar12df4972019-07-01 14:24:48 +02001847 /* socket not in use */
1848 ms->type = MEMIF_SOCKET_TYPE_NONE;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001849 }
Jakub Grajciar12df4972019-07-01 14:24:48 +02001850
1851 if (!c->args.is_master)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001852 {
1853 lm->disconn_slaves--;
1854 if (lm->disconn_slaves <= 0)
1855 {
1856 if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1857 {
1858 err = memif_syscall_error_handler (errno);
1859 DBG ("timerfd_settime: disarm");
1860 }
1861 }
1862 }
1863
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001864 lm->free (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001865 c = NULL;
1866
1867 *conn = c;
1868 return err;
1869}
1870
1871int
1872memif_connect1 (memif_connection_t * c)
1873{
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001874 libmemif_main_t *lm;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001875 memif_region_t *mr;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001876 memif_queue_t *mq;
1877 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001878
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001879 if (c == NULL)
1880 return MEMIF_ERR_INVAL_ARG;
1881
1882 lm = get_libmemif_main (c->args.socket);
1883
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001884 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001885 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001886 mr = &c->regions[i];
1887 if (mr != NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001888 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001889 if (!mr->addr)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001890 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001891 if (mr->is_external)
1892 {
1893 if (lm->get_external_region_addr == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001894 return MEMIF_ERR_INVAL_ARG;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001895 mr->addr =
1896 lm->get_external_region_addr (mr->region_size, mr->fd,
1897 c->private_ctx);
1898 }
1899 else
1900 {
1901 if (mr->fd < 0)
1902 return MEMIF_ERR_NO_SHMFD;
1903
1904 if ((mr->addr =
1905 mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1906 MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
1907 {
1908 return memif_syscall_error_handler (errno);
1909 }
1910 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001911 }
1912 }
1913 }
1914
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001915 for (i = 0; i < c->rx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001916 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001917 mq = &c->rx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001918 if (mq != NULL)
1919 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001920 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001921 if (mq->ring->cookie != MEMIF_COOKIE)
1922 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001923 DBG ("wrong cookie on rx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001924 return MEMIF_ERR_COOKIE;
1925 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001926 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001927 }
1928 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001929
1930 for (i = 0; i < c->tx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001931 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001932 mq = &c->tx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001933 if (mq != NULL)
1934 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001935 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001936 if (mq->ring->cookie != MEMIF_COOKIE)
1937 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001938 DBG ("wrong cookie on tx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001939 return MEMIF_ERR_COOKIE;
1940 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001941 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001942 }
1943 }
1944
Jakub Grajciar12df4972019-07-01 14:24:48 +02001945 lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD,
Jakub Grajciar6f090fa2019-11-14 10:47:25 +01001946 lm->private_ctx);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001947
1948 return 0;
1949}
1950
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001951static inline int
1952memif_add_region (libmemif_main_t * lm, memif_connection_t * conn,
1953 uint8_t has_buffers)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001954{
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001955 memif_region_t *r;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001956
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001957 r =
1958 lm->realloc (conn->regions,
1959 sizeof (memif_region_t) * ++conn->regions_num);
1960 if (r == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001961 return MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001962
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001963 conn->regions = r;
1964 r = &conn->regions[conn->regions_num - 1];
1965 memset (r, 0, sizeof (memif_region_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001966
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001967 if (has_buffers != 0)
1968 {
1969 r->buffer_offset = 0;
1970 }
1971 else
1972 {
1973 r->buffer_offset =
1974 (conn->run_args.num_s2m_rings +
1975 conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1976 sizeof (memif_desc_t) *
Jakub Grajciar568cc462018-09-05 12:11:35 +02001977 (1 << conn->
1978 run_args.log2_ring_size));
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001979 }
1980
1981 r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001982 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1983 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1984
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001985 if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001986 return memif_syscall_error_handler (errno);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001987
1988 if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1989 return memif_syscall_error_handler (errno);
1990
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001991 if ((ftruncate (r->fd, r->region_size)) == -1)
1992 return memif_syscall_error_handler (errno);
1993
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001994 if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1995 MAP_SHARED, r->fd, 0)) == MAP_FAILED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001996 return memif_syscall_error_handler (errno);
1997
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001998 return MEMIF_ERR_SUCCESS;
1999}
2000
2001static inline int
2002memif_init_queues (libmemif_main_t * lm, memif_connection_t * conn)
2003{
2004 int i, j;
2005 memif_ring_t *ring;
2006
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002007 for (i = 0; i < conn->run_args.num_s2m_rings; i++)
2008 {
2009 ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
2010 DBG ("RING: %p I: %d", ring, i);
2011 ring->head = ring->tail = 0;
2012 ring->cookie = MEMIF_COOKIE;
2013 ring->flags = 0;
2014 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
2015 {
2016 uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002017 ring->desc[j].region = 1;
2018 ring->desc[j].offset =
2019 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002020 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002021 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002022 }
2023 }
2024 for (i = 0; i < conn->run_args.num_m2s_rings; i++)
2025 {
2026 ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
2027 DBG ("RING: %p I: %d", ring, i);
2028 ring->head = ring->tail = 0;
2029 ring->cookie = MEMIF_COOKIE;
2030 ring->flags = 0;
2031 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
2032 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002033 uint16_t slot = (i + conn->run_args.num_s2m_rings) *
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002034 (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002035 ring->desc[j].region = 1;
2036 ring->desc[j].offset =
2037 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002038 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002039 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002040 }
2041 }
2042 memif_queue_t *mq;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002043 DBG ("alloc: %p", lm->alloc);
2044 DBG ("size: %lu", sizeof (memif_queue_t) * conn->run_args.num_s2m_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002045 mq =
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002046 (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2047 conn->run_args.num_s2m_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002048 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002049 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002050
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002051 int x;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002052 memif_list_elt_t e;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002053 for (x = 0; x < conn->run_args.num_s2m_rings; x++)
2054 {
2055 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2056 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002057 e.key = mq[x].int_fd;
2058 e.data_struct = conn;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002059 add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002060
2061 mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
2062 DBG ("RING: %p I: %d", mq[x].ring, x);
2063 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2064 mq[x].region = 0;
2065 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002066 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2067 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002068 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002069 }
2070 conn->tx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01002071 conn->tx_queues_num = conn->run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002072
2073 mq =
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002074 (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2075 conn->run_args.num_m2s_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002076 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002077 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002078
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002079 for (x = 0; x < conn->run_args.num_m2s_rings; x++)
2080 {
2081 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2082 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002083 e.key = mq[x].int_fd;
2084 e.data_struct = conn;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002085 add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002086
2087 mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
2088 DBG ("RING: %p I: %d", mq[x].ring, x);
2089 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2090 mq[x].region = 0;
2091 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002092 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2093 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002094 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002095 }
2096 conn->rx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01002097 conn->rx_queues_num = conn->run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002098
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002099 return MEMIF_ERR_SUCCESS;
2100}
2101
2102int
2103memif_init_regions_and_queues (memif_connection_t * conn)
2104{
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002105 memif_region_t *r;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002106 libmemif_main_t *lm;
2107
2108 if (conn == NULL)
2109 return MEMIF_ERR_INVAL_ARG;
2110
2111 lm = get_libmemif_main (conn->args.socket);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002112
2113 /* region 0. rings */
2114 memif_add_region (lm, conn, /* has_buffers */ 0);
2115
2116 /* region 1. buffers */
2117 if (lm->add_external_region)
2118 {
2119 r =
2120 (memif_region_t *) lm->realloc (conn->regions,
2121 sizeof (memif_region_t) *
2122 ++conn->regions_num);
2123 if (r == NULL)
2124 return MEMIF_ERR_NOMEM;
2125 conn->regions = r;
2126
2127 conn->regions[1].region_size =
2128 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
2129 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
2130 conn->regions[1].buffer_offset = 0;
2131 lm->add_external_region (&conn->regions[1].addr,
2132 conn->regions[1].region_size,
2133 &conn->regions[1].fd, conn->private_ctx);
2134 conn->regions[1].is_external = 1;
2135 }
2136 else
2137 {
2138 memif_add_region (lm, conn, 1);
2139 }
2140
2141 memif_init_queues (lm, conn);
2142
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002143 return 0;
2144}
2145
Jakub Grajciar47e68de2021-01-08 15:32:43 +01002146int
2147memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
2148 memif_buffer_t *buf)
2149{
2150 memif_connection_t *c = (memif_connection_t *) conn;
2151 if (EXPECT_FALSE (c == NULL))
2152 return MEMIF_ERR_NOCONN;
2153 if (EXPECT_FALSE (qid >= c->tx_queues_num))
2154 return MEMIF_ERR_QID;
2155 if (EXPECT_FALSE (buf == NULL))
2156 return MEMIF_ERR_INVAL_ARG;
2157
2158 uint16_t ring_size, ns;
2159 memif_queue_t *mq = &c->tx_queues[qid];
2160 memif_ring_t *ring = mq->ring;
2161
2162 ring_size = (1 << mq->log2_ring_size);
2163 if (c->args.is_master)
2164 ns = ring->head - mq->next_buf;
2165 else
2166 ns = ring_size - mq->next_buf + ring->tail;
2167
2168 if ((mq->next_buf - buf->desc_index) > ns)
2169 return MEMIF_ERR_INVAL_ARG;
2170
2171 mq->next_buf = buf->desc_index;
2172
2173 return MEMIF_ERR_SUCCESS;
2174}
2175
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002176static void
2177memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
2178 memif_buffer_t *buf, uint16_t slot)
2179{
2180 uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
2181 uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
2182 memif_desc_t *from_d, *to_d, tmp_d;
2183
2184 /* Get the descriptors */
2185 from_d = &from_q->ring->desc[buf->desc_index & from_mask];
2186 to_d = &to_q->ring->desc[slot & to_mask];
2187
2188 /* Swap descriptors */
2189 tmp_d = *from_d;
2190 *from_d = *to_d;
2191 *to_d = tmp_d;
2192
2193 /* Update descriptor index and queue for clients buffer */
2194 buf->desc_index = slot;
2195 buf->queue = to_q;
2196}
2197
2198int
2199memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
2200 memif_buffer_t *buf_b)
2201{
2202 memif_connection_t *c = (memif_connection_t *) conn;
2203 if (EXPECT_FALSE (c == NULL))
2204 return MEMIF_ERR_NOCONN;
2205 if (EXPECT_FALSE (c->args.is_master))
2206 return MEMIF_ERR_INVAL_ARG;
2207 if ((buf_a == NULL) || (buf_b == NULL))
2208 return MEMIF_ERR_INVAL_ARG;
2209
2210 int err;
2211 /* store buf_a information */
2212 uint16_t index_a = buf_a->desc_index;
2213 memif_queue_t *mq_a = buf_a->queue;
2214
2215 /* swap buffers, buf_a was updated with new desc_index and queue */
2216 memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
2217 (memif_queue_t *) buf_b->queue, buf_a,
2218 buf_b->desc_index);
2219
2220 /* update buf_b desc_index and queue */
2221 buf_b->desc_index = index_a;
2222 buf_b->queue = mq_a;
2223
2224 return MEMIF_ERR_SUCCESS;
2225}
2226
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002227int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002228memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
2229 memif_buffer_t * bufs, uint16_t count,
2230 uint16_t * count_out)
2231{
2232 memif_connection_t *c = (memif_connection_t *) conn;
2233 if (EXPECT_FALSE (c == NULL))
2234 return MEMIF_ERR_NOCONN;
2235 if (EXPECT_FALSE (c->fd < 0))
2236 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002237 if (EXPECT_FALSE (qid >= c->tx_queues_num))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002238 return MEMIF_ERR_QID;
2239 if (EXPECT_FALSE (!count_out))
2240 return MEMIF_ERR_INVAL_ARG;
2241 if (EXPECT_FALSE (c->args.is_master))
2242 return MEMIF_ERR_INVAL_ARG;
2243
2244 memif_queue_t *mq = &c->tx_queues[qid];
2245 memif_ring_t *ring = mq->ring;
2246 memif_buffer_t *b0;
2247 uint16_t mask = (1 << mq->log2_ring_size) - 1;
2248 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002249 uint16_t ns;
2250 memif_queue_t *bmq;
msardara8f554b72018-12-11 18:36:55 +01002251 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002252 *count_out = 0;
2253
2254 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002255
2256 /* can only be called by slave */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002257 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002258
2259 b0 = bufs;
2260
2261 while (count && ns)
2262 {
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002263 /* Swaps the descriptors, updates next_buf pointer and updates client
2264 * memif buffer */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002265
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002266 memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
2267 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002268
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002269 mq->next_buf++; /* mark the buffer as allocated */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002270 count--;
2271 ns--;
2272 b0++;
2273 *count_out += 1;
2274 }
2275
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002276 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2277 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002278
2279 if (count)
2280 {
2281 DBG ("ring buffer full! qid: %u", qid);
2282 err = MEMIF_ERR_NOBUF_RING;
2283 }
2284
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002285 return err;
2286}
2287
2288int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002289memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
2290 memif_buffer_t * bufs, uint16_t count,
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002291 uint16_t * count_out, uint16_t size)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002292{
2293 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002294 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002295 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002296 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002297 return MEMIF_ERR_DISCONNECTED;
2298 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002299 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2300 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002301 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002302 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002303 if (EXPECT_FALSE (!count_out))
2304 return MEMIF_ERR_INVAL_ARG;
2305
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002306 libmemif_main_t *lm = get_libmemif_main (c->args.socket);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002307 memif_queue_t *mq = &c->tx_queues[qid];
2308 memif_ring_t *ring = mq->ring;
msardara8f554b72018-12-11 18:36:55 +01002309 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002310 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002311 uint32_t offset_mask = c->run_args.buffer_size - 1;
Chun Li5dca5462018-02-07 09:51:35 +08002312 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002313 uint16_t ns;
msardara8f554b72018-12-11 18:36:55 +01002314 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002315 uint16_t dst_left, src_left;
2316 uint16_t saved_count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002317 uint16_t saved_next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002318 memif_buffer_t *saved_b;
2319 *count_out = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002320
Chun Li5dca5462018-02-07 09:51:35 +08002321 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002322
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002323 if (c->args.is_master)
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002324 ns = ring->head - mq->next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002325 else
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002326 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar04b68bd2017-10-30 10:34:54 +01002327
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002328 while (count && ns)
2329 {
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002330 b0 = (bufs + *count_out);
2331
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002332 saved_b = b0;
2333 saved_count = count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002334 saved_next_buf = mq->next_buf;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002335
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002336 b0->desc_index = mq->next_buf;
2337 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002338
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002339 /* slave can produce buffer with original length */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002340 dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
2341 c->run_args.buffer_size;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002342 src_left = size;
2343
2344 while (src_left)
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002345 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002346 if (EXPECT_FALSE (dst_left == 0))
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002347 {
2348 if (count && ns)
2349 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002350 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002351 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002352 ns--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002353
2354 ring->desc[b0->desc_index & mask].flags |=
2355 MEMIF_DESC_FLAG_NEXT;
2356 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
2357
2358 b0 = (bufs + *count_out);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002359 b0->desc_index = mq->next_buf;
2360 dst_left = (c->args.is_master) ?
2361 ring->desc[mq->next_buf & mask].length :
2362 c->run_args.buffer_size;
2363 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002364 }
2365 else
2366 {
2367 /* rollback allocated chain buffers */
2368 memset (saved_b, 0, sizeof (memif_buffer_t)
2369 * (saved_count - count + 1));
2370 *count_out -= saved_count - count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002371 mq->next_buf = saved_next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002372 goto no_ns;
2373 }
2374 }
2375 b0->len = memif_min (dst_left, src_left);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002376
2377 /* slave resets buffer offset */
2378 if (c->args.is_master == 0)
2379 {
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002380 memif_desc_t *d = &ring->desc[mq->next_buf & mask];
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002381 if (lm->get_external_buffer_offset)
2382 d->offset = lm->get_external_buffer_offset (c->private_ctx);
2383 else
2384 d->offset = d->offset - (d->offset & offset_mask);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002385 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002386 b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002387
2388 src_left -= b0->len;
2389 dst_left -= b0->len;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002390 }
2391
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002392 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002393 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002394 ns--;
2395 count--;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002396 }
2397
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002398no_ns:
2399
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002400 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2401 mq->next_buf);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002402
2403 if (count)
2404 {
2405 DBG ("ring buffer full! qid: %u", qid);
2406 err = MEMIF_ERR_NOBUF_RING;
2407 }
2408
2409 return err;
2410}
2411
2412int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002413memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
2414 uint16_t headroom)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002415{
2416 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002417 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002418 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002419 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002420 return MEMIF_ERR_DISCONNECTED;
2421 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002422 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2423 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002424 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002425 return MEMIF_ERR_QID;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002426 libmemif_main_t *lm = get_libmemif_main (c->args.socket);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002427 memif_queue_t *mq = &c->rx_queues[qid];
2428 memif_ring_t *ring = mq->ring;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002429 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002430 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002431 uint16_t slot, counter = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002432
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002433 if (c->args.is_master)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002434 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002435 MEMIF_MEMORY_BARRIER ();
2436 ring->tail =
2437 (ring->tail + count <=
2438 mq->last_head) ? ring->tail + count : mq->last_head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002439 return MEMIF_ERR_SUCCESS;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002440 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002441
2442 uint16_t head = ring->head;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002443 slot = head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002444 uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002445 count = (count < ns) ? count : ns;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002446
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002447 memif_desc_t *d;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002448 while (counter < count)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002449 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002450 d = &ring->desc[slot & mask];
2451 d->region = 1;
2452 d->length = c->run_args.buffer_size - headroom;
2453 if (lm->get_external_buffer_offset)
2454 d->offset = lm->get_external_buffer_offset (c->private_ctx);
2455 else
2456 d->offset = d->offset - (d->offset & offset_mask) + headroom;
2457 slot++;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002458 counter++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002459 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002460
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002461 MEMIF_MEMORY_BARRIER ();
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01002462 ring->head = slot;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002463
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002464 return MEMIF_ERR_SUCCESS; /* 0 */
2465}
2466
2467int
2468memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
2469 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
2470{
2471 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002472 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002473 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002474 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002475 return MEMIF_ERR_DISCONNECTED;
2476 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002477 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2478 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002479 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002480 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002481 if (EXPECT_FALSE (!tx))
2482 return MEMIF_ERR_INVAL_ARG;
2483
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002484 memif_queue_t *mq = &c->tx_queues[qid];
2485 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002486 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar14217482021-01-14 13:23:48 +01002487 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002488 memif_buffer_t *b0;
Jakub Grajciar14217482021-01-14 13:23:48 +01002489 memif_desc_t *d;
2490 int64_t data_offset;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002491 *tx = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002492 int err = MEMIF_ERR_SUCCESS;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002493
2494 if (EXPECT_FALSE (count == 0))
2495 return MEMIF_ERR_SUCCESS;
2496
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002497 uint16_t index;
2498 if (c->args.is_master)
2499 index = ring->tail;
2500 else
2501 index = ring->head;
2502
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002503 while (count)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002504 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002505 b0 = (bufs + *tx);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002506 /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
2507 */
2508 if ((b0->desc_index & mask) != (index & mask))
2509 {
2510 err = MEMIF_ERR_INVAL_ARG;
2511 goto done;
2512 }
Jakub Grajciar14217482021-01-14 13:23:48 +01002513 d = &ring->desc[b0->desc_index & mask];
2514 d->length = b0->len;
2515 if (!c->args.is_master)
2516 {
2517 // reset headroom
2518 d->offset = d->offset - (d->offset & offset_mask);
2519 // calculate offset from user data
2520 data_offset = b0->data - (d->offset + c->regions[d->region].addr);
2521 if (data_offset != 0)
2522 {
2523 /* verify data offset */
2524 if ((data_offset < 0) ||
2525 (data_offset > (d->offset + offset_mask)))
2526 {
2527 printf ("%ld\n", data_offset);
2528 err = MEMIF_ERR_INVAL_ARG;
2529 goto done;
2530 }
2531 d->offset += data_offset;
2532 }
2533 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002534
2535#ifdef MEMIF_DBG_SHM
2536 printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
2537 printf ("data: %p\n",
2538 memif_get_buffer (c, ring, b0->desc_index & mask));
2539 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002540 print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
2541 ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002542#endif /* MEMIF_DBG_SHM */
2543
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002544 *tx += 1;
2545 count--;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002546 index++;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002547 }
2548
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002549done:
Milan Lenco0a47c992017-10-12 14:19:31 +02002550 MEMIF_MEMORY_BARRIER ();
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002551 if (c->args.is_master)
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002552 ring->tail = b0->desc_index + 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002553 else
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002554 ring->head = b0->desc_index + 1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002555
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002556 if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
2557 {
2558 uint64_t a = 1;
2559 int r = write (mq->int_fd, &a, sizeof (a));
2560 if (r < 0)
2561 return MEMIF_ERR_INT_WRITE;
2562 }
2563
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002564 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002565}
2566
2567int
2568memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
2569 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
2570{
2571 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002572 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002573 return MEMIF_ERR_NOCONN;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002574 if (EXPECT_FALSE (c->fd < 0))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002575 return MEMIF_ERR_DISCONNECTED;
2576 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002577 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2578 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002579 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002580 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002581 if (EXPECT_FALSE (!rx))
2582 return MEMIF_ERR_INVAL_ARG;
2583
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002584 memif_queue_t *mq = &c->rx_queues[qid];
2585 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002586 uint16_t cur_slot, last_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002587 uint16_t ns;
2588 uint16_t mask = (1 << mq->log2_ring_size) - 1;
msardara8f554b72018-12-11 18:36:55 +01002589 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002590 *rx = 0;
2591
2592 uint64_t b;
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01002593 ssize_t r;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002594
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002595 cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
2596 last_slot = (c->args.is_master) ? ring->head : ring->tail;
2597 if (cur_slot == last_slot)
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01002598 {
2599 r = read (mq->int_fd, &b, sizeof (b));
2600 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2601 return memif_syscall_error_handler (errno);
2602
2603 return MEMIF_ERR_SUCCESS;
2604 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002605
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002606 ns = last_slot - cur_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002607
2608 while (ns && count)
2609 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002610 b0 = (bufs + *rx);
2611
2612 b0->desc_index = cur_slot;
2613 b0->data = memif_get_buffer (c, ring, cur_slot & mask);
2614 b0->len = ring->desc[cur_slot & mask].length;
2615 /* slave resets buffer length */
2616 if (c->args.is_master == 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002617 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002618 ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002619 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002620
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002621 if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
2622 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002623 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002624 ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
2625 }
Jakub Grajciar14217482021-01-14 13:23:48 +01002626
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002627 b0->queue = mq;
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02002628#ifdef MEMIF_DBG_SHM
Jakub Grajciar3744fc72018-03-29 13:15:10 +02002629 printf ("data: %p\n", b0->data);
2630 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01002631 printf ("queue: %p\n", b0->queue);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002632 print_bytes (b0->data, b0->len, DBG_RX_BUF);
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02002633#endif /* MEMIF_DBG_SHM */
2634 ns--;
2635 *rx += 1;
2636
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002637 count--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002638 cur_slot++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002639 }
2640
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002641 if (c->args.is_master)
2642 mq->last_head = cur_slot;
2643 else
2644 mq->last_tail = cur_slot;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02002645
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002646 if (ns)
2647 {
2648 DBG ("not enough buffers!");
2649 return MEMIF_ERR_NOBUF;
2650 }
2651
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01002652 r = read (mq->int_fd, &b, sizeof (b));
2653 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2654 return memif_syscall_error_handler (errno);
2655
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002656 return MEMIF_ERR_SUCCESS; /* 0 */
2657}
2658
2659int
2660memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
2661 char *buf, ssize_t buflen)
2662{
2663 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002664 libmemif_main_t *lm;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002665 memif_socket_t *ms;
2666 int err = MEMIF_ERR_SUCCESS, i;
2667 ssize_t l0 = 0, l1;
2668
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002669 if (c == NULL)
2670 return MEMIF_ERR_NOCONN;
2671
Jakub Grajciar12df4972019-07-01 14:24:48 +02002672 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002673 lm = get_libmemif_main (ms);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002674
2675 l1 = strlen ((char *) c->args.interface_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002676 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002677 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002678 md->if_name =
2679 (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002680 l0 += l1 + 1;
2681 }
2682 else
2683 err = MEMIF_ERR_NOBUF_DET;
2684
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002685 l1 = strlen ((char *) lm->app_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002686 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002687 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02002688 md->inst_name = (uint8_t *) strcpy (buf + l0, (char *) lm->app_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002689 l0 += l1 + 1;
2690 }
2691 else
2692 err = MEMIF_ERR_NOBUF_DET;
2693
2694 l1 = strlen ((char *) c->remote_if_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002695 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002696 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002697 md->remote_if_name =
2698 (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002699 l0 += l1 + 1;
2700 }
2701 else
2702 err = MEMIF_ERR_NOBUF_DET;
2703
2704 l1 = strlen ((char *) c->remote_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02002705 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002706 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002707 md->remote_inst_name =
2708 (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002709 l0 += l1 + 1;
2710 }
2711 else
2712 err = MEMIF_ERR_NOBUF_DET;
2713
2714 md->id = c->args.interface_id;
2715
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002716 if (strlen ((char *) c->args.secret) > 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002717 {
2718 l1 = strlen ((char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02002719 if (l0 + l1 < buflen)
2720 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02002721 md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02002722 l0 += l1 + 1;
2723 }
2724 else
2725 err = MEMIF_ERR_NOBUF_DET;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002726 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002727
2728 md->role = (c->args.is_master) ? 0 : 1;
2729 md->mode = c->args.mode;
2730
Jakub Grajciar12df4972019-07-01 14:24:48 +02002731 l1 = strlen ((char *) ms->filename);
Milan Lenco0a47c992017-10-12 14:19:31 +02002732 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002733 {
2734 md->socket_filename =
Jakub Grajciar12df4972019-07-01 14:24:48 +02002735 (uint8_t *) strcpy (buf + l0, (char *) ms->filename);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002736 l0 += l1 + 1;
2737 }
2738 else
2739 err = MEMIF_ERR_NOBUF_DET;
2740
Jakub Grajciar568cc462018-09-05 12:11:35 +02002741 l1 = strlen ((char *) c->remote_disconnect_string);
2742 if (l0 + l1 < buflen)
2743 {
2744 md->error =
2745 (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
2746 l0 += l1 + 1;
2747 }
2748 else
2749 err = MEMIF_ERR_NOBUF_DET;
2750
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002751 md->regions_num = c->regions_num;
2752 l1 = sizeof (memif_region_details_t) * md->regions_num;
2753 if (l0 + l1 <= buflen)
2754 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002755 md->regions = (memif_region_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002756 for (i = 0; i < md->regions_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002757 {
2758 md->regions[i].index = i;
2759 md->regions[i].addr = c->regions[i].addr;
2760 md->regions[i].size = c->regions[i].region_size;
2761 md->regions[i].fd = c->regions[i].fd;
2762 md->regions[i].is_external = c->regions[i].is_external;
2763 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002764 l0 += l1;
2765 }
2766 else
2767 err = MEMIF_ERR_NOBUF_DET;
2768
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002769 md->rx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002770 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2771 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002772
2773 l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2774 if (l0 + l1 <= buflen)
2775 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002776 md->rx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002777 for (i = 0; i < md->rx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002778 {
2779 md->rx_queues[i].region = c->rx_queues[i].region;
2780 md->rx_queues[i].qid = i;
2781 md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2782 md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2783 md->rx_queues[i].head = c->rx_queues[i].ring->head;
2784 md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2785 md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2786 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002787 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002788 }
2789 else
2790 err = MEMIF_ERR_NOBUF_DET;
2791
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002792 md->tx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002793 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2794 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002795
2796 l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2797 if (l0 + l1 <= buflen)
2798 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002799 md->tx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002800 for (i = 0; i < md->tx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002801 {
2802 md->tx_queues[i].region = c->tx_queues[i].region;
2803 md->tx_queues[i].qid = i;
2804 md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2805 md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2806 md->tx_queues[i].head = c->tx_queues[i].ring->head;
2807 md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2808 md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2809 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002810 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002811 }
2812 else
2813 err = MEMIF_ERR_NOBUF_DET;
2814
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002815 md->link_up_down = (c->fd > 0) ? 1 : 0;
2816
2817 return err; /* 0 */
2818}
2819
2820int
2821memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2822{
2823 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002824 uint8_t num;
2825
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002826 *efd = -1;
2827 if (c == NULL)
2828 return MEMIF_ERR_NOCONN;
2829 if (c->fd < 0)
2830 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002831
2832 num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002833 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2834 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002835 if (qid >= num)
2836 return MEMIF_ERR_QID;
2837
2838 *efd = c->rx_queues[qid].int_fd;
2839
2840 return MEMIF_ERR_SUCCESS;
2841}
2842
2843int
2844memif_cleanup ()
2845{
2846 libmemif_main_t *lm = &libmemif_main;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002847 int err;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002848
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02002849 err = memif_delete_socket ((memif_socket_handle_t *) & lm->default_socket);
2850 if (err != MEMIF_ERR_SUCCESS)
2851 return err;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002852
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002853 if (lm->control_list)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002854 lm->free (lm->control_list);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002855 lm->control_list = NULL;
2856 if (lm->interrupt_list)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002857 lm->free (lm->interrupt_list);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002858 lm->interrupt_list = NULL;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002859 if (lm->socket_list)
2860 lm->free (lm->socket_list);
2861 lm->socket_list = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002862 if (lm->pending_list)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02002863 lm->free (lm->pending_list);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002864 lm->pending_list = NULL;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02002865 if (lm->poll_cancel_fd != -1)
2866 close (lm->poll_cancel_fd);
2867
2868 return MEMIF_ERR_SUCCESS; /* 0 */
2869}
2870
2871int
2872memif_per_thread_cleanup (memif_per_thread_main_handle_t * pt_main)
2873{
2874 libmemif_main_t *lm = (libmemif_main_t *) * pt_main;
2875
2876 if (lm == NULL)
2877 return MEMIF_ERR_INVAL_ARG;
2878
2879 /* No default socket in case of per thread */
2880
2881 if (lm->control_list)
2882 lm->free (lm->control_list);
2883 lm->control_list = NULL;
2884 if (lm->interrupt_list)
2885 lm->free (lm->interrupt_list);
2886 lm->interrupt_list = NULL;
2887 if (lm->socket_list)
2888 lm->free (lm->socket_list);
2889 lm->socket_list = NULL;
2890 if (lm->pending_list)
2891 lm->free (lm->pending_list);
2892 lm->pending_list = NULL;
2893 if (lm->poll_cancel_fd != -1)
2894 close (lm->poll_cancel_fd);
2895
2896 lm->free (lm);
2897
2898 *pt_main = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002899
2900 return MEMIF_ERR_SUCCESS; /* 0 */
2901}