blob: 6f9ba2fe2291514dfd2039a60719b379c1188b64 [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
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020068static char memif_buf[MAX_ERRBUF_LEN];
69
70const char *memif_errlist[ERRLIST_LEN] = { /* MEMIF_ERR_SUCCESS */
71 "Success.",
72 /* MEMIF_ERR_SYSCALL */
73 "Unspecified syscall error (build with -DMEMIF_DBG or make debug).",
Jakub Grajciar568cc462018-09-05 12:11:35 +020074 /* MEMIF_ERR_CONNREFUSED */
75 "Connection refused",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020076 /* MEMIF_ERR_ACCES */
Paul Vinciguerra62237662020-05-29 23:03:06 -040077 "Permission to resource denied.",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020078 /* MEMIF_ERR_NO_FILE */
79 "Socket file does not exist",
80 /* MEMIF_ERR_FILE_LIMIT */
81 "System limit on total numer of open files reached.",
82 /* MEMIF_ERR_PROC_FILE_LIMIT */
83 "Per-process limit on total number of open files reached.",
84 /* MEMIF_ERR_ALREADY */
85 "Connection already requested.",
86 /* MEMIF_ERR_AGAIN */
87 "File descriptor refers to file other than socket, or operation would block.",
88 /* MEMIF_ERR_BAD_FD */
89 "Bad file descriptor.",
90 /* MEMIF_ERR_NOMEM */
91 "Out of memory.",
92 /* MEMIF_ERR_INVAL_ARG */
93 "Invalid argument.",
94 /* MEMIF_ERR_NOCONN */
Paul Vinciguerra62237662020-05-29 23:03:06 -040095 "Memif connection handle does not point to existing connection",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +020096 /* MEMIF_ERR_CONN */
97 "Memif connection handle points to existing connection",
98 /* MEMIF_ERR_CB_FDUPDATE */
99 "Callback memif_control_fd_update_t returned error",
100 /* MEMIF_ERR_FILE_NOT_SOCK */
101 "File specified by socket filename exists and is not socket.",
102 /* MEMIF_ERR_NO_SHMFD */
103 "Missing shared memory file descriptor. (internal error)",
104 /* MEMIF_ERR_COOKIE */
105 "Invalid cookie on ring. (internal error)",
106 /* MEMIF_ERR_NOBUF_RING */
107 "Ring buffer full.",
108 /* MEMIF_ERR_NOBUF */
109 "Not enough memif buffers. There are unreceived data in shared memory.",
110 /* MEMIF_ERR_NOBUF_DET */
Paul Vinciguerraf4fbfd62020-05-15 23:13:36 -0400111 "Not enough space for memif details in supplied buffer. String data might be malformed.",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200112 /* MEMIF_ERR_INT_WRITE */
113 "Send interrupt error.",
114 /* MEMIF_ERR_MFMSG */
115 "Malformed message received on control channel.",
116 /* MEMIF_ERR_QID */
117 "Invalid queue id",
118 /* MEMIF_ERR_PROTO */
119 "Incompatible memory interface protocol version.",
120 /* MEMIF_ERR_ID */
121 "Unmatched interface id.",
122 /* MEMIF_ERR_ACCSLAVE */
Paul Vinciguerraf4fbfd62020-05-15 23:13:36 -0400123 "Slave cannot accept connection request.",
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200124 /* MEMIF_ERR_ALRCONN */
125 "Interface is already connected.",
126 /* MEMIF_ERR_MODE */
127 "Mode mismatch.",
128 /* MEMIF_ERR_SECRET */
129 "Secret mismatch.",
130 /* MEMIF_ERR_NOSECRET */
131 "Secret required.",
132 /* MEMIF_ERR_MAXREG */
133 "Limit on total number of regions reached.",
134 /* MEMIF_ERR_MAXRING */
135 "Limit on total number of ring reached.",
136 /* MEMIF_ERR_NO_INTFD */
137 "Missing interrupt file descriptor. (internal error)",
138 /* MEMIF_ERR_DISCONNECT */
139 "Interface received disconnect request.",
140 /* MEMIF_ERR_DISCONNECTED */
141 "Interface is disconnected.",
142 /* MEMIF_ERR_UNKNOWN_MSG */
Milan Lenco0a47c992017-10-12 14:19:31 +0200143 "Unknown message type received on control channel. (internal error)",
144 /* MEMIF_ERR_POLL_CANCEL */
Damjan Marion6d56fa42017-11-03 12:24:37 +0100145 "Memif event polling was canceled.",
146 /* MEMIF_ERR_MAX_RING */
Jakub Grajciar3744fc72018-03-29 13:15:10 +0200147 "Maximum log2 ring size is 15",
Jakub Grajciarab7c2b02018-03-28 10:21:05 +0200148 /* MEMIF_ERR_PRIVHDR */
149 "Private headers not supported."
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200150};
151
152#define MEMIF_ERR_UNDEFINED "undefined error"
153
154char *
155memif_strerror (int err_code)
156{
157 if (err_code >= ERRLIST_LEN)
158 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000159 strlcpy (memif_buf, MEMIF_ERR_UNDEFINED, sizeof (memif_buf));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200160 }
161 else
162 {
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000163 strlcpy (memif_buf, memif_errlist[err_code], sizeof (memif_buf));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100164 memif_buf[strlen (memif_errlist[err_code])] = '\0';
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200165 }
166 return memif_buf;
167}
168
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200169uint16_t
170memif_get_version ()
171{
172 return MEMIF_VERSION;
173}
174
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100175const char *
176memif_get_version_str ()
177{
178#define __STR_HELPER(x) #x
179#define __STR(x) __STR_HELPER (x)
180 return __STR (MEMIF_VERSION_MAJOR) "." __STR (MEMIF_VERSION_MINOR);
181#undef __STR
182#undef __STR_HELPER
183}
184
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200185#define DBG_TX_BUF (0)
186#define DBG_RX_BUF (1)
187
188#ifdef MEMIF_DBG_SHM
189static void
190print_bytes (void *data, uint16_t len, uint8_t q)
191{
192 if (q == DBG_TX_BUF)
193 printf ("\nTX:\n\t");
194 else
195 printf ("\nRX:\n\t");
196 int i;
197 for (i = 0; i < len; i++)
198 {
199 if (i % 8 == 0)
200 printf ("\n%d:\t", i);
201 printf ("%02X ", ((uint8_t *) (data))[i]);
202 }
203 printf ("\n\n");
204}
Jakub Grajciarba3c4e82017-09-18 11:21:40 +0200205#endif /* MEMIF_DBG_SHM */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200206
207int
208memif_syscall_error_handler (int err_code)
209{
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200210 DBG ("%s", strerror (err_code));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200211
212 if (err_code == 0)
213 return MEMIF_ERR_SUCCESS;
214 if (err_code == EACCES)
215 return MEMIF_ERR_ACCES;
216 if (err_code == ENFILE)
217 return MEMIF_ERR_FILE_LIMIT;
218 if (err_code == EMFILE)
219 return MEMIF_ERR_PROC_FILE_LIMIT;
220 if (err_code == ENOMEM)
221 return MEMIF_ERR_NOMEM;
Damjan Marion6d56fa42017-11-03 12:24:37 +0100222/* connection refused if master does not exist
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200223 this error would spam the user until master was created */
Jakub Grajciar568cc462018-09-05 12:11:35 +0200224/*
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200225 if (err_code == ECONNREFUSED)
226 return MEMIF_ERR_SUCCESS;
Jakub Grajciar568cc462018-09-05 12:11:35 +0200227*/
228 if (err_code == ECONNREFUSED)
229 return MEMIF_ERR_CONNREFUSED;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200230 if (err_code == EALREADY)
231 return MEMIF_ERR_ALREADY;
232 if (err_code == EAGAIN)
233 return MEMIF_ERR_AGAIN;
234 if (err_code == EBADF)
235 return MEMIF_ERR_BAD_FD;
236 if (err_code == ENOENT)
237 return MEMIF_ERR_NO_FILE;
238
239 /* other syscall errors */
240 return MEMIF_ERR_SYSCALL;
241}
242
243static int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100244memif_add_epoll_fd (memif_socket_t *ms, memif_fd_event_t fde, uint32_t events)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200245{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100246 if (fde.fd < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200247 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100248 DBG ("invalid fd %d", fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200249 return -1;
250 }
251 struct epoll_event evt;
252 memset (&evt, 0, sizeof (evt));
253 evt.events = events;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100254 evt.data.ptr = fde.private_ctx;
255 if (epoll_ctl (ms->epfd, EPOLL_CTL_ADD, fde.fd, &evt) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200256 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100257 DBG ("epoll_ctl: %s fd %d", strerror (errno), fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200258 return -1;
259 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100260 DBG ("fd %d added to epoll", fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200261 return 0;
262}
263
264static int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100265memif_mod_epoll_fd (memif_socket_t *ms, memif_fd_event_t fde, uint32_t events)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200266{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100267 if (fde.fd < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200268 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100269 DBG ("invalid fd %d", fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200270 return -1;
271 }
272 struct epoll_event evt;
273 memset (&evt, 0, sizeof (evt));
274 evt.events = events;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100275 evt.data.ptr = fde.private_ctx;
276 if (epoll_ctl (ms->epfd, EPOLL_CTL_MOD, fde.fd, &evt) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200277 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100278 DBG ("epoll_ctl: %s fd %d", strerror (errno), fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200279 return -1;
280 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100281 DBG ("fd %d modified on epoll", fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200282 return 0;
283}
284
285static int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100286memif_del_epoll_fd (memif_socket_t *ms, memif_fd_event_t fde)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200287{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100288 if (fde.fd < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200289 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100290 DBG ("invalid fd %d", fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200291 return -1;
292 }
293 struct epoll_event evt;
294 memset (&evt, 0, sizeof (evt));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100295 if (epoll_ctl (ms->epfd, EPOLL_CTL_DEL, fde.fd, &evt) < 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200296 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100297 DBG ("epoll_ctl: %s fd %d", strerror (errno), fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200298 return -1;
299 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100300 DBG ("fd %d removed from epoll", fde.fd);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200301 return 0;
302}
303
304int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100305memif_control_fd_update (memif_fd_event_t fde, void *private_ctx)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200306{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100307 memif_socket_t *ms = (memif_socket_t *) private_ctx;
308 int fd;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200309
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100310 if (ms == NULL)
311 return MEMIF_ERR_INVAL_ARG;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200312
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100313 if (fde.type & MEMIF_FD_EVENT_DEL)
314 return memif_del_epoll_fd (ms, fde);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200315
316 uint32_t evt = 0;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100317 if (fde.type & MEMIF_FD_EVENT_READ)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200318 evt |= EPOLLIN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100319 if (fde.type & MEMIF_FD_EVENT_WRITE)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200320 evt |= EPOLLOUT;
321
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100322 if (fde.type & MEMIF_FD_EVENT_MOD)
323 return memif_mod_epoll_fd (ms, fde, evt);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200324
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100325 return memif_add_epoll_fd (ms, fde, evt);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200326}
327
328static void
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100329memif_control_fd_update_register (memif_socket_t *ms,
330 memif_control_fd_update_t *cb)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200331{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100332 ms->args.on_control_fd_update = cb;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200333}
334
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200335void
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100336memif_register_external_region (memif_socket_handle_t sock,
337 memif_add_external_region_t *ar,
338 memif_get_external_region_addr_t *gr,
339 memif_del_external_region_t *dr,
340 memif_get_external_buffer_offset_t *go)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200341{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100342 memif_socket_t *ms = (memif_socket_t *) sock;
343 ms->add_external_region = ar;
344 ms->get_external_region_addr = gr;
345 ms->del_external_region = dr;
346 ms->get_external_buffer_offset = go;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200347}
348
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200349static void
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100350memif_alloc_register (memif_socket_t *ms, memif_alloc_t *ma)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200351{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100352 ms->args.alloc = ma;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200353}
354
355static void
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100356memif_realloc_register (memif_socket_t *ms, memif_realloc_t *mr)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200357{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100358 ms->args.realloc = mr;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200359}
360
361static void
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100362memif_free_register (memif_socket_t *ms, memif_free_t *mf)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200363{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100364 ms->args.free = mf;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200365}
366
367static inline memif_ring_t *
368memif_get_ring (memif_connection_t * conn, memif_ring_type_t type,
369 uint16_t ring_num)
370{
371 if (&conn->regions[0] == NULL)
372 return NULL;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +0200373 void *p = conn->regions[0].addr;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200374 int ring_size =
375 sizeof (memif_ring_t) +
376 sizeof (memif_desc_t) * (1 << conn->run_args.log2_ring_size);
377 p += (ring_num + type * conn->run_args.num_s2m_rings) * ring_size;
378
379 return (memif_ring_t *) p;
380}
381
382int
383memif_set_rx_mode (memif_conn_handle_t c, memif_rx_mode_t rx_mode,
384 uint16_t qid)
385{
386 memif_connection_t *conn = (memif_connection_t *) c;
387 if (conn == NULL)
388 return MEMIF_ERR_NOCONN;
389 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +0200390 (conn->args.is_master) ? conn->run_args.num_s2m_rings : conn->
391 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200392 if (qid >= num)
393 return MEMIF_ERR_QID;
394
395 conn->rx_queues[qid].ring->flags = rx_mode;
396 DBG ("rx_mode flag: %u", conn->rx_queues[qid].ring->flags);
397 return MEMIF_ERR_SUCCESS;
398}
399
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100400int
401memif_poll_cancel_handler (memif_fd_event_type_t type, void *private_ctx)
Jakub Grajciar12df4972019-07-01 14:24:48 +0200402{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100403 return MEMIF_ERR_POLL_CANCEL;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200404}
405
406int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100407memif_connect_handler (memif_fd_event_type_t type, void *private_ctx)
408{
409 memif_socket_t *ms = (memif_socket_t *) private_ctx;
410 memif_connection_t *c;
411
Daniel Bérešc69655e2022-04-22 08:06:17 +0000412 if (ms->timer_fd >= 0)
413 {
414 uint64_t u64;
Daniel Béreš98533422023-01-19 10:19:27 +0100415 ssize_t __attribute__ ((unused)) r;
Daniel Bérešc69655e2022-04-22 08:06:17 +0000416 /*
417 Have to read the timer fd else it stays read-ready
418 and makes epoll_pwait() return without sleeping
419 */
Daniel Béreš98533422023-01-19 10:19:27 +0100420 r = read (ms->timer_fd, &u64, sizeof (u64));
Daniel Bérešc69655e2022-04-22 08:06:17 +0000421 }
422
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100423 /* loop ms->slave_interfaces and request connection for disconnected ones */
424 TAILQ_FOREACH (c, &ms->slave_interfaces, next)
425 {
426 /* connected or connecting */
427 if (c->control_channel != NULL)
428 continue;
429
430 /* ignore errors */
431 memif_request_connection (c);
432 }
433
434 return MEMIF_ERR_SUCCESS;
435}
436
437int
438memif_set_connection_request_timer (memif_socket_handle_t sock,
439 struct itimerspec timer)
440{
441 memif_socket_t *ms = (memif_socket_t *) sock;
442 memif_fd_event_t fde;
443 memif_fd_event_data_t *fdata;
444 void *ctx;
445
446 if (ms == NULL)
447 return MEMIF_ERR_INVAL_ARG;
448
449 if (ms->timer_fd < 0)
450 {
451 /* only create new timer if there is a valid interval */
452 if (timer.it_interval.tv_sec == 0 && timer.it_interval.tv_nsec == 0)
453 return MEMIF_ERR_SUCCESS;
454
455 /* create timerfd */
456 ms->timer_fd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
457 if (ms->timer_fd < 0)
458 return memif_syscall_error_handler (errno);
459
460 /* start listening for events */
461 fdata = ms->args.alloc (sizeof (*fdata));
462 fdata->event_handler = memif_connect_handler;
463 fdata->private_ctx = ms;
464
465 fde.fd = ms->timer_fd;
466 fde.type = MEMIF_FD_EVENT_READ;
467 fde.private_ctx = fdata;
468
469 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
470 ms->args.on_control_fd_update (fde, ctx);
471 }
472
473 ms->args.connection_request_timer = timer;
474
475 /* arm the timer */
476 if (timerfd_settime (ms->timer_fd, 0, &ms->args.connection_request_timer,
477 NULL) < 0)
478 return memif_syscall_error_handler (errno);
479
480 return MEMIF_ERR_SUCCESS;
481}
482
483int
484memif_create_socket (memif_socket_handle_t *sock, memif_socket_args_t *args,
Jakub Grajciar12df4972019-07-01 14:24:48 +0200485 void *private_ctx)
486{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200487 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100488 memif_fd_event_t fde;
489 memif_fd_event_data_t *fdata;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200490 int i, err = MEMIF_ERR_SUCCESS;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100491 void *ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200492
493 /* allocate memif_socket_t */
494 ms = NULL;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100495 if (args->alloc != NULL)
496 ms = args->alloc (sizeof (memif_socket_t));
497 else
498 ms = malloc (sizeof (memif_socket_t));
Jakub Grajciar12df4972019-07-01 14:24:48 +0200499 if (ms == NULL)
500 {
501 err = MEMIF_ERR_NOMEM;
502 goto error;
503 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100504
505 /* default values */
Jakub Grajciar12df4972019-07-01 14:24:48 +0200506 memset (ms, 0, sizeof (memif_socket_t));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100507 ms->epfd = -1;
508 ms->listener_fd = -1;
509 ms->poll_cancel_fd = -1;
510 ms->timer_fd = -1;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200511
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100512 /* copy arguments to internal struct */
513 memcpy (&ms->args, args, sizeof (*args));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100514 ms->private_ctx = private_ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200515
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100516 if (ms->args.alloc == NULL)
517 memif_alloc_register (ms, malloc);
518 if (ms->args.realloc == NULL)
519 memif_realloc_register (ms, realloc);
520 if (ms->args.free == NULL)
521 memif_free_register (ms, free);
522
523 TAILQ_INIT (&ms->master_interfaces);
524 TAILQ_INIT (&ms->slave_interfaces);
525
526 /* FIXME: implement connection request timer */
527
528 /* initialize internal epoll */
529 if (ms->args.on_control_fd_update == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +0200530 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100531 ms->epfd = epoll_create (1);
532 /* register default fd update callback */
533 memif_control_fd_update_register (ms, memif_control_fd_update);
534 ms->poll_cancel_fd = eventfd (0, EFD_NONBLOCK);
535 if (ms->poll_cancel_fd < 0)
536 {
537 err = errno;
538 DBG ("eventfd: %s", strerror (err));
539 return memif_syscall_error_handler (err);
540 }
541 /* add interrupt fd to epfd */
542 fdata = ms->args.alloc (sizeof (*fdata));
543 fdata->event_handler = memif_poll_cancel_handler;
544 fdata->private_ctx = ms;
545
546 fde.fd = ms->poll_cancel_fd;
547 fde.type = MEMIF_FD_EVENT_READ;
548 fde.private_ctx = fdata;
549
550 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
551 ms->args.on_control_fd_update (fde, ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200552 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100553
554 err =
555 memif_set_connection_request_timer (ms, ms->args.connection_request_timer);
556 if (err != MEMIF_ERR_SUCCESS)
557 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200558
559 *sock = ms;
560
561 return err;
562
563error:
564 if (ms != NULL)
565 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100566 ms->args.free (ms);
567 if (ms->epfd != -1)
568 close (ms->epfd);
569 if (ms->poll_cancel_fd != -1)
570 close (ms->poll_cancel_fd);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200571 }
572 return err;
573}
574
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100575memif_socket_handle_t
576memif_get_socket_handle (memif_conn_handle_t conn)
577{
578 memif_connection_t *c = (memif_connection_t *) conn;
579
580 if (c == NULL)
581 return NULL;
582
583 return c->args.socket;
584}
585
586const char *
587memif_get_socket_path (memif_socket_handle_t sock)
588{
589 memif_socket_t *ms = (memif_socket_t *) sock;
590
591 if (ms == NULL)
592 return NULL;
593
594 return ms->args.path;
595}
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200596
597int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100598memif_get_listener_fd (memif_socket_handle_t sock)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200599{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100600 memif_socket_t *ms = (memif_socket_t *) sock;
601
602 if (ms == NULL)
603 return -1;
604
605 return ms->listener_fd;
606}
607
608int
609memif_set_listener_fd (memif_socket_handle_t sock, int fd)
610{
611 memif_socket_t *ms = (memif_socket_t *) sock;
612 memif_fd_event_t fde;
613 memif_fd_event_data_t *fdata;
614 void *ctx;
615
616 if ((ms == NULL) || (fd < 0))
617 return MEMIF_ERR_INVAL_ARG;
618
619 fdata = ms->args.alloc (sizeof (*fdata));
620 if (fdata == NULL)
621 return MEMIF_ERR_NOMEM;
622
623 ms->listener_fd = fd;
624
625 fdata->event_handler = memif_listener_handler;
626 fdata->private_ctx = ms;
627 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
628 /* send fd to epoll */
629 fde.fd = ms->listener_fd;
630 fde.type = MEMIF_FD_EVENT_READ;
631 fde.private_ctx = fdata;
632 ms->args.on_control_fd_update (fde, ctx);
633
634 return MEMIF_ERR_SUCCESS;
635}
636
637int
638memif_create (memif_conn_handle_t *c, memif_conn_args_t *args,
639 memif_connection_update_t *on_connect,
640 memif_connection_update_t *on_disconnect,
641 memif_on_interrupt_t *on_interrupt, void *private_ctx)
642{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200643 int err, index = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200644 memif_connection_t *conn = (memif_connection_t *) * c;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100645 memif_socket_t *ms = (memif_socket_t *) args->socket;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200646
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200647 if (conn != NULL)
648 {
649 DBG ("This handle already points to existing memif.");
650 return MEMIF_ERR_CONN;
651 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200652
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100653 if (ms == NULL)
654 {
655 DBG ("Missing memif socket");
656 return MEMIF_ERR_INVAL_ARG;
657 }
658
659 conn = (memif_connection_t *) ms->args.alloc (sizeof (*conn));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200660 if (conn == NULL)
661 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200662 err = MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200663 goto error;
664 }
665 memset (conn, 0, sizeof (memif_connection_t));
666
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200667 conn->args.interface_id = args->interface_id;
668
669 if (args->log2_ring_size == 0)
670 args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
Damjan Marion6d56fa42017-11-03 12:24:37 +0100671 else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
672 {
673 err = MEMIF_ERR_MAX_RING;
674 goto error;
675 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200676 if (args->buffer_size == 0)
677 args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
678 if (args->num_s2m_rings == 0)
679 args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
680 if (args->num_m2s_rings == 0)
681 args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
682
683 conn->args.num_s2m_rings = args->num_s2m_rings;
684 conn->args.num_m2s_rings = args->num_m2s_rings;
685 conn->args.buffer_size = args->buffer_size;
686 conn->args.log2_ring_size = args->log2_ring_size;
687 conn->args.is_master = args->is_master;
688 conn->args.mode = args->mode;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100689 conn->args.socket = args->socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200690 conn->regions = NULL;
691 conn->tx_queues = NULL;
692 conn->rx_queues = NULL;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100693 conn->control_channel = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200694 conn->on_connect = on_connect;
695 conn->on_disconnect = on_disconnect;
696 conn->on_interrupt = on_interrupt;
697 conn->private_ctx = private_ctx;
698 memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
699
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100700 uint8_t l = sizeof (conn->args.interface_name);
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000701 strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100702 l);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200703
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100704 if ((l = strlen ((char *) args->secret)) > 0)
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000705 strlcpy ((char *) conn->args.secret, (char *) args->secret,
706 sizeof (conn->args.secret));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200707
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100708 if (args->is_master)
709 TAILQ_INSERT_TAIL (&ms->master_interfaces, conn, next);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200710 else
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100711 TAILQ_INSERT_TAIL (&ms->slave_interfaces, conn, next);
712
713 err = memif_request_connection (conn);
714 if (err != MEMIF_ERR_SUCCESS && err != MEMIF_ERR_CONNREFUSED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200715 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100716 if (args->is_master)
717 TAILQ_REMOVE (&ms->master_interfaces, conn, next);
718 else
719 TAILQ_REMOVE (&ms->slave_interfaces, conn, next);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200720 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200721 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200722
Jakub Grajciar12df4972019-07-01 14:24:48 +0200723 *c = conn;
724
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200725 return 0;
726
727error:
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200728 if (conn != NULL)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100729 ms->args.free (conn);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200730 *c = conn = NULL;
731 return err;
732}
733
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200734static inline int
735memif_path_is_abstract (const char *filename)
736{
737 return (filename[0] == '@');
738}
739
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200740int
Jakub Grajciar12df4972019-07-01 14:24:48 +0200741memif_request_connection (memif_conn_handle_t c)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100742{
Jakub Grajciar84b83772019-03-04 12:42:19 +0100743 memif_connection_t *conn = (memif_connection_t *) c;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200744 memif_socket_t *ms;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100745 int err = MEMIF_ERR_SUCCESS;
746 int sockfd = -1;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100747 struct sockaddr_un un = { 0 };
748 struct stat file_stat;
749 int on = 1;
750 memif_control_channel_t *cc = NULL;
751 memif_fd_event_t fde;
752 memif_fd_event_data_t *fdata = NULL;
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200753 int sunlen = sizeof (un);
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100754 void *ctx;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100755
Jakub Grajciar12df4972019-07-01 14:24:48 +0200756 if (conn == NULL)
757 return MEMIF_ERR_NOCONN;
758
759 ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +0200760
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100761 /* if control channel is assigned, the interface is either connected or
762 * connecting */
763 if (conn->control_channel != NULL)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100764 return MEMIF_ERR_ALRCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100765 /* if interface is master and the socket is already listener we are done */
766 if (conn->args.is_master && (ms->listener_fd != -1))
767 return MEMIF_ERR_SUCCESS;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100768
769 sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
770 if (sockfd < 0)
771 {
772 err = memif_syscall_error_handler (errno);
773 goto error;
774 }
775
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100776 un.sun_family = AF_UNIX;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100777
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100778 /* use memcpy to support abstract socket
779 * ms->args.path is already a valid socket path
780 */
781 memcpy (un.sun_path, ms->args.path, sizeof (un.sun_path) - 1);
Jakub Grajciar84b83772019-03-04 12:42:19 +0100782
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100783 /* allocate fd event data */
784 fdata = ms->args.alloc (sizeof (*fdata));
785 if (fdata == NULL)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100786 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100787 err = MEMIF_ERR_NOMEM;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100788 goto error;
789 }
790
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200791 if (memif_path_is_abstract (ms->args.path))
792 {
793 /* Ensure the string is NULL terminated */
794 un.sun_path[sizeof (un.sun_path) - 1] = '\0';
795 /* sunlen is strlen(un.sun_path) + sizeof(un.sun_family) */
796 sunlen = strlen (un.sun_path) + (sizeof (un) - sizeof (un.sun_path));
797 /* Handle abstract socket by converting '@' -> '\0' */
798 un.sun_path[0] = '\0';
799 }
800
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100801 if (conn->args.is_master != 0)
802 {
803 /* Configure socket optins */
804 if (setsockopt (sockfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
805 {
806 err = memif_syscall_error_handler (errno);
807 goto error;
808 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200809 if (bind (sockfd, (struct sockaddr *) &un, sunlen) < 0)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100810 {
811 err = memif_syscall_error_handler (errno);
812 goto error;
813 }
814 if (listen (sockfd, 1) < 0)
815 {
816 err = memif_syscall_error_handler (errno);
817 goto error;
818 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200819 if (!memif_path_is_abstract (ms->args.path))
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100820 {
821 /* Verify that the socket was created */
822 if (stat ((char *) ms->args.path, &file_stat) < 0)
823 {
824 err = memif_syscall_error_handler (errno);
825 goto error;
826 }
827 }
828
829 /* assign listener fd */
830 ms->listener_fd = sockfd;
831
832 fdata->event_handler = memif_listener_handler;
833 fdata->private_ctx = ms;
834 }
835 else
836 {
837 cc = ms->args.alloc (sizeof (*cc));
838 if (cc == NULL)
839 {
840 err = MEMIF_ERR_NOMEM;
841 goto error;
842 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200843 if (connect (sockfd, (struct sockaddr *) &un, sunlen) != 0)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100844 {
845 err = MEMIF_ERR_CONNREFUSED;
846 goto error;
847 }
848
849 /* Create control channel */
850 cc->fd = sockfd;
851 cc->sock = ms;
852 cc->conn = conn;
853 TAILQ_INIT (&cc->msg_queue);
854
855 /* assign control channel to endpoint */
856 conn->control_channel = cc;
857
858 fdata->event_handler = memif_control_channel_handler;
859 fdata->private_ctx = cc;
860 }
861
862 /* if event polling is done internally, send memif socket as context */
863 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
864 /* send fd to epoll */
865 fde.fd = sockfd;
866 fde.type = MEMIF_FD_EVENT_READ;
867 fde.private_ctx = fdata;
868 ms->args.on_control_fd_update (fde, ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200869
870 return err;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100871
872error:
873 if (sockfd > 0)
874 close (sockfd);
875 sockfd = -1;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100876 if (fdata != NULL)
877 ms->args.free (fdata);
878 fdata = NULL;
879 if (cc != NULL)
880 ms->args.free (cc);
881 conn->control_channel = cc = NULL;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100882 return err;
883}
884
885int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100886memif_control_fd_handler (void *ptr, memif_fd_event_type_t events)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200887{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100888 memif_fd_event_data_t *fdata = (memif_fd_event_data_t *) ptr;
msardara8f554b72018-12-11 18:36:55 +0100889
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100890 if (fdata == NULL)
891 return MEMIF_ERR_INVAL_ARG;
msardara8f554b72018-12-11 18:36:55 +0100892
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100893 return fdata->event_handler (events, fdata->private_ctx);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200894}
895
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100896int
897memif_interrupt_handler (memif_fd_event_type_t type, void *private_ctx)
898{
899 memif_interrupt_t *idata = (memif_interrupt_t *) private_ctx;
900
901 if (idata == NULL)
902 return MEMIF_ERR_INVAL_ARG;
903
904 return idata->c->on_interrupt (idata->c, idata->c->private_ctx, idata->qid);
905}
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200906
907int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100908memif_poll_event (memif_socket_handle_t sock, int timeout)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200909{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100910 memif_socket_t *ms = (memif_socket_t *) sock;
msardara8f554b72018-12-11 18:36:55 +0100911 struct epoll_event evt;
912 int en = 0, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100913 memif_fd_event_type_t events = 0;
Milan Lenco0a47c992017-10-12 14:19:31 +0200914 uint64_t counter = 0;
915 ssize_t r = 0;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100916 sigset_t sigset;
917
918 if (ms == NULL)
919 return MEMIF_ERR_INVAL_ARG;
920
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200921 memset (&evt, 0, sizeof (evt));
922 evt.events = EPOLLIN | EPOLLOUT;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200923 sigemptyset (&sigset);
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100924 en = epoll_pwait (ms->epfd, &evt, 1, timeout, &sigset);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200925 if (en < 0)
926 {
Milan Lenco0a47c992017-10-12 14:19:31 +0200927 err = errno;
928 DBG ("epoll_pwait: %s", strerror (err));
929 return memif_syscall_error_handler (err);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200930 }
931 if (en > 0)
932 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200933 if (evt.events & EPOLLIN)
934 events |= MEMIF_FD_EVENT_READ;
935 if (evt.events & EPOLLOUT)
936 events |= MEMIF_FD_EVENT_WRITE;
937 if (evt.events & EPOLLERR)
938 events |= MEMIF_FD_EVENT_ERROR;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100939 return memif_control_fd_handler (evt.data.ptr, events);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200940 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100941 return MEMIF_ERR_SUCCESS;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200942}
943
944int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100945memif_cancel_poll_event (memif_socket_handle_t sock)
Milan Lenco0a47c992017-10-12 14:19:31 +0200946{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100947 memif_socket_t *ms = (memif_socket_t *) sock;
Milan Lenco0a47c992017-10-12 14:19:31 +0200948 uint64_t counter = 1;
949 ssize_t w = 0;
950
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100951 if (ms->poll_cancel_fd == -1)
952 return MEMIF_ERR_INVAL_ARG;
953 w = write (ms->poll_cancel_fd, &counter, sizeof (counter));
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200954 if (w < sizeof (counter))
955 return MEMIF_ERR_INT_WRITE;
956
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100957 return MEMIF_ERR_SUCCESS;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200958}
959
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100960void
961memif_close_queues (memif_socket_t *ms, memif_queue_t *queues, int nqueues)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200962{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100963 memif_fd_event_t fde;
964 memif_queue_t *mq;
965 void *ctx;
966
967 int i;
968 for (i = 0; i < nqueues; i++)
969 {
970 mq = &queues[i];
971 if (mq != NULL)
972 {
973 if (mq->int_fd > 0)
974 {
975 /* Stop listening for events */
976 fde.fd = mq->int_fd;
977 fde.type = MEMIF_FD_EVENT_DEL;
978 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
979 ms->args.on_control_fd_update (fde, ctx);
980 close (mq->int_fd);
981 }
982 mq->int_fd = -1;
983 }
984 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200985}
986
987/* send disconnect msg and close interface */
988int
989memif_disconnect_internal (memif_connection_t * c)
990{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200991 int err = MEMIF_ERR_SUCCESS, i; /* 0 */
992 memif_queue_t *mq;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100993 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
994 memif_fd_event_t fde;
995 void *ctx;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +0200996
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200997 c->on_disconnect ((void *) c, c->private_ctx);
998
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100999 /* Delete control channel */
1000 if (c->control_channel != NULL)
1001 memif_delete_control_channel (c->control_channel);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001002
1003 if (c->tx_queues != NULL)
1004 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001005 memif_close_queues (ms, c->tx_queues, c->tx_queues_num);
1006 ms->args.free (c->tx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001007 c->tx_queues = NULL;
1008 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001009 c->tx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001010
1011 if (c->rx_queues != NULL)
1012 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001013 memif_close_queues (ms, c->rx_queues, c->rx_queues_num);
1014 ms->args.free (c->rx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001015 c->rx_queues = NULL;
1016 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001017 c->rx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001018
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001019 /* TODO: Slave reuse regions */
1020
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001021 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001022 {
Jakub Grajciar412e7b62018-09-27 10:26:35 +02001023 if (&c->regions[i] == NULL)
1024 continue;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001025 if (c->regions[i].is_external != 0)
1026 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001027 ms->del_external_region (c->regions[i].addr,
1028 c->regions[i].region_size, c->regions[i].fd,
1029 c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001030 }
1031 else
1032 {
1033 if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1034 return memif_syscall_error_handler (errno);
1035 if (c->regions[i].fd > 0)
1036 close (c->regions[i].fd);
1037 c->regions[i].fd = -1;
1038 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001039 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001040 ms->args.free (c->regions);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001041 c->regions = NULL;
1042 c->regions_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001043
1044 memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1045
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001046 return err;
1047}
1048
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001049const char *
1050memif_get_socket_filename (memif_socket_handle_t sock)
1051{
1052 memif_socket_t *ms = (memif_socket_t *) sock;
1053
1054 if (ms == NULL)
1055 return NULL;
1056
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001057 return (char *) ms->args.path;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001058}
1059
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001060int
Jakub Grajciar12df4972019-07-01 14:24:48 +02001061memif_delete_socket (memif_socket_handle_t * sock)
1062{
1063 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001064 memif_fd_event_t fde;
1065 void *ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001066
1067 /* check if socket is in use */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001068 if (ms == NULL || !TAILQ_EMPTY (&ms->master_interfaces) ||
1069 !TAILQ_EMPTY (&ms->slave_interfaces))
Jakub Grajciar12df4972019-07-01 14:24:48 +02001070 return MEMIF_ERR_INVAL_ARG;
1071
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001072 if (ms->listener_fd > 0)
1073 {
1074 fde.fd = ms->listener_fd;
1075 fde.type = MEMIF_FD_EVENT_DEL;
1076 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1077 ms->args.on_control_fd_update (fde, ctx);
1078 }
1079 ms->listener_fd = -1;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001080
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001081 if (ms->poll_cancel_fd > 0)
1082 {
1083 fde.fd = ms->poll_cancel_fd;
1084 fde.type = MEMIF_FD_EVENT_DEL;
1085 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1086 ms->args.on_control_fd_update (fde, ctx);
1087 }
1088 ms->poll_cancel_fd = -1;
1089
1090 if (ms->epfd > 0)
1091 close (ms->epfd);
1092 ms->epfd = -1;
1093
1094 ms->args.free (ms);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001095 *sock = ms = NULL;
1096
1097 return MEMIF_ERR_SUCCESS;
1098}
1099
1100int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001101memif_delete (memif_conn_handle_t * conn)
1102{
1103 memif_connection_t *c = (memif_connection_t *) * conn;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001104 memif_socket_t *ms;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001105 int err = MEMIF_ERR_SUCCESS;
1106
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001107 if (c == NULL)
1108 {
1109 DBG ("no connection");
1110 return MEMIF_ERR_NOCONN;
1111 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001112
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001113 err = memif_disconnect_internal (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001114
Jakub Grajciar12df4972019-07-01 14:24:48 +02001115 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001116
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001117 if (c->args.is_master)
1118 TAILQ_REMOVE (&ms->master_interfaces, c, next);
1119 else
1120 TAILQ_REMOVE (&ms->slave_interfaces, c, next);
1121 /* TODO: don't listen with empty interface queue */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001122
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001123 ms->args.free (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001124 c = NULL;
1125
1126 *conn = c;
1127 return err;
1128}
1129
1130int
1131memif_connect1 (memif_connection_t * c)
1132{
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001133 memif_socket_t *ms;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001134 memif_region_t *mr;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001135 memif_queue_t *mq;
1136 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001137
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001138 if (c == NULL)
1139 return MEMIF_ERR_INVAL_ARG;
1140
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001141 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001142
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001143 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001144 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001145 mr = &c->regions[i];
1146 if (mr != NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001147 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001148 if (!mr->addr)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001149 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001150 if (mr->is_external)
1151 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001152 if (ms->get_external_region_addr == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001153 return MEMIF_ERR_INVAL_ARG;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001154 mr->addr = ms->get_external_region_addr (
1155 mr->region_size, mr->fd, c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001156 }
1157 else
1158 {
1159 if (mr->fd < 0)
1160 return MEMIF_ERR_NO_SHMFD;
1161
1162 if ((mr->addr =
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001163 mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1164 MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001165 {
1166 return memif_syscall_error_handler (errno);
1167 }
1168 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001169 }
1170 }
1171 }
1172
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001173 for (i = 0; i < c->rx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001174 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001175 mq = &c->rx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001176 if (mq != NULL)
1177 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001178 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001179 if (mq->ring->cookie != MEMIF_COOKIE)
1180 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001181 DBG ("wrong cookie on rx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001182 return MEMIF_ERR_COOKIE;
1183 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001184 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001185 }
1186 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001187
1188 for (i = 0; i < c->tx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001189 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001190 mq = &c->tx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001191 if (mq != NULL)
1192 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001193 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001194 if (mq->ring->cookie != MEMIF_COOKIE)
1195 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001196 DBG ("wrong cookie on tx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001197 return MEMIF_ERR_COOKIE;
1198 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001199 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001200 }
1201 }
1202
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001203 return 0;
1204}
1205
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001206static inline int
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001207memif_add_region (memif_connection_t *conn, uint8_t has_buffers)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001208{
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001209 memif_region_t *r;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001210 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001211
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001212 r = ms->args.realloc (conn->regions,
1213 sizeof (memif_region_t) * ++conn->regions_num);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001214 if (r == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001215 return MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001216
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001217 conn->regions = r;
1218 r = &conn->regions[conn->regions_num - 1];
1219 memset (r, 0, sizeof (memif_region_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001220
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001221 if (has_buffers != 0)
1222 {
1223 r->buffer_offset = 0;
1224 }
1225 else
1226 {
1227 r->buffer_offset =
1228 (conn->run_args.num_s2m_rings +
1229 conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1230 sizeof (memif_desc_t) *
Jakub Grajciar568cc462018-09-05 12:11:35 +02001231 (1 << conn->
1232 run_args.log2_ring_size));
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001233 }
1234
1235 r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001236 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1237 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1238
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001239 if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001240 return memif_syscall_error_handler (errno);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001241
1242 if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1243 return memif_syscall_error_handler (errno);
1244
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001245 if ((ftruncate (r->fd, r->region_size)) == -1)
1246 return memif_syscall_error_handler (errno);
1247
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001248 if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1249 MAP_SHARED, r->fd, 0)) == MAP_FAILED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001250 return memif_syscall_error_handler (errno);
1251
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001252 return MEMIF_ERR_SUCCESS;
1253}
1254
1255static inline int
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001256memif_init_queues (memif_connection_t *conn)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001257{
1258 int i, j;
1259 memif_ring_t *ring;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001260 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
mbly00e9fe62023-12-06 12:22:14 -08001261 uint32_t ring_size = 1 << conn->run_args.log2_ring_size;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001262
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001263 for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1264 {
1265 ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1266 DBG ("RING: %p I: %d", ring, i);
1267 ring->head = ring->tail = 0;
1268 ring->cookie = MEMIF_COOKIE;
1269 ring->flags = 0;
mbly00e9fe62023-12-06 12:22:14 -08001270 uint32_t base = i;
1271 uint32_t ring_offset = base * ring_size;
1272 for (j = 0; j < ring_size; j++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001273 {
mbly00e9fe62023-12-06 12:22:14 -08001274 uint32_t slot = ring_offset + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001275 ring->desc[j].region = 1;
1276 ring->desc[j].offset =
1277 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001278 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001279 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001280 }
1281 }
1282 for (i = 0; i < conn->run_args.num_m2s_rings; i++)
1283 {
1284 ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
1285 DBG ("RING: %p I: %d", ring, i);
1286 ring->head = ring->tail = 0;
1287 ring->cookie = MEMIF_COOKIE;
1288 ring->flags = 0;
mbly00e9fe62023-12-06 12:22:14 -08001289 uint32_t base = conn->run_args.num_s2m_rings + i;
1290 uint32_t ring_offset = base * ring_size;
1291 for (j = 0; j < ring_size; j++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001292 {
mbly00e9fe62023-12-06 12:22:14 -08001293 uint32_t slot = ring_offset + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001294 ring->desc[j].region = 1;
1295 ring->desc[j].offset =
1296 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001297 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001298 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001299 }
1300 }
1301 memif_queue_t *mq;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001302 mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1303 conn->run_args.num_s2m_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001304 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001305 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001306
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001307 int x;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001308
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001309 for (x = 0; x < conn->run_args.num_s2m_rings; x++)
1310 {
1311 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1312 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001313
1314 mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
1315 DBG ("RING: %p I: %d", mq[x].ring, x);
1316 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1317 mq[x].region = 0;
1318 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001319 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1320 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001321 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001322 }
1323 conn->tx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001324 conn->tx_queues_num = conn->run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001325
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001326 mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1327 conn->run_args.num_m2s_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001328 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001329 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001330
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001331 for (x = 0; x < conn->run_args.num_m2s_rings; x++)
1332 {
1333 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1334 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001335
1336 mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
1337 DBG ("RING: %p I: %d", mq[x].ring, x);
1338 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1339 mq[x].region = 0;
1340 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001341 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1342 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001343 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001344 }
1345 conn->rx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001346 conn->rx_queues_num = conn->run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001347
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001348 return MEMIF_ERR_SUCCESS;
1349}
1350
1351int
1352memif_init_regions_and_queues (memif_connection_t * conn)
1353{
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001354 memif_region_t *r;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001355 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001356
1357 /* region 0. rings */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001358 memif_add_region (conn, /* has_buffers */ 0);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001359
1360 /* region 1. buffers */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001361 if (ms->add_external_region)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001362 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001363 r = (memif_region_t *) ms->args.realloc (
1364 conn->regions, sizeof (memif_region_t) * ++conn->regions_num);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001365 if (r == NULL)
1366 return MEMIF_ERR_NOMEM;
1367 conn->regions = r;
1368
1369 conn->regions[1].region_size =
1370 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1371 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1372 conn->regions[1].buffer_offset = 0;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001373 ms->add_external_region (&conn->regions[1].addr,
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001374 conn->regions[1].region_size,
1375 &conn->regions[1].fd, conn->private_ctx);
1376 conn->regions[1].is_external = 1;
1377 }
1378 else
1379 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001380 memif_add_region (conn, 1);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001381 }
1382
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001383 memif_init_queues (conn);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001384
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001385 return 0;
1386}
1387
Jakub Grajciar47e68de2021-01-08 15:32:43 +01001388int
1389memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
1390 memif_buffer_t *buf)
1391{
1392 memif_connection_t *c = (memif_connection_t *) conn;
1393 if (EXPECT_FALSE (c == NULL))
1394 return MEMIF_ERR_NOCONN;
1395 if (EXPECT_FALSE (qid >= c->tx_queues_num))
1396 return MEMIF_ERR_QID;
1397 if (EXPECT_FALSE (buf == NULL))
1398 return MEMIF_ERR_INVAL_ARG;
1399
1400 uint16_t ring_size, ns;
1401 memif_queue_t *mq = &c->tx_queues[qid];
1402 memif_ring_t *ring = mq->ring;
1403
1404 ring_size = (1 << mq->log2_ring_size);
1405 if (c->args.is_master)
1406 ns = ring->head - mq->next_buf;
1407 else
1408 ns = ring_size - mq->next_buf + ring->tail;
1409
1410 if ((mq->next_buf - buf->desc_index) > ns)
1411 return MEMIF_ERR_INVAL_ARG;
1412
1413 mq->next_buf = buf->desc_index;
1414
1415 return MEMIF_ERR_SUCCESS;
1416}
1417
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001418static void
1419memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
1420 memif_buffer_t *buf, uint16_t slot)
1421{
1422 uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
1423 uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
1424 memif_desc_t *from_d, *to_d, tmp_d;
1425
1426 /* Get the descriptors */
1427 from_d = &from_q->ring->desc[buf->desc_index & from_mask];
1428 to_d = &to_q->ring->desc[slot & to_mask];
1429
1430 /* Swap descriptors */
1431 tmp_d = *from_d;
1432 *from_d = *to_d;
1433 *to_d = tmp_d;
1434
1435 /* Update descriptor index and queue for clients buffer */
1436 buf->desc_index = slot;
1437 buf->queue = to_q;
1438}
1439
1440int
1441memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
1442 memif_buffer_t *buf_b)
1443{
1444 memif_connection_t *c = (memif_connection_t *) conn;
1445 if (EXPECT_FALSE (c == NULL))
1446 return MEMIF_ERR_NOCONN;
1447 if (EXPECT_FALSE (c->args.is_master))
1448 return MEMIF_ERR_INVAL_ARG;
1449 if ((buf_a == NULL) || (buf_b == NULL))
1450 return MEMIF_ERR_INVAL_ARG;
1451
1452 int err;
1453 /* store buf_a information */
1454 uint16_t index_a = buf_a->desc_index;
1455 memif_queue_t *mq_a = buf_a->queue;
1456
1457 /* swap buffers, buf_a was updated with new desc_index and queue */
1458 memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
1459 (memif_queue_t *) buf_b->queue, buf_a,
1460 buf_b->desc_index);
1461
1462 /* update buf_b desc_index and queue */
1463 buf_b->desc_index = index_a;
1464 buf_b->queue = mq_a;
1465
1466 return MEMIF_ERR_SUCCESS;
1467}
1468
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001469int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001470memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
1471 memif_buffer_t * bufs, uint16_t count,
1472 uint16_t * count_out)
1473{
1474 memif_connection_t *c = (memif_connection_t *) conn;
1475 if (EXPECT_FALSE (c == NULL))
1476 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001477 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001478 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001479 if (EXPECT_FALSE (qid >= c->tx_queues_num))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001480 return MEMIF_ERR_QID;
1481 if (EXPECT_FALSE (!count_out))
1482 return MEMIF_ERR_INVAL_ARG;
1483 if (EXPECT_FALSE (c->args.is_master))
1484 return MEMIF_ERR_INVAL_ARG;
1485
1486 memif_queue_t *mq = &c->tx_queues[qid];
1487 memif_ring_t *ring = mq->ring;
1488 memif_buffer_t *b0;
1489 uint16_t mask = (1 << mq->log2_ring_size) - 1;
1490 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001491 uint16_t ns;
1492 memif_queue_t *bmq;
msardara8f554b72018-12-11 18:36:55 +01001493 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001494 *count_out = 0;
1495
1496 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001497
1498 /* can only be called by slave */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001499 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001500
1501 b0 = bufs;
1502
1503 while (count && ns)
1504 {
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001505 /* Swaps the descriptors, updates next_buf pointer and updates client
1506 * memif buffer */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001507
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001508 memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
1509 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001510
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001511 mq->next_buf++; /* mark the buffer as allocated */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001512 count--;
1513 ns--;
1514 b0++;
1515 *count_out += 1;
1516 }
1517
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001518 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1519 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001520
1521 if (count)
1522 {
1523 DBG ("ring buffer full! qid: %u", qid);
1524 err = MEMIF_ERR_NOBUF_RING;
1525 }
1526
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001527 return err;
1528}
1529
1530int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001531memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
1532 memif_buffer_t * bufs, uint16_t count,
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001533 uint16_t * count_out, uint16_t size)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001534{
1535 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001536 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001537 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001538 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001539 return MEMIF_ERR_DISCONNECTED;
1540 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001541 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1542 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001543 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001544 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001545 if (EXPECT_FALSE (!count_out))
1546 return MEMIF_ERR_INVAL_ARG;
1547
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001548 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001549 memif_queue_t *mq = &c->tx_queues[qid];
1550 memif_ring_t *ring = mq->ring;
msardara8f554b72018-12-11 18:36:55 +01001551 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001552 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Chun Li5dca5462018-02-07 09:51:35 +08001553 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001554 uint16_t ns;
msardara8f554b72018-12-11 18:36:55 +01001555 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001556 uint16_t dst_left, src_left;
mblya9087792023-12-05 09:36:49 -08001557 uint16_t saved_count_out, delta_count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001558 uint16_t saved_next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001559 memif_buffer_t *saved_b;
1560 *count_out = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001561
Chun Li5dca5462018-02-07 09:51:35 +08001562 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001563
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001564 if (c->args.is_master)
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001565 ns = ring->head - mq->next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001566 else
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001567 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar04b68bd2017-10-30 10:34:54 +01001568
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001569 while (count && ns)
1570 {
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001571 b0 = (bufs + *count_out);
1572
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001573 saved_b = b0;
mblya9087792023-12-05 09:36:49 -08001574 saved_count_out = *count_out;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001575 saved_next_buf = mq->next_buf;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001576
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001577 b0->desc_index = mq->next_buf;
1578 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciar8caf9ec2021-12-01 09:07:09 +01001579 b0->flags = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001580
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001581 /* slave can produce buffer with original length */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001582 dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
1583 c->run_args.buffer_size;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001584 src_left = size;
1585
1586 while (src_left)
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001587 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001588 if (EXPECT_FALSE (dst_left == 0))
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001589 {
mblya9087792023-12-05 09:36:49 -08001590 if (ns)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001591 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001592 ring->desc[b0->desc_index & mask].flags |=
1593 MEMIF_DESC_FLAG_NEXT;
1594 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1595
1596 b0 = (bufs + *count_out);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001597 b0->desc_index = mq->next_buf;
1598 dst_left = (c->args.is_master) ?
1599 ring->desc[mq->next_buf & mask].length :
1600 c->run_args.buffer_size;
1601 ring->desc[mq->next_buf & mask].flags = 0;
mblya9087792023-12-05 09:36:49 -08001602 b0->flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001603 }
1604 else
1605 {
1606 /* rollback allocated chain buffers */
mblya9087792023-12-05 09:36:49 -08001607 delta_count = *count_out - saved_count_out;
1608 memset (saved_b, 0, sizeof (memif_buffer_t) * delta_count);
1609 *count_out -= delta_count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001610 mq->next_buf = saved_next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001611 goto no_ns;
1612 }
1613 }
1614 b0->len = memif_min (dst_left, src_left);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001615
1616 /* slave resets buffer offset */
1617 if (c->args.is_master == 0)
1618 {
mblya9087792023-12-05 09:36:49 -08001619 memif_desc_t *d = &ring->desc[mq->next_buf & mask];
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001620 if (ms->get_external_buffer_offset)
1621 d->offset = ms->get_external_buffer_offset (c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001622 else
Mohsin Kazmi8a344842022-07-27 13:43:07 +00001623 d->offset = d->offset - (d->offset % c->run_args.buffer_size);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001624 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001625 b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001626
1627 src_left -= b0->len;
1628 dst_left -= b0->len;
mblya9087792023-12-05 09:36:49 -08001629 *count_out += 1;
1630 mq->next_buf++;
1631 ns--;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001632 }
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001633 count--;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001634 }
1635
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001636no_ns:
1637
mblya9087792023-12-05 09:36:49 -08001638 DBG ("allocated: %u/%u bufs, size: %u. Next buffer pointer %d", *count_out,
1639 count, size, mq->next_buf);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001640
1641 if (count)
1642 {
1643 DBG ("ring buffer full! qid: %u", qid);
1644 err = MEMIF_ERR_NOBUF_RING;
1645 }
1646
1647 return err;
1648}
1649
1650int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001651memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
1652 uint16_t headroom)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001653{
1654 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001655 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001656 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001657 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001658 return MEMIF_ERR_DISCONNECTED;
1659 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001660 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1661 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001662 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001663 return MEMIF_ERR_QID;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001664 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001665 memif_queue_t *mq = &c->rx_queues[qid];
1666 memif_ring_t *ring = mq->ring;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001667 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001668 uint16_t slot, counter = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001669
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001670 if (c->args.is_master)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001671 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001672 MEMIF_MEMORY_BARRIER ();
1673 ring->tail =
1674 (ring->tail + count <=
1675 mq->last_head) ? ring->tail + count : mq->last_head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001676 return MEMIF_ERR_SUCCESS;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001677 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001678
1679 uint16_t head = ring->head;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001680 slot = head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001681 uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001682 count = (count < ns) ? count : ns;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001683
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001684 memif_desc_t *d;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001685 while (counter < count)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001686 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001687 d = &ring->desc[slot & mask];
1688 d->region = 1;
1689 d->length = c->run_args.buffer_size - headroom;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001690 if (ms->get_external_buffer_offset)
1691 d->offset = ms->get_external_buffer_offset (c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001692 else
Mohsin Kazmi8a344842022-07-27 13:43:07 +00001693 d->offset =
1694 d->offset - (d->offset % c->run_args.buffer_size) + headroom;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001695 slot++;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001696 counter++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001697 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001698
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001699 MEMIF_MEMORY_BARRIER ();
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001700 ring->head = slot;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001701
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001702 return MEMIF_ERR_SUCCESS; /* 0 */
1703}
1704
1705int
1706memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
1707 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
1708{
1709 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001710 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001711 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001712 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001713 return MEMIF_ERR_DISCONNECTED;
1714 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001715 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1716 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001717 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001718 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001719 if (EXPECT_FALSE (!tx))
1720 return MEMIF_ERR_INVAL_ARG;
1721
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001722 memif_queue_t *mq = &c->tx_queues[qid];
1723 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001724 uint16_t mask = (1 << mq->log2_ring_size) - 1;
1725 memif_buffer_t *b0;
Jakub Grajciar14217482021-01-14 13:23:48 +01001726 memif_desc_t *d;
1727 int64_t data_offset;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001728 *tx = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001729 int err = MEMIF_ERR_SUCCESS;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001730
1731 if (EXPECT_FALSE (count == 0))
1732 return MEMIF_ERR_SUCCESS;
1733
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001734 uint16_t index;
1735 if (c->args.is_master)
1736 index = ring->tail;
1737 else
1738 index = ring->head;
1739
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001740 while (count)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001741 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001742 b0 = (bufs + *tx);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001743 /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
1744 */
1745 if ((b0->desc_index & mask) != (index & mask))
1746 {
1747 err = MEMIF_ERR_INVAL_ARG;
1748 goto done;
1749 }
Jakub Grajciar14217482021-01-14 13:23:48 +01001750 d = &ring->desc[b0->desc_index & mask];
1751 d->length = b0->len;
Mohsin Kazmi8636a322022-07-18 11:21:05 +00001752 d->flags =
1753 ((b0->flags & MEMIF_BUFFER_FLAG_NEXT) == 1) ? MEMIF_DESC_FLAG_NEXT : 0;
Jakub Grajciar14217482021-01-14 13:23:48 +01001754 if (!c->args.is_master)
1755 {
1756 // reset headroom
Mohsin Kazmi8a344842022-07-27 13:43:07 +00001757 d->offset = d->offset - (d->offset % c->run_args.buffer_size);
Jakub Grajciar14217482021-01-14 13:23:48 +01001758 // calculate offset from user data
1759 data_offset = b0->data - (d->offset + c->regions[d->region].addr);
1760 if (data_offset != 0)
1761 {
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001762 /* verify data offset and buffer length */
Jakub Grajciar14217482021-01-14 13:23:48 +01001763 if ((data_offset < 0) ||
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001764 ((data_offset + b0->len) > c->run_args.buffer_size))
Jakub Grajciar14217482021-01-14 13:23:48 +01001765 {
Nathan Skrzypczak814eee52021-05-07 19:39:07 +02001766 DBG ("slot: %d, data_offset: %ld, length: %d",
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001767 b0->desc_index & mask, data_offset, b0->len);
Jakub Grajciar14217482021-01-14 13:23:48 +01001768 err = MEMIF_ERR_INVAL_ARG;
1769 goto done;
1770 }
1771 d->offset += data_offset;
1772 }
1773 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001774
1775#ifdef MEMIF_DBG_SHM
1776 printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
1777 printf ("data: %p\n",
1778 memif_get_buffer (c, ring, b0->desc_index & mask));
1779 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001780 print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
1781 ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001782#endif /* MEMIF_DBG_SHM */
1783
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001784 *tx += 1;
1785 count--;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001786 index++;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001787 }
1788
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001789done:
Milan Lenco0a47c992017-10-12 14:19:31 +02001790 MEMIF_MEMORY_BARRIER ();
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001791 if (c->args.is_master)
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001792 ring->tail = b0->desc_index + 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001793 else
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001794 ring->head = b0->desc_index + 1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001795
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001796 if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
1797 {
1798 uint64_t a = 1;
1799 int r = write (mq->int_fd, &a, sizeof (a));
1800 if (r < 0)
1801 return MEMIF_ERR_INT_WRITE;
1802 }
1803
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001804 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001805}
1806
1807int
1808memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
1809 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
1810{
1811 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001812 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001813 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001814 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001815 return MEMIF_ERR_DISCONNECTED;
1816 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001817 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1818 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001819 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001820 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001821 if (EXPECT_FALSE (!rx))
1822 return MEMIF_ERR_INVAL_ARG;
1823
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001824 memif_queue_t *mq = &c->rx_queues[qid];
1825 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001826 uint16_t cur_slot, last_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001827 uint16_t ns;
1828 uint16_t mask = (1 << mq->log2_ring_size) - 1;
msardara8f554b72018-12-11 18:36:55 +01001829 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001830 *rx = 0;
1831
1832 uint64_t b;
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001833 ssize_t r;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001834
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001835 cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
1836 last_slot = (c->args.is_master) ? ring->head : ring->tail;
1837 if (cur_slot == last_slot)
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001838 {
1839 r = read (mq->int_fd, &b, sizeof (b));
1840 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1841 return memif_syscall_error_handler (errno);
1842
1843 return MEMIF_ERR_SUCCESS;
1844 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001845
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001846 ns = last_slot - cur_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001847
1848 while (ns && count)
1849 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001850 b0 = (bufs + *rx);
1851
1852 b0->desc_index = cur_slot;
1853 b0->data = memif_get_buffer (c, ring, cur_slot & mask);
1854 b0->len = ring->desc[cur_slot & mask].length;
Jakub Grajciar8caf9ec2021-12-01 09:07:09 +01001855 b0->flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001856 /* slave resets buffer length */
1857 if (c->args.is_master == 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001858 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001859 ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001860 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001861
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001862 if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
1863 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001864 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001865 ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
1866 }
Jakub Grajciar14217482021-01-14 13:23:48 +01001867
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001868 b0->queue = mq;
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02001869#ifdef MEMIF_DBG_SHM
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001870 printf ("data: %p\n", b0->data);
1871 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001872 printf ("queue: %p\n", b0->queue);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001873 print_bytes (b0->data, b0->len, DBG_RX_BUF);
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02001874#endif /* MEMIF_DBG_SHM */
1875 ns--;
1876 *rx += 1;
1877
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001878 count--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001879 cur_slot++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001880 }
1881
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001882 if (c->args.is_master)
1883 mq->last_head = cur_slot;
1884 else
1885 mq->last_tail = cur_slot;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001886
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001887 if (ns)
1888 {
1889 DBG ("not enough buffers!");
1890 return MEMIF_ERR_NOBUF;
1891 }
1892
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001893 r = read (mq->int_fd, &b, sizeof (b));
1894 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1895 return memif_syscall_error_handler (errno);
1896
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001897 return MEMIF_ERR_SUCCESS; /* 0 */
1898}
1899
1900int
1901memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
1902 char *buf, ssize_t buflen)
1903{
1904 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001905 memif_socket_t *ms;
1906 int err = MEMIF_ERR_SUCCESS, i;
1907 ssize_t l0 = 0, l1;
1908
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001909 if (c == NULL)
1910 return MEMIF_ERR_NOCONN;
1911
Jakub Grajciar12df4972019-07-01 14:24:48 +02001912 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001913
1914 l1 = strlen ((char *) c->args.interface_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001915 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001916 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001917 md->if_name =
1918 (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001919 l0 += l1 + 1;
1920 }
1921 else
1922 err = MEMIF_ERR_NOBUF_DET;
1923
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001924 l1 = strlen ((char *) ms->args.app_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001925 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001926 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001927 md->inst_name =
1928 (uint8_t *) strcpy (buf + l0, (char *) ms->args.app_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001929 l0 += l1 + 1;
1930 }
1931 else
1932 err = MEMIF_ERR_NOBUF_DET;
1933
1934 l1 = strlen ((char *) c->remote_if_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001935 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001936 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001937 md->remote_if_name =
1938 (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001939 l0 += l1 + 1;
1940 }
1941 else
1942 err = MEMIF_ERR_NOBUF_DET;
1943
1944 l1 = strlen ((char *) c->remote_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001945 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001946 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001947 md->remote_inst_name =
1948 (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001949 l0 += l1 + 1;
1950 }
1951 else
1952 err = MEMIF_ERR_NOBUF_DET;
1953
1954 md->id = c->args.interface_id;
1955
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001956 if (strlen ((char *) c->args.secret) > 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001957 {
1958 l1 = strlen ((char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02001959 if (l0 + l1 < buflen)
1960 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02001961 md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02001962 l0 += l1 + 1;
1963 }
1964 else
1965 err = MEMIF_ERR_NOBUF_DET;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001966 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001967
1968 md->role = (c->args.is_master) ? 0 : 1;
1969 md->mode = c->args.mode;
1970
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001971 l1 = 108;
Milan Lenco0a47c992017-10-12 14:19:31 +02001972 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001973 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001974 md->socket_path = (uint8_t *) memcpy (buf + l0, ms->args.path, 108);
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001975 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001976 }
1977 else
1978 err = MEMIF_ERR_NOBUF_DET;
1979
Jakub Grajciar568cc462018-09-05 12:11:35 +02001980 l1 = strlen ((char *) c->remote_disconnect_string);
1981 if (l0 + l1 < buflen)
1982 {
1983 md->error =
1984 (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
1985 l0 += l1 + 1;
1986 }
1987 else
1988 err = MEMIF_ERR_NOBUF_DET;
1989
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001990 md->regions_num = c->regions_num;
1991 l1 = sizeof (memif_region_details_t) * md->regions_num;
1992 if (l0 + l1 <= buflen)
1993 {
Koichiro Den33331ed2019-01-03 00:22:24 +09001994 md->regions = (memif_region_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09001995 for (i = 0; i < md->regions_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001996 {
1997 md->regions[i].index = i;
1998 md->regions[i].addr = c->regions[i].addr;
1999 md->regions[i].size = c->regions[i].region_size;
2000 md->regions[i].fd = c->regions[i].fd;
2001 md->regions[i].is_external = c->regions[i].is_external;
2002 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002003 l0 += l1;
2004 }
2005 else
2006 err = MEMIF_ERR_NOBUF_DET;
2007
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002008 md->rx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002009 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2010 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002011
2012 l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2013 if (l0 + l1 <= buflen)
2014 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002015 md->rx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002016 for (i = 0; i < md->rx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002017 {
2018 md->rx_queues[i].region = c->rx_queues[i].region;
2019 md->rx_queues[i].qid = i;
2020 md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2021 md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2022 md->rx_queues[i].head = c->rx_queues[i].ring->head;
2023 md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2024 md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2025 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002026 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002027 }
2028 else
2029 err = MEMIF_ERR_NOBUF_DET;
2030
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002031 md->tx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002032 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2033 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002034
2035 l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2036 if (l0 + l1 <= buflen)
2037 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002038 md->tx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002039 for (i = 0; i < md->tx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002040 {
2041 md->tx_queues[i].region = c->tx_queues[i].region;
2042 md->tx_queues[i].qid = i;
2043 md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2044 md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2045 md->tx_queues[i].head = c->tx_queues[i].ring->head;
2046 md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2047 md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2048 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002049 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002050 }
2051 else
2052 err = MEMIF_ERR_NOBUF_DET;
2053
Jakub Grajciar134f1e02021-01-04 11:10:42 +01002054 /* This is not completely true, clients should relay on
2055 * on_connect/on_disconnect callbacks */
2056 md->link_up_down = (c->control_channel != NULL) ? 1 : 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002057
2058 return err; /* 0 */
2059}
2060
2061int
2062memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2063{
2064 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002065 uint8_t num;
2066
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002067 *efd = -1;
2068 if (c == NULL)
2069 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01002070 if (c->control_channel == NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002071 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002072
2073 num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002074 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2075 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002076 if (qid >= num)
2077 return MEMIF_ERR_QID;
2078
2079 *efd = c->rx_queues[qid].int_fd;
2080
2081 return MEMIF_ERR_SUCCESS;
2082}