blob: 397c2bbce0cd592ef40379f84c5e266c8fcebfde [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
412 /* loop ms->slave_interfaces and request connection for disconnected ones */
413 TAILQ_FOREACH (c, &ms->slave_interfaces, next)
414 {
415 /* connected or connecting */
416 if (c->control_channel != NULL)
417 continue;
418
419 /* ignore errors */
420 memif_request_connection (c);
421 }
422
423 return MEMIF_ERR_SUCCESS;
424}
425
426int
427memif_set_connection_request_timer (memif_socket_handle_t sock,
428 struct itimerspec timer)
429{
430 memif_socket_t *ms = (memif_socket_t *) sock;
431 memif_fd_event_t fde;
432 memif_fd_event_data_t *fdata;
433 void *ctx;
434
435 if (ms == NULL)
436 return MEMIF_ERR_INVAL_ARG;
437
438 if (ms->timer_fd < 0)
439 {
440 /* only create new timer if there is a valid interval */
441 if (timer.it_interval.tv_sec == 0 && timer.it_interval.tv_nsec == 0)
442 return MEMIF_ERR_SUCCESS;
443
444 /* create timerfd */
445 ms->timer_fd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
446 if (ms->timer_fd < 0)
447 return memif_syscall_error_handler (errno);
448
449 /* start listening for events */
450 fdata = ms->args.alloc (sizeof (*fdata));
451 fdata->event_handler = memif_connect_handler;
452 fdata->private_ctx = ms;
453
454 fde.fd = ms->timer_fd;
455 fde.type = MEMIF_FD_EVENT_READ;
456 fde.private_ctx = fdata;
457
458 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
459 ms->args.on_control_fd_update (fde, ctx);
460 }
461
462 ms->args.connection_request_timer = timer;
463
464 /* arm the timer */
465 if (timerfd_settime (ms->timer_fd, 0, &ms->args.connection_request_timer,
466 NULL) < 0)
467 return memif_syscall_error_handler (errno);
468
469 return MEMIF_ERR_SUCCESS;
470}
471
472int
473memif_create_socket (memif_socket_handle_t *sock, memif_socket_args_t *args,
Jakub Grajciar12df4972019-07-01 14:24:48 +0200474 void *private_ctx)
475{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200476 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100477 memif_fd_event_t fde;
478 memif_fd_event_data_t *fdata;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200479 int i, err = MEMIF_ERR_SUCCESS;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100480 void *ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200481
482 /* allocate memif_socket_t */
483 ms = NULL;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100484 if (args->alloc != NULL)
485 ms = args->alloc (sizeof (memif_socket_t));
486 else
487 ms = malloc (sizeof (memif_socket_t));
Jakub Grajciar12df4972019-07-01 14:24:48 +0200488 if (ms == NULL)
489 {
490 err = MEMIF_ERR_NOMEM;
491 goto error;
492 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100493
494 /* default values */
Jakub Grajciar12df4972019-07-01 14:24:48 +0200495 memset (ms, 0, sizeof (memif_socket_t));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100496 ms->epfd = -1;
497 ms->listener_fd = -1;
498 ms->poll_cancel_fd = -1;
499 ms->timer_fd = -1;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200500
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100501 /* copy arguments to internal struct */
502 memcpy (&ms->args, args, sizeof (*args));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100503 ms->private_ctx = private_ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200504
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100505 if (ms->args.alloc == NULL)
506 memif_alloc_register (ms, malloc);
507 if (ms->args.realloc == NULL)
508 memif_realloc_register (ms, realloc);
509 if (ms->args.free == NULL)
510 memif_free_register (ms, free);
511
512 TAILQ_INIT (&ms->master_interfaces);
513 TAILQ_INIT (&ms->slave_interfaces);
514
515 /* FIXME: implement connection request timer */
516
517 /* initialize internal epoll */
518 if (ms->args.on_control_fd_update == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +0200519 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100520 ms->epfd = epoll_create (1);
521 /* register default fd update callback */
522 memif_control_fd_update_register (ms, memif_control_fd_update);
523 ms->poll_cancel_fd = eventfd (0, EFD_NONBLOCK);
524 if (ms->poll_cancel_fd < 0)
525 {
526 err = errno;
527 DBG ("eventfd: %s", strerror (err));
528 return memif_syscall_error_handler (err);
529 }
530 /* add interrupt fd to epfd */
531 fdata = ms->args.alloc (sizeof (*fdata));
532 fdata->event_handler = memif_poll_cancel_handler;
533 fdata->private_ctx = ms;
534
535 fde.fd = ms->poll_cancel_fd;
536 fde.type = MEMIF_FD_EVENT_READ;
537 fde.private_ctx = fdata;
538
539 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
540 ms->args.on_control_fd_update (fde, ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200541 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100542
543 err =
544 memif_set_connection_request_timer (ms, ms->args.connection_request_timer);
545 if (err != MEMIF_ERR_SUCCESS)
546 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200547
548 *sock = ms;
549
550 return err;
551
552error:
553 if (ms != NULL)
554 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100555 ms->args.free (ms);
556 if (ms->epfd != -1)
557 close (ms->epfd);
558 if (ms->poll_cancel_fd != -1)
559 close (ms->poll_cancel_fd);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200560 }
561 return err;
562}
563
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100564memif_socket_handle_t
565memif_get_socket_handle (memif_conn_handle_t conn)
566{
567 memif_connection_t *c = (memif_connection_t *) conn;
568
569 if (c == NULL)
570 return NULL;
571
572 return c->args.socket;
573}
574
575const char *
576memif_get_socket_path (memif_socket_handle_t sock)
577{
578 memif_socket_t *ms = (memif_socket_t *) sock;
579
580 if (ms == NULL)
581 return NULL;
582
583 return ms->args.path;
584}
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200585
586int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100587memif_get_listener_fd (memif_socket_handle_t sock)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200588{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100589 memif_socket_t *ms = (memif_socket_t *) sock;
590
591 if (ms == NULL)
592 return -1;
593
594 return ms->listener_fd;
595}
596
597int
598memif_set_listener_fd (memif_socket_handle_t sock, int fd)
599{
600 memif_socket_t *ms = (memif_socket_t *) sock;
601 memif_fd_event_t fde;
602 memif_fd_event_data_t *fdata;
603 void *ctx;
604
605 if ((ms == NULL) || (fd < 0))
606 return MEMIF_ERR_INVAL_ARG;
607
608 fdata = ms->args.alloc (sizeof (*fdata));
609 if (fdata == NULL)
610 return MEMIF_ERR_NOMEM;
611
612 ms->listener_fd = fd;
613
614 fdata->event_handler = memif_listener_handler;
615 fdata->private_ctx = ms;
616 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
617 /* send fd to epoll */
618 fde.fd = ms->listener_fd;
619 fde.type = MEMIF_FD_EVENT_READ;
620 fde.private_ctx = fdata;
621 ms->args.on_control_fd_update (fde, ctx);
622
623 return MEMIF_ERR_SUCCESS;
624}
625
626int
627memif_create (memif_conn_handle_t *c, memif_conn_args_t *args,
628 memif_connection_update_t *on_connect,
629 memif_connection_update_t *on_disconnect,
630 memif_on_interrupt_t *on_interrupt, void *private_ctx)
631{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200632 int err, index = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200633 memif_connection_t *conn = (memif_connection_t *) * c;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100634 memif_socket_t *ms = (memif_socket_t *) args->socket;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200635
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200636 if (conn != NULL)
637 {
638 DBG ("This handle already points to existing memif.");
639 return MEMIF_ERR_CONN;
640 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200641
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100642 if (ms == NULL)
643 {
644 DBG ("Missing memif socket");
645 return MEMIF_ERR_INVAL_ARG;
646 }
647
648 conn = (memif_connection_t *) ms->args.alloc (sizeof (*conn));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200649 if (conn == NULL)
650 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200651 err = MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200652 goto error;
653 }
654 memset (conn, 0, sizeof (memif_connection_t));
655
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200656 conn->args.interface_id = args->interface_id;
657
658 if (args->log2_ring_size == 0)
659 args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
Damjan Marion6d56fa42017-11-03 12:24:37 +0100660 else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
661 {
662 err = MEMIF_ERR_MAX_RING;
663 goto error;
664 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200665 if (args->buffer_size == 0)
666 args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
667 if (args->num_s2m_rings == 0)
668 args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
669 if (args->num_m2s_rings == 0)
670 args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
671
672 conn->args.num_s2m_rings = args->num_s2m_rings;
673 conn->args.num_m2s_rings = args->num_m2s_rings;
674 conn->args.buffer_size = args->buffer_size;
675 conn->args.log2_ring_size = args->log2_ring_size;
676 conn->args.is_master = args->is_master;
677 conn->args.mode = args->mode;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100678 conn->args.socket = args->socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200679 conn->regions = NULL;
680 conn->tx_queues = NULL;
681 conn->rx_queues = NULL;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100682 conn->control_channel = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200683 conn->on_connect = on_connect;
684 conn->on_disconnect = on_disconnect;
685 conn->on_interrupt = on_interrupt;
686 conn->private_ctx = private_ctx;
687 memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
688
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100689 uint8_t l = sizeof (conn->args.interface_name);
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000690 strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100691 l);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200692
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100693 if ((l = strlen ((char *) args->secret)) > 0)
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000694 strlcpy ((char *) conn->args.secret, (char *) args->secret,
695 sizeof (conn->args.secret));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200696
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100697 if (args->is_master)
698 TAILQ_INSERT_TAIL (&ms->master_interfaces, conn, next);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200699 else
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100700 TAILQ_INSERT_TAIL (&ms->slave_interfaces, conn, next);
701
702 err = memif_request_connection (conn);
703 if (err != MEMIF_ERR_SUCCESS && err != MEMIF_ERR_CONNREFUSED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200704 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100705 if (args->is_master)
706 TAILQ_REMOVE (&ms->master_interfaces, conn, next);
707 else
708 TAILQ_REMOVE (&ms->slave_interfaces, conn, next);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200709 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200710 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200711
Jakub Grajciar12df4972019-07-01 14:24:48 +0200712 *c = conn;
713
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200714 return 0;
715
716error:
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200717 if (conn != NULL)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100718 ms->args.free (conn);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200719 *c = conn = NULL;
720 return err;
721}
722
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200723static inline int
724memif_path_is_abstract (const char *filename)
725{
726 return (filename[0] == '@');
727}
728
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200729int
Jakub Grajciar12df4972019-07-01 14:24:48 +0200730memif_request_connection (memif_conn_handle_t c)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100731{
Jakub Grajciar84b83772019-03-04 12:42:19 +0100732 memif_connection_t *conn = (memif_connection_t *) c;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200733 memif_socket_t *ms;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100734 int err = MEMIF_ERR_SUCCESS;
735 int sockfd = -1;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100736 struct sockaddr_un un = { 0 };
737 struct stat file_stat;
738 int on = 1;
739 memif_control_channel_t *cc = NULL;
740 memif_fd_event_t fde;
741 memif_fd_event_data_t *fdata = NULL;
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200742 int sunlen = sizeof (un);
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100743 void *ctx;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100744
Jakub Grajciar12df4972019-07-01 14:24:48 +0200745 if (conn == NULL)
746 return MEMIF_ERR_NOCONN;
747
748 ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +0200749
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100750 /* if control channel is assigned, the interface is either connected or
751 * connecting */
752 if (conn->control_channel != NULL)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100753 return MEMIF_ERR_ALRCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100754 /* if interface is master and the socket is already listener we are done */
755 if (conn->args.is_master && (ms->listener_fd != -1))
756 return MEMIF_ERR_SUCCESS;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100757
758 sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
759 if (sockfd < 0)
760 {
761 err = memif_syscall_error_handler (errno);
762 goto error;
763 }
764
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100765 un.sun_family = AF_UNIX;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100766
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100767 /* use memcpy to support abstract socket
768 * ms->args.path is already a valid socket path
769 */
770 memcpy (un.sun_path, ms->args.path, sizeof (un.sun_path) - 1);
Jakub Grajciar84b83772019-03-04 12:42:19 +0100771
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100772 /* allocate fd event data */
773 fdata = ms->args.alloc (sizeof (*fdata));
774 if (fdata == NULL)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100775 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100776 err = MEMIF_ERR_NOMEM;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100777 goto error;
778 }
779
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200780 if (memif_path_is_abstract (ms->args.path))
781 {
782 /* Ensure the string is NULL terminated */
783 un.sun_path[sizeof (un.sun_path) - 1] = '\0';
784 /* sunlen is strlen(un.sun_path) + sizeof(un.sun_family) */
785 sunlen = strlen (un.sun_path) + (sizeof (un) - sizeof (un.sun_path));
786 /* Handle abstract socket by converting '@' -> '\0' */
787 un.sun_path[0] = '\0';
788 }
789
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100790 if (conn->args.is_master != 0)
791 {
792 /* Configure socket optins */
793 if (setsockopt (sockfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
794 {
795 err = memif_syscall_error_handler (errno);
796 goto error;
797 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200798 if (bind (sockfd, (struct sockaddr *) &un, sunlen) < 0)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100799 {
800 err = memif_syscall_error_handler (errno);
801 goto error;
802 }
803 if (listen (sockfd, 1) < 0)
804 {
805 err = memif_syscall_error_handler (errno);
806 goto error;
807 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200808 if (!memif_path_is_abstract (ms->args.path))
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100809 {
810 /* Verify that the socket was created */
811 if (stat ((char *) ms->args.path, &file_stat) < 0)
812 {
813 err = memif_syscall_error_handler (errno);
814 goto error;
815 }
816 }
817
818 /* assign listener fd */
819 ms->listener_fd = sockfd;
820
821 fdata->event_handler = memif_listener_handler;
822 fdata->private_ctx = ms;
823 }
824 else
825 {
826 cc = ms->args.alloc (sizeof (*cc));
827 if (cc == NULL)
828 {
829 err = MEMIF_ERR_NOMEM;
830 goto error;
831 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200832 if (connect (sockfd, (struct sockaddr *) &un, sunlen) != 0)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100833 {
834 err = MEMIF_ERR_CONNREFUSED;
835 goto error;
836 }
837
838 /* Create control channel */
839 cc->fd = sockfd;
840 cc->sock = ms;
841 cc->conn = conn;
842 TAILQ_INIT (&cc->msg_queue);
843
844 /* assign control channel to endpoint */
845 conn->control_channel = cc;
846
847 fdata->event_handler = memif_control_channel_handler;
848 fdata->private_ctx = cc;
849 }
850
851 /* if event polling is done internally, send memif socket as context */
852 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
853 /* send fd to epoll */
854 fde.fd = sockfd;
855 fde.type = MEMIF_FD_EVENT_READ;
856 fde.private_ctx = fdata;
857 ms->args.on_control_fd_update (fde, ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200858
859 return err;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100860
861error:
862 if (sockfd > 0)
863 close (sockfd);
864 sockfd = -1;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100865 if (fdata != NULL)
866 ms->args.free (fdata);
867 fdata = NULL;
868 if (cc != NULL)
869 ms->args.free (cc);
870 conn->control_channel = cc = NULL;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100871 return err;
872}
873
874int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100875memif_control_fd_handler (void *ptr, memif_fd_event_type_t events)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200876{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100877 memif_fd_event_data_t *fdata = (memif_fd_event_data_t *) ptr;
msardara8f554b72018-12-11 18:36:55 +0100878
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100879 if (fdata == NULL)
880 return MEMIF_ERR_INVAL_ARG;
msardara8f554b72018-12-11 18:36:55 +0100881
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100882 return fdata->event_handler (events, fdata->private_ctx);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200883}
884
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100885int
886memif_interrupt_handler (memif_fd_event_type_t type, void *private_ctx)
887{
888 memif_interrupt_t *idata = (memif_interrupt_t *) private_ctx;
889
890 if (idata == NULL)
891 return MEMIF_ERR_INVAL_ARG;
892
893 return idata->c->on_interrupt (idata->c, idata->c->private_ctx, idata->qid);
894}
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200895
896int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100897memif_poll_event (memif_socket_handle_t sock, int timeout)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200898{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100899 memif_socket_t *ms = (memif_socket_t *) sock;
msardara8f554b72018-12-11 18:36:55 +0100900 struct epoll_event evt;
901 int en = 0, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100902 memif_fd_event_type_t events = 0;
Milan Lenco0a47c992017-10-12 14:19:31 +0200903 uint64_t counter = 0;
904 ssize_t r = 0;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100905 sigset_t sigset;
906
907 if (ms == NULL)
908 return MEMIF_ERR_INVAL_ARG;
909
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200910 memset (&evt, 0, sizeof (evt));
911 evt.events = EPOLLIN | EPOLLOUT;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200912 sigemptyset (&sigset);
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100913 en = epoll_pwait (ms->epfd, &evt, 1, timeout, &sigset);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200914 if (en < 0)
915 {
Milan Lenco0a47c992017-10-12 14:19:31 +0200916 err = errno;
917 DBG ("epoll_pwait: %s", strerror (err));
918 return memif_syscall_error_handler (err);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200919 }
920 if (en > 0)
921 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200922 if (evt.events & EPOLLIN)
923 events |= MEMIF_FD_EVENT_READ;
924 if (evt.events & EPOLLOUT)
925 events |= MEMIF_FD_EVENT_WRITE;
926 if (evt.events & EPOLLERR)
927 events |= MEMIF_FD_EVENT_ERROR;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100928 return memif_control_fd_handler (evt.data.ptr, events);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200929 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100930 return MEMIF_ERR_SUCCESS;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200931}
932
933int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100934memif_cancel_poll_event (memif_socket_handle_t sock)
Milan Lenco0a47c992017-10-12 14:19:31 +0200935{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100936 memif_socket_t *ms = (memif_socket_t *) sock;
Milan Lenco0a47c992017-10-12 14:19:31 +0200937 uint64_t counter = 1;
938 ssize_t w = 0;
939
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100940 if (ms->poll_cancel_fd == -1)
941 return MEMIF_ERR_INVAL_ARG;
942 w = write (ms->poll_cancel_fd, &counter, sizeof (counter));
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200943 if (w < sizeof (counter))
944 return MEMIF_ERR_INT_WRITE;
945
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100946 return MEMIF_ERR_SUCCESS;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200947}
948
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100949void
950memif_close_queues (memif_socket_t *ms, memif_queue_t *queues, int nqueues)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200951{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100952 memif_fd_event_t fde;
953 memif_queue_t *mq;
954 void *ctx;
955
956 int i;
957 for (i = 0; i < nqueues; i++)
958 {
959 mq = &queues[i];
960 if (mq != NULL)
961 {
962 if (mq->int_fd > 0)
963 {
964 /* Stop listening for events */
965 fde.fd = mq->int_fd;
966 fde.type = MEMIF_FD_EVENT_DEL;
967 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
968 ms->args.on_control_fd_update (fde, ctx);
969 close (mq->int_fd);
970 }
971 mq->int_fd = -1;
972 }
973 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200974}
975
976/* send disconnect msg and close interface */
977int
978memif_disconnect_internal (memif_connection_t * c)
979{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200980 int err = MEMIF_ERR_SUCCESS, i; /* 0 */
981 memif_queue_t *mq;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100982 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
983 memif_fd_event_t fde;
984 void *ctx;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +0200985
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200986 c->on_disconnect ((void *) c, c->private_ctx);
987
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100988 /* Delete control channel */
989 if (c->control_channel != NULL)
990 memif_delete_control_channel (c->control_channel);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200991
992 if (c->tx_queues != NULL)
993 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100994 memif_close_queues (ms, c->tx_queues, c->tx_queues_num);
995 ms->args.free (c->tx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200996 c->tx_queues = NULL;
997 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +0100998 c->tx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200999
1000 if (c->rx_queues != NULL)
1001 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001002 memif_close_queues (ms, c->rx_queues, c->rx_queues_num);
1003 ms->args.free (c->rx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001004 c->rx_queues = NULL;
1005 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001006 c->rx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001007
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001008 /* TODO: Slave reuse regions */
1009
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001010 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001011 {
Jakub Grajciar412e7b62018-09-27 10:26:35 +02001012 if (&c->regions[i] == NULL)
1013 continue;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001014 if (c->regions[i].is_external != 0)
1015 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001016 ms->del_external_region (c->regions[i].addr,
1017 c->regions[i].region_size, c->regions[i].fd,
1018 c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001019 }
1020 else
1021 {
1022 if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1023 return memif_syscall_error_handler (errno);
1024 if (c->regions[i].fd > 0)
1025 close (c->regions[i].fd);
1026 c->regions[i].fd = -1;
1027 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001028 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001029 ms->args.free (c->regions);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001030 c->regions = NULL;
1031 c->regions_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001032
1033 memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1034
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001035 return err;
1036}
1037
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001038const char *
1039memif_get_socket_filename (memif_socket_handle_t sock)
1040{
1041 memif_socket_t *ms = (memif_socket_t *) sock;
1042
1043 if (ms == NULL)
1044 return NULL;
1045
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001046 return (char *) ms->args.path;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001047}
1048
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001049int
Jakub Grajciar12df4972019-07-01 14:24:48 +02001050memif_delete_socket (memif_socket_handle_t * sock)
1051{
1052 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001053 memif_fd_event_t fde;
1054 void *ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001055
1056 /* check if socket is in use */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001057 if (ms == NULL || !TAILQ_EMPTY (&ms->master_interfaces) ||
1058 !TAILQ_EMPTY (&ms->slave_interfaces))
Jakub Grajciar12df4972019-07-01 14:24:48 +02001059 return MEMIF_ERR_INVAL_ARG;
1060
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001061 if (ms->listener_fd > 0)
1062 {
1063 fde.fd = ms->listener_fd;
1064 fde.type = MEMIF_FD_EVENT_DEL;
1065 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1066 ms->args.on_control_fd_update (fde, ctx);
1067 }
1068 ms->listener_fd = -1;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001069
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001070 if (ms->poll_cancel_fd > 0)
1071 {
1072 fde.fd = ms->poll_cancel_fd;
1073 fde.type = MEMIF_FD_EVENT_DEL;
1074 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1075 ms->args.on_control_fd_update (fde, ctx);
1076 }
1077 ms->poll_cancel_fd = -1;
1078
1079 if (ms->epfd > 0)
1080 close (ms->epfd);
1081 ms->epfd = -1;
1082
1083 ms->args.free (ms);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001084 *sock = ms = NULL;
1085
1086 return MEMIF_ERR_SUCCESS;
1087}
1088
1089int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001090memif_delete (memif_conn_handle_t * conn)
1091{
1092 memif_connection_t *c = (memif_connection_t *) * conn;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001093 memif_socket_t *ms;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001094 int err = MEMIF_ERR_SUCCESS;
1095
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001096 if (c == NULL)
1097 {
1098 DBG ("no connection");
1099 return MEMIF_ERR_NOCONN;
1100 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001101
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001102 err = memif_disconnect_internal (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001103
Jakub Grajciar12df4972019-07-01 14:24:48 +02001104 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001105
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001106 if (c->args.is_master)
1107 TAILQ_REMOVE (&ms->master_interfaces, c, next);
1108 else
1109 TAILQ_REMOVE (&ms->slave_interfaces, c, next);
1110 /* TODO: don't listen with empty interface queue */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001111
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001112 ms->args.free (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001113 c = NULL;
1114
1115 *conn = c;
1116 return err;
1117}
1118
1119int
1120memif_connect1 (memif_connection_t * c)
1121{
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001122 memif_socket_t *ms;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001123 memif_region_t *mr;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001124 memif_queue_t *mq;
1125 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001126
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001127 if (c == NULL)
1128 return MEMIF_ERR_INVAL_ARG;
1129
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001130 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001131
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001132 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001133 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001134 mr = &c->regions[i];
1135 if (mr != NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001136 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001137 if (!mr->addr)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001138 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001139 if (mr->is_external)
1140 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001141 if (ms->get_external_region_addr == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001142 return MEMIF_ERR_INVAL_ARG;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001143 mr->addr = ms->get_external_region_addr (
1144 mr->region_size, mr->fd, c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001145 }
1146 else
1147 {
1148 if (mr->fd < 0)
1149 return MEMIF_ERR_NO_SHMFD;
1150
1151 if ((mr->addr =
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001152 mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1153 MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001154 {
1155 return memif_syscall_error_handler (errno);
1156 }
1157 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001158 }
1159 }
1160 }
1161
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001162 for (i = 0; i < c->rx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001163 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001164 mq = &c->rx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001165 if (mq != NULL)
1166 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001167 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001168 if (mq->ring->cookie != MEMIF_COOKIE)
1169 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001170 DBG ("wrong cookie on rx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001171 return MEMIF_ERR_COOKIE;
1172 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001173 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001174 }
1175 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001176
1177 for (i = 0; i < c->tx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001178 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001179 mq = &c->tx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001180 if (mq != NULL)
1181 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001182 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001183 if (mq->ring->cookie != MEMIF_COOKIE)
1184 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001185 DBG ("wrong cookie on tx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001186 return MEMIF_ERR_COOKIE;
1187 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001188 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001189 }
1190 }
1191
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001192 return 0;
1193}
1194
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001195static inline int
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001196memif_add_region (memif_connection_t *conn, uint8_t has_buffers)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001197{
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001198 memif_region_t *r;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001199 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001200
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001201 r = ms->args.realloc (conn->regions,
1202 sizeof (memif_region_t) * ++conn->regions_num);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001203 if (r == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001204 return MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001205
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001206 conn->regions = r;
1207 r = &conn->regions[conn->regions_num - 1];
1208 memset (r, 0, sizeof (memif_region_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001209
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001210 if (has_buffers != 0)
1211 {
1212 r->buffer_offset = 0;
1213 }
1214 else
1215 {
1216 r->buffer_offset =
1217 (conn->run_args.num_s2m_rings +
1218 conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1219 sizeof (memif_desc_t) *
Jakub Grajciar568cc462018-09-05 12:11:35 +02001220 (1 << conn->
1221 run_args.log2_ring_size));
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001222 }
1223
1224 r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001225 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1226 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1227
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001228 if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001229 return memif_syscall_error_handler (errno);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001230
1231 if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1232 return memif_syscall_error_handler (errno);
1233
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001234 if ((ftruncate (r->fd, r->region_size)) == -1)
1235 return memif_syscall_error_handler (errno);
1236
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001237 if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1238 MAP_SHARED, r->fd, 0)) == MAP_FAILED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001239 return memif_syscall_error_handler (errno);
1240
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001241 return MEMIF_ERR_SUCCESS;
1242}
1243
1244static inline int
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001245memif_init_queues (memif_connection_t *conn)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001246{
1247 int i, j;
1248 memif_ring_t *ring;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001249 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001250
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001251 for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1252 {
1253 ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1254 DBG ("RING: %p I: %d", ring, i);
1255 ring->head = ring->tail = 0;
1256 ring->cookie = MEMIF_COOKIE;
1257 ring->flags = 0;
1258 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1259 {
1260 uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001261 ring->desc[j].region = 1;
1262 ring->desc[j].offset =
1263 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001264 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001265 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001266 }
1267 }
1268 for (i = 0; i < conn->run_args.num_m2s_rings; i++)
1269 {
1270 ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
1271 DBG ("RING: %p I: %d", ring, i);
1272 ring->head = ring->tail = 0;
1273 ring->cookie = MEMIF_COOKIE;
1274 ring->flags = 0;
1275 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1276 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001277 uint16_t slot = (i + conn->run_args.num_s2m_rings) *
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001278 (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001279 ring->desc[j].region = 1;
1280 ring->desc[j].offset =
1281 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001282 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001283 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001284 }
1285 }
1286 memif_queue_t *mq;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001287 mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1288 conn->run_args.num_s2m_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001289 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001290 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001291
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001292 int x;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001293
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001294 for (x = 0; x < conn->run_args.num_s2m_rings; x++)
1295 {
1296 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1297 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001298
1299 mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
1300 DBG ("RING: %p I: %d", mq[x].ring, x);
1301 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1302 mq[x].region = 0;
1303 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001304 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1305 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001306 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001307 }
1308 conn->tx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001309 conn->tx_queues_num = conn->run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001310
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001311 mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1312 conn->run_args.num_m2s_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001313 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001314 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001315
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001316 for (x = 0; x < conn->run_args.num_m2s_rings; x++)
1317 {
1318 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1319 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001320
1321 mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
1322 DBG ("RING: %p I: %d", mq[x].ring, x);
1323 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1324 mq[x].region = 0;
1325 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001326 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1327 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001328 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001329 }
1330 conn->rx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001331 conn->rx_queues_num = conn->run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001332
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001333 return MEMIF_ERR_SUCCESS;
1334}
1335
1336int
1337memif_init_regions_and_queues (memif_connection_t * conn)
1338{
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001339 memif_region_t *r;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001340 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001341
1342 /* region 0. rings */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001343 memif_add_region (conn, /* has_buffers */ 0);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001344
1345 /* region 1. buffers */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001346 if (ms->add_external_region)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001347 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001348 r = (memif_region_t *) ms->args.realloc (
1349 conn->regions, sizeof (memif_region_t) * ++conn->regions_num);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001350 if (r == NULL)
1351 return MEMIF_ERR_NOMEM;
1352 conn->regions = r;
1353
1354 conn->regions[1].region_size =
1355 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1356 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1357 conn->regions[1].buffer_offset = 0;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001358 ms->add_external_region (&conn->regions[1].addr,
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001359 conn->regions[1].region_size,
1360 &conn->regions[1].fd, conn->private_ctx);
1361 conn->regions[1].is_external = 1;
1362 }
1363 else
1364 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001365 memif_add_region (conn, 1);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001366 }
1367
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001368 memif_init_queues (conn);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001369
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001370 return 0;
1371}
1372
Jakub Grajciar47e68de2021-01-08 15:32:43 +01001373int
1374memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
1375 memif_buffer_t *buf)
1376{
1377 memif_connection_t *c = (memif_connection_t *) conn;
1378 if (EXPECT_FALSE (c == NULL))
1379 return MEMIF_ERR_NOCONN;
1380 if (EXPECT_FALSE (qid >= c->tx_queues_num))
1381 return MEMIF_ERR_QID;
1382 if (EXPECT_FALSE (buf == NULL))
1383 return MEMIF_ERR_INVAL_ARG;
1384
1385 uint16_t ring_size, ns;
1386 memif_queue_t *mq = &c->tx_queues[qid];
1387 memif_ring_t *ring = mq->ring;
1388
1389 ring_size = (1 << mq->log2_ring_size);
1390 if (c->args.is_master)
1391 ns = ring->head - mq->next_buf;
1392 else
1393 ns = ring_size - mq->next_buf + ring->tail;
1394
1395 if ((mq->next_buf - buf->desc_index) > ns)
1396 return MEMIF_ERR_INVAL_ARG;
1397
1398 mq->next_buf = buf->desc_index;
1399
1400 return MEMIF_ERR_SUCCESS;
1401}
1402
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001403static void
1404memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
1405 memif_buffer_t *buf, uint16_t slot)
1406{
1407 uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
1408 uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
1409 memif_desc_t *from_d, *to_d, tmp_d;
1410
1411 /* Get the descriptors */
1412 from_d = &from_q->ring->desc[buf->desc_index & from_mask];
1413 to_d = &to_q->ring->desc[slot & to_mask];
1414
1415 /* Swap descriptors */
1416 tmp_d = *from_d;
1417 *from_d = *to_d;
1418 *to_d = tmp_d;
1419
1420 /* Update descriptor index and queue for clients buffer */
1421 buf->desc_index = slot;
1422 buf->queue = to_q;
1423}
1424
1425int
1426memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
1427 memif_buffer_t *buf_b)
1428{
1429 memif_connection_t *c = (memif_connection_t *) conn;
1430 if (EXPECT_FALSE (c == NULL))
1431 return MEMIF_ERR_NOCONN;
1432 if (EXPECT_FALSE (c->args.is_master))
1433 return MEMIF_ERR_INVAL_ARG;
1434 if ((buf_a == NULL) || (buf_b == NULL))
1435 return MEMIF_ERR_INVAL_ARG;
1436
1437 int err;
1438 /* store buf_a information */
1439 uint16_t index_a = buf_a->desc_index;
1440 memif_queue_t *mq_a = buf_a->queue;
1441
1442 /* swap buffers, buf_a was updated with new desc_index and queue */
1443 memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
1444 (memif_queue_t *) buf_b->queue, buf_a,
1445 buf_b->desc_index);
1446
1447 /* update buf_b desc_index and queue */
1448 buf_b->desc_index = index_a;
1449 buf_b->queue = mq_a;
1450
1451 return MEMIF_ERR_SUCCESS;
1452}
1453
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001454int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001455memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
1456 memif_buffer_t * bufs, uint16_t count,
1457 uint16_t * count_out)
1458{
1459 memif_connection_t *c = (memif_connection_t *) conn;
1460 if (EXPECT_FALSE (c == NULL))
1461 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001462 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001463 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001464 if (EXPECT_FALSE (qid >= c->tx_queues_num))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001465 return MEMIF_ERR_QID;
1466 if (EXPECT_FALSE (!count_out))
1467 return MEMIF_ERR_INVAL_ARG;
1468 if (EXPECT_FALSE (c->args.is_master))
1469 return MEMIF_ERR_INVAL_ARG;
1470
1471 memif_queue_t *mq = &c->tx_queues[qid];
1472 memif_ring_t *ring = mq->ring;
1473 memif_buffer_t *b0;
1474 uint16_t mask = (1 << mq->log2_ring_size) - 1;
1475 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001476 uint16_t ns;
1477 memif_queue_t *bmq;
msardara8f554b72018-12-11 18:36:55 +01001478 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001479 *count_out = 0;
1480
1481 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001482
1483 /* can only be called by slave */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001484 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001485
1486 b0 = bufs;
1487
1488 while (count && ns)
1489 {
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001490 /* Swaps the descriptors, updates next_buf pointer and updates client
1491 * memif buffer */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001492
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001493 memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
1494 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001495
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001496 mq->next_buf++; /* mark the buffer as allocated */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001497 count--;
1498 ns--;
1499 b0++;
1500 *count_out += 1;
1501 }
1502
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001503 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1504 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001505
1506 if (count)
1507 {
1508 DBG ("ring buffer full! qid: %u", qid);
1509 err = MEMIF_ERR_NOBUF_RING;
1510 }
1511
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001512 return err;
1513}
1514
1515int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001516memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
1517 memif_buffer_t * bufs, uint16_t count,
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001518 uint16_t * count_out, uint16_t size)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001519{
1520 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001521 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001522 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001523 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001524 return MEMIF_ERR_DISCONNECTED;
1525 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001526 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1527 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001528 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001529 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001530 if (EXPECT_FALSE (!count_out))
1531 return MEMIF_ERR_INVAL_ARG;
1532
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001533 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001534 memif_queue_t *mq = &c->tx_queues[qid];
1535 memif_ring_t *ring = mq->ring;
msardara8f554b72018-12-11 18:36:55 +01001536 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001537 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001538 uint32_t offset_mask = c->run_args.buffer_size - 1;
Chun Li5dca5462018-02-07 09:51:35 +08001539 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001540 uint16_t ns;
msardara8f554b72018-12-11 18:36:55 +01001541 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001542 uint16_t dst_left, src_left;
1543 uint16_t saved_count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001544 uint16_t saved_next_buf;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001545 uint16_t slot;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001546 memif_buffer_t *saved_b;
1547 *count_out = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001548
Chun Li5dca5462018-02-07 09:51:35 +08001549 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001550
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001551 if (c->args.is_master)
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001552 ns = ring->head - mq->next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001553 else
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001554 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar04b68bd2017-10-30 10:34:54 +01001555
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001556 while (count && ns)
1557 {
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001558 b0 = (bufs + *count_out);
1559
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001560 saved_b = b0;
1561 saved_count = count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001562 saved_next_buf = mq->next_buf;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001563
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001564 b0->desc_index = mq->next_buf;
1565 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciar8caf9ec2021-12-01 09:07:09 +01001566 b0->flags = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001567
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001568 /* slave can produce buffer with original length */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001569 dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
1570 c->run_args.buffer_size;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001571 src_left = size;
1572
1573 while (src_left)
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001574 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001575 if (EXPECT_FALSE (dst_left == 0))
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001576 {
1577 if (count && ns)
1578 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001579 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001580 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001581 ns--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001582
1583 ring->desc[b0->desc_index & mask].flags |=
1584 MEMIF_DESC_FLAG_NEXT;
1585 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1586
1587 b0 = (bufs + *count_out);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001588 b0->desc_index = mq->next_buf;
1589 dst_left = (c->args.is_master) ?
1590 ring->desc[mq->next_buf & mask].length :
1591 c->run_args.buffer_size;
1592 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001593 }
1594 else
1595 {
1596 /* rollback allocated chain buffers */
1597 memset (saved_b, 0, sizeof (memif_buffer_t)
1598 * (saved_count - count + 1));
1599 *count_out -= saved_count - count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001600 mq->next_buf = saved_next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001601 goto no_ns;
1602 }
1603 }
1604 b0->len = memif_min (dst_left, src_left);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001605
1606 /* slave resets buffer offset */
1607 if (c->args.is_master == 0)
1608 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001609 memif_desc_t *d = &ring->desc[slot & mask];
1610 if (ms->get_external_buffer_offset)
1611 d->offset = ms->get_external_buffer_offset (c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001612 else
1613 d->offset = d->offset - (d->offset & offset_mask);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001614 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001615 b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001616
1617 src_left -= b0->len;
1618 dst_left -= b0->len;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001619 }
1620
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001621 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001622 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001623 ns--;
1624 count--;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001625 }
1626
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001627no_ns:
1628
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001629 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1630 mq->next_buf);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001631
1632 if (count)
1633 {
1634 DBG ("ring buffer full! qid: %u", qid);
1635 err = MEMIF_ERR_NOBUF_RING;
1636 }
1637
1638 return err;
1639}
1640
1641int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001642memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
1643 uint16_t headroom)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001644{
1645 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001646 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001647 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001648 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001649 return MEMIF_ERR_DISCONNECTED;
1650 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001651 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1652 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001653 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001654 return MEMIF_ERR_QID;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001655 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001656 memif_queue_t *mq = &c->rx_queues[qid];
1657 memif_ring_t *ring = mq->ring;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001658 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001659 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001660 uint16_t slot, counter = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001661
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001662 if (c->args.is_master)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001663 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001664 MEMIF_MEMORY_BARRIER ();
1665 ring->tail =
1666 (ring->tail + count <=
1667 mq->last_head) ? ring->tail + count : mq->last_head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001668 return MEMIF_ERR_SUCCESS;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001669 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001670
1671 uint16_t head = ring->head;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001672 slot = head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001673 uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001674 count = (count < ns) ? count : ns;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001675
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001676 memif_desc_t *d;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001677 while (counter < count)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001678 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001679 d = &ring->desc[slot & mask];
1680 d->region = 1;
1681 d->length = c->run_args.buffer_size - headroom;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001682 if (ms->get_external_buffer_offset)
1683 d->offset = ms->get_external_buffer_offset (c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001684 else
1685 d->offset = d->offset - (d->offset & offset_mask) + headroom;
1686 slot++;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001687 counter++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001688 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001689
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001690 MEMIF_MEMORY_BARRIER ();
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001691 ring->head = slot;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001692
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001693 return MEMIF_ERR_SUCCESS; /* 0 */
1694}
1695
1696int
1697memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
1698 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
1699{
1700 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001701 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001702 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001703 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001704 return MEMIF_ERR_DISCONNECTED;
1705 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001706 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1707 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001708 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001709 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001710 if (EXPECT_FALSE (!tx))
1711 return MEMIF_ERR_INVAL_ARG;
1712
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001713 memif_queue_t *mq = &c->tx_queues[qid];
1714 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001715 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar14217482021-01-14 13:23:48 +01001716 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001717 memif_buffer_t *b0;
Jakub Grajciar14217482021-01-14 13:23:48 +01001718 memif_desc_t *d;
1719 int64_t data_offset;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001720 *tx = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001721 int err = MEMIF_ERR_SUCCESS;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001722
1723 if (EXPECT_FALSE (count == 0))
1724 return MEMIF_ERR_SUCCESS;
1725
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001726 uint16_t index;
1727 if (c->args.is_master)
1728 index = ring->tail;
1729 else
1730 index = ring->head;
1731
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001732 while (count)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001733 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001734 b0 = (bufs + *tx);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001735 /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
1736 */
1737 if ((b0->desc_index & mask) != (index & mask))
1738 {
1739 err = MEMIF_ERR_INVAL_ARG;
1740 goto done;
1741 }
Jakub Grajciar14217482021-01-14 13:23:48 +01001742 d = &ring->desc[b0->desc_index & mask];
1743 d->length = b0->len;
1744 if (!c->args.is_master)
1745 {
1746 // reset headroom
1747 d->offset = d->offset - (d->offset & offset_mask);
1748 // calculate offset from user data
1749 data_offset = b0->data - (d->offset + c->regions[d->region].addr);
1750 if (data_offset != 0)
1751 {
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001752 /* verify data offset and buffer length */
Jakub Grajciar14217482021-01-14 13:23:48 +01001753 if ((data_offset < 0) ||
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001754 ((data_offset + b0->len) > c->run_args.buffer_size))
Jakub Grajciar14217482021-01-14 13:23:48 +01001755 {
Nathan Skrzypczak814eee52021-05-07 19:39:07 +02001756 DBG ("slot: %d, data_offset: %ld, length: %d",
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001757 b0->desc_index & mask, data_offset, b0->len);
Jakub Grajciar14217482021-01-14 13:23:48 +01001758 err = MEMIF_ERR_INVAL_ARG;
1759 goto done;
1760 }
1761 d->offset += data_offset;
1762 }
1763 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001764
1765#ifdef MEMIF_DBG_SHM
1766 printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
1767 printf ("data: %p\n",
1768 memif_get_buffer (c, ring, b0->desc_index & mask));
1769 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001770 print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
1771 ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001772#endif /* MEMIF_DBG_SHM */
1773
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001774 *tx += 1;
1775 count--;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001776 index++;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001777 }
1778
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001779done:
Milan Lenco0a47c992017-10-12 14:19:31 +02001780 MEMIF_MEMORY_BARRIER ();
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001781 if (c->args.is_master)
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001782 ring->tail = b0->desc_index + 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001783 else
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001784 ring->head = b0->desc_index + 1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001785
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001786 if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
1787 {
1788 uint64_t a = 1;
1789 int r = write (mq->int_fd, &a, sizeof (a));
1790 if (r < 0)
1791 return MEMIF_ERR_INT_WRITE;
1792 }
1793
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001794 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001795}
1796
1797int
1798memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
1799 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
1800{
1801 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001802 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001803 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001804 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001805 return MEMIF_ERR_DISCONNECTED;
1806 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001807 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1808 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001809 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001810 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001811 if (EXPECT_FALSE (!rx))
1812 return MEMIF_ERR_INVAL_ARG;
1813
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001814 memif_queue_t *mq = &c->rx_queues[qid];
1815 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001816 uint16_t cur_slot, last_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001817 uint16_t ns;
1818 uint16_t mask = (1 << mq->log2_ring_size) - 1;
msardara8f554b72018-12-11 18:36:55 +01001819 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001820 *rx = 0;
1821
1822 uint64_t b;
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001823 ssize_t r;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001824
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001825 cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
1826 last_slot = (c->args.is_master) ? ring->head : ring->tail;
1827 if (cur_slot == last_slot)
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001828 {
1829 r = read (mq->int_fd, &b, sizeof (b));
1830 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1831 return memif_syscall_error_handler (errno);
1832
1833 return MEMIF_ERR_SUCCESS;
1834 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001835
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001836 ns = last_slot - cur_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001837
1838 while (ns && count)
1839 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001840 b0 = (bufs + *rx);
1841
1842 b0->desc_index = cur_slot;
1843 b0->data = memif_get_buffer (c, ring, cur_slot & mask);
1844 b0->len = ring->desc[cur_slot & mask].length;
Jakub Grajciar8caf9ec2021-12-01 09:07:09 +01001845 b0->flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001846 /* slave resets buffer length */
1847 if (c->args.is_master == 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001848 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001849 ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001850 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001851
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001852 if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
1853 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001854 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001855 ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
1856 }
Jakub Grajciar14217482021-01-14 13:23:48 +01001857
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001858 b0->queue = mq;
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02001859#ifdef MEMIF_DBG_SHM
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001860 printf ("data: %p\n", b0->data);
1861 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001862 printf ("queue: %p\n", b0->queue);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001863 print_bytes (b0->data, b0->len, DBG_RX_BUF);
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02001864#endif /* MEMIF_DBG_SHM */
1865 ns--;
1866 *rx += 1;
1867
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001868 count--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001869 cur_slot++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001870 }
1871
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001872 if (c->args.is_master)
1873 mq->last_head = cur_slot;
1874 else
1875 mq->last_tail = cur_slot;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001876
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001877 if (ns)
1878 {
1879 DBG ("not enough buffers!");
1880 return MEMIF_ERR_NOBUF;
1881 }
1882
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001883 r = read (mq->int_fd, &b, sizeof (b));
1884 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1885 return memif_syscall_error_handler (errno);
1886
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001887 return MEMIF_ERR_SUCCESS; /* 0 */
1888}
1889
1890int
1891memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
1892 char *buf, ssize_t buflen)
1893{
1894 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001895 memif_socket_t *ms;
1896 int err = MEMIF_ERR_SUCCESS, i;
1897 ssize_t l0 = 0, l1;
1898
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001899 if (c == NULL)
1900 return MEMIF_ERR_NOCONN;
1901
Jakub Grajciar12df4972019-07-01 14:24:48 +02001902 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001903
1904 l1 = strlen ((char *) c->args.interface_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001905 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001906 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001907 md->if_name =
1908 (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001909 l0 += l1 + 1;
1910 }
1911 else
1912 err = MEMIF_ERR_NOBUF_DET;
1913
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001914 l1 = strlen ((char *) ms->args.app_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001915 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001916 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001917 md->inst_name =
1918 (uint8_t *) strcpy (buf + l0, (char *) ms->args.app_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001919 l0 += l1 + 1;
1920 }
1921 else
1922 err = MEMIF_ERR_NOBUF_DET;
1923
1924 l1 = strlen ((char *) c->remote_if_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001925 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001926 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001927 md->remote_if_name =
1928 (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_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_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_inst_name =
1938 (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001939 l0 += l1 + 1;
1940 }
1941 else
1942 err = MEMIF_ERR_NOBUF_DET;
1943
1944 md->id = c->args.interface_id;
1945
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001946 if (strlen ((char *) c->args.secret) > 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001947 {
1948 l1 = strlen ((char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02001949 if (l0 + l1 < buflen)
1950 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02001951 md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02001952 l0 += l1 + 1;
1953 }
1954 else
1955 err = MEMIF_ERR_NOBUF_DET;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001956 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001957
1958 md->role = (c->args.is_master) ? 0 : 1;
1959 md->mode = c->args.mode;
1960
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001961 l1 = 108;
Milan Lenco0a47c992017-10-12 14:19:31 +02001962 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001963 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001964 md->socket_path = (uint8_t *) memcpy (buf + l0, ms->args.path, 108);
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001965 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001966 }
1967 else
1968 err = MEMIF_ERR_NOBUF_DET;
1969
Jakub Grajciar568cc462018-09-05 12:11:35 +02001970 l1 = strlen ((char *) c->remote_disconnect_string);
1971 if (l0 + l1 < buflen)
1972 {
1973 md->error =
1974 (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
1975 l0 += l1 + 1;
1976 }
1977 else
1978 err = MEMIF_ERR_NOBUF_DET;
1979
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001980 md->regions_num = c->regions_num;
1981 l1 = sizeof (memif_region_details_t) * md->regions_num;
1982 if (l0 + l1 <= buflen)
1983 {
Koichiro Den33331ed2019-01-03 00:22:24 +09001984 md->regions = (memif_region_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09001985 for (i = 0; i < md->regions_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001986 {
1987 md->regions[i].index = i;
1988 md->regions[i].addr = c->regions[i].addr;
1989 md->regions[i].size = c->regions[i].region_size;
1990 md->regions[i].fd = c->regions[i].fd;
1991 md->regions[i].is_external = c->regions[i].is_external;
1992 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001993 l0 += l1;
1994 }
1995 else
1996 err = MEMIF_ERR_NOBUF_DET;
1997
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001998 md->rx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001999 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2000 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002001
2002 l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2003 if (l0 + l1 <= buflen)
2004 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002005 md->rx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002006 for (i = 0; i < md->rx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002007 {
2008 md->rx_queues[i].region = c->rx_queues[i].region;
2009 md->rx_queues[i].qid = i;
2010 md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2011 md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2012 md->rx_queues[i].head = c->rx_queues[i].ring->head;
2013 md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2014 md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2015 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002016 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002017 }
2018 else
2019 err = MEMIF_ERR_NOBUF_DET;
2020
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002021 md->tx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002022 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2023 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002024
2025 l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2026 if (l0 + l1 <= buflen)
2027 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002028 md->tx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002029 for (i = 0; i < md->tx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002030 {
2031 md->tx_queues[i].region = c->tx_queues[i].region;
2032 md->tx_queues[i].qid = i;
2033 md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2034 md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2035 md->tx_queues[i].head = c->tx_queues[i].ring->head;
2036 md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2037 md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2038 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002039 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002040 }
2041 else
2042 err = MEMIF_ERR_NOBUF_DET;
2043
Jakub Grajciar134f1e02021-01-04 11:10:42 +01002044 /* This is not completely true, clients should relay on
2045 * on_connect/on_disconnect callbacks */
2046 md->link_up_down = (c->control_channel != NULL) ? 1 : 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002047
2048 return err; /* 0 */
2049}
2050
2051int
2052memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2053{
2054 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002055 uint8_t num;
2056
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002057 *efd = -1;
2058 if (c == NULL)
2059 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01002060 if (c->control_channel == NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002061 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002062
2063 num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002064 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2065 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002066 if (qid >= num)
2067 return MEMIF_ERR_QID;
2068
2069 *efd = c->rx_queues[qid].int_fd;
2070
2071 return MEMIF_ERR_SUCCESS;
2072}