blob: 2a4cd817a65a340f8f8d038e7d3773d5f8ef2a4d [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;
415 /*
416 Have to read the timer fd else it stays read-ready
417 and makes epoll_pwait() return without sleeping
418 */
419 read (ms->timer_fd, &u64, sizeof (u64));
420 }
421
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100422 /* loop ms->slave_interfaces and request connection for disconnected ones */
423 TAILQ_FOREACH (c, &ms->slave_interfaces, next)
424 {
425 /* connected or connecting */
426 if (c->control_channel != NULL)
427 continue;
428
429 /* ignore errors */
430 memif_request_connection (c);
431 }
432
433 return MEMIF_ERR_SUCCESS;
434}
435
436int
437memif_set_connection_request_timer (memif_socket_handle_t sock,
438 struct itimerspec timer)
439{
440 memif_socket_t *ms = (memif_socket_t *) sock;
441 memif_fd_event_t fde;
442 memif_fd_event_data_t *fdata;
443 void *ctx;
444
445 if (ms == NULL)
446 return MEMIF_ERR_INVAL_ARG;
447
448 if (ms->timer_fd < 0)
449 {
450 /* only create new timer if there is a valid interval */
451 if (timer.it_interval.tv_sec == 0 && timer.it_interval.tv_nsec == 0)
452 return MEMIF_ERR_SUCCESS;
453
454 /* create timerfd */
455 ms->timer_fd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
456 if (ms->timer_fd < 0)
457 return memif_syscall_error_handler (errno);
458
459 /* start listening for events */
460 fdata = ms->args.alloc (sizeof (*fdata));
461 fdata->event_handler = memif_connect_handler;
462 fdata->private_ctx = ms;
463
464 fde.fd = ms->timer_fd;
465 fde.type = MEMIF_FD_EVENT_READ;
466 fde.private_ctx = fdata;
467
468 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
469 ms->args.on_control_fd_update (fde, ctx);
470 }
471
472 ms->args.connection_request_timer = timer;
473
474 /* arm the timer */
475 if (timerfd_settime (ms->timer_fd, 0, &ms->args.connection_request_timer,
476 NULL) < 0)
477 return memif_syscall_error_handler (errno);
478
479 return MEMIF_ERR_SUCCESS;
480}
481
482int
483memif_create_socket (memif_socket_handle_t *sock, memif_socket_args_t *args,
Jakub Grajciar12df4972019-07-01 14:24:48 +0200484 void *private_ctx)
485{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200486 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100487 memif_fd_event_t fde;
488 memif_fd_event_data_t *fdata;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200489 int i, err = MEMIF_ERR_SUCCESS;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100490 void *ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200491
492 /* allocate memif_socket_t */
493 ms = NULL;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100494 if (args->alloc != NULL)
495 ms = args->alloc (sizeof (memif_socket_t));
496 else
497 ms = malloc (sizeof (memif_socket_t));
Jakub Grajciar12df4972019-07-01 14:24:48 +0200498 if (ms == NULL)
499 {
500 err = MEMIF_ERR_NOMEM;
501 goto error;
502 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100503
504 /* default values */
Jakub Grajciar12df4972019-07-01 14:24:48 +0200505 memset (ms, 0, sizeof (memif_socket_t));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100506 ms->epfd = -1;
507 ms->listener_fd = -1;
508 ms->poll_cancel_fd = -1;
509 ms->timer_fd = -1;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200510
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100511 /* copy arguments to internal struct */
512 memcpy (&ms->args, args, sizeof (*args));
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100513 ms->private_ctx = private_ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200514
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100515 if (ms->args.alloc == NULL)
516 memif_alloc_register (ms, malloc);
517 if (ms->args.realloc == NULL)
518 memif_realloc_register (ms, realloc);
519 if (ms->args.free == NULL)
520 memif_free_register (ms, free);
521
522 TAILQ_INIT (&ms->master_interfaces);
523 TAILQ_INIT (&ms->slave_interfaces);
524
525 /* FIXME: implement connection request timer */
526
527 /* initialize internal epoll */
528 if (ms->args.on_control_fd_update == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +0200529 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100530 ms->epfd = epoll_create (1);
531 /* register default fd update callback */
532 memif_control_fd_update_register (ms, memif_control_fd_update);
533 ms->poll_cancel_fd = eventfd (0, EFD_NONBLOCK);
534 if (ms->poll_cancel_fd < 0)
535 {
536 err = errno;
537 DBG ("eventfd: %s", strerror (err));
538 return memif_syscall_error_handler (err);
539 }
540 /* add interrupt fd to epfd */
541 fdata = ms->args.alloc (sizeof (*fdata));
542 fdata->event_handler = memif_poll_cancel_handler;
543 fdata->private_ctx = ms;
544
545 fde.fd = ms->poll_cancel_fd;
546 fde.type = MEMIF_FD_EVENT_READ;
547 fde.private_ctx = fdata;
548
549 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
550 ms->args.on_control_fd_update (fde, ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200551 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100552
553 err =
554 memif_set_connection_request_timer (ms, ms->args.connection_request_timer);
555 if (err != MEMIF_ERR_SUCCESS)
556 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200557
558 *sock = ms;
559
560 return err;
561
562error:
563 if (ms != NULL)
564 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100565 ms->args.free (ms);
566 if (ms->epfd != -1)
567 close (ms->epfd);
568 if (ms->poll_cancel_fd != -1)
569 close (ms->poll_cancel_fd);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200570 }
571 return err;
572}
573
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100574memif_socket_handle_t
575memif_get_socket_handle (memif_conn_handle_t conn)
576{
577 memif_connection_t *c = (memif_connection_t *) conn;
578
579 if (c == NULL)
580 return NULL;
581
582 return c->args.socket;
583}
584
585const char *
586memif_get_socket_path (memif_socket_handle_t sock)
587{
588 memif_socket_t *ms = (memif_socket_t *) sock;
589
590 if (ms == NULL)
591 return NULL;
592
593 return ms->args.path;
594}
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200595
596int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100597memif_get_listener_fd (memif_socket_handle_t sock)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200598{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100599 memif_socket_t *ms = (memif_socket_t *) sock;
600
601 if (ms == NULL)
602 return -1;
603
604 return ms->listener_fd;
605}
606
607int
608memif_set_listener_fd (memif_socket_handle_t sock, int fd)
609{
610 memif_socket_t *ms = (memif_socket_t *) sock;
611 memif_fd_event_t fde;
612 memif_fd_event_data_t *fdata;
613 void *ctx;
614
615 if ((ms == NULL) || (fd < 0))
616 return MEMIF_ERR_INVAL_ARG;
617
618 fdata = ms->args.alloc (sizeof (*fdata));
619 if (fdata == NULL)
620 return MEMIF_ERR_NOMEM;
621
622 ms->listener_fd = fd;
623
624 fdata->event_handler = memif_listener_handler;
625 fdata->private_ctx = ms;
626 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
627 /* send fd to epoll */
628 fde.fd = ms->listener_fd;
629 fde.type = MEMIF_FD_EVENT_READ;
630 fde.private_ctx = fdata;
631 ms->args.on_control_fd_update (fde, ctx);
632
633 return MEMIF_ERR_SUCCESS;
634}
635
636int
637memif_create (memif_conn_handle_t *c, memif_conn_args_t *args,
638 memif_connection_update_t *on_connect,
639 memif_connection_update_t *on_disconnect,
640 memif_on_interrupt_t *on_interrupt, void *private_ctx)
641{
Jakub Grajciar12df4972019-07-01 14:24:48 +0200642 int err, index = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200643 memif_connection_t *conn = (memif_connection_t *) * c;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100644 memif_socket_t *ms = (memif_socket_t *) args->socket;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200645
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200646 if (conn != NULL)
647 {
648 DBG ("This handle already points to existing memif.");
649 return MEMIF_ERR_CONN;
650 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200651
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100652 if (ms == NULL)
653 {
654 DBG ("Missing memif socket");
655 return MEMIF_ERR_INVAL_ARG;
656 }
657
658 conn = (memif_connection_t *) ms->args.alloc (sizeof (*conn));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200659 if (conn == NULL)
660 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +0200661 err = MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200662 goto error;
663 }
664 memset (conn, 0, sizeof (memif_connection_t));
665
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200666 conn->args.interface_id = args->interface_id;
667
668 if (args->log2_ring_size == 0)
669 args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
Damjan Marion6d56fa42017-11-03 12:24:37 +0100670 else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
671 {
672 err = MEMIF_ERR_MAX_RING;
673 goto error;
674 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200675 if (args->buffer_size == 0)
676 args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
677 if (args->num_s2m_rings == 0)
678 args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
679 if (args->num_m2s_rings == 0)
680 args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
681
682 conn->args.num_s2m_rings = args->num_s2m_rings;
683 conn->args.num_m2s_rings = args->num_m2s_rings;
684 conn->args.buffer_size = args->buffer_size;
685 conn->args.log2_ring_size = args->log2_ring_size;
686 conn->args.is_master = args->is_master;
687 conn->args.mode = args->mode;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100688 conn->args.socket = args->socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200689 conn->regions = NULL;
690 conn->tx_queues = NULL;
691 conn->rx_queues = NULL;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100692 conn->control_channel = NULL;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200693 conn->on_connect = on_connect;
694 conn->on_disconnect = on_disconnect;
695 conn->on_interrupt = on_interrupt;
696 conn->private_ctx = private_ctx;
697 memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
698
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100699 uint8_t l = sizeof (conn->args.interface_name);
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000700 strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100701 l);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200702
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100703 if ((l = strlen ((char *) args->secret)) > 0)
Andrew Yourtchenkoe5b7ca42021-01-29 14:18:12 +0000704 strlcpy ((char *) conn->args.secret, (char *) args->secret,
705 sizeof (conn->args.secret));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200706
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100707 if (args->is_master)
708 TAILQ_INSERT_TAIL (&ms->master_interfaces, conn, next);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200709 else
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100710 TAILQ_INSERT_TAIL (&ms->slave_interfaces, conn, next);
711
712 err = memif_request_connection (conn);
713 if (err != MEMIF_ERR_SUCCESS && err != MEMIF_ERR_CONNREFUSED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200714 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100715 if (args->is_master)
716 TAILQ_REMOVE (&ms->master_interfaces, conn, next);
717 else
718 TAILQ_REMOVE (&ms->slave_interfaces, conn, next);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200719 goto error;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200720 }
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200721
Jakub Grajciar12df4972019-07-01 14:24:48 +0200722 *c = conn;
723
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200724 return 0;
725
726error:
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200727 if (conn != NULL)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100728 ms->args.free (conn);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200729 *c = conn = NULL;
730 return err;
731}
732
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200733static inline int
734memif_path_is_abstract (const char *filename)
735{
736 return (filename[0] == '@');
737}
738
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200739int
Jakub Grajciar12df4972019-07-01 14:24:48 +0200740memif_request_connection (memif_conn_handle_t c)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100741{
Jakub Grajciar84b83772019-03-04 12:42:19 +0100742 memif_connection_t *conn = (memif_connection_t *) c;
Jakub Grajciar12df4972019-07-01 14:24:48 +0200743 memif_socket_t *ms;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100744 int err = MEMIF_ERR_SUCCESS;
745 int sockfd = -1;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100746 struct sockaddr_un un = { 0 };
747 struct stat file_stat;
748 int on = 1;
749 memif_control_channel_t *cc = NULL;
750 memif_fd_event_t fde;
751 memif_fd_event_data_t *fdata = NULL;
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200752 int sunlen = sizeof (un);
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100753 void *ctx;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100754
Jakub Grajciar12df4972019-07-01 14:24:48 +0200755 if (conn == NULL)
756 return MEMIF_ERR_NOCONN;
757
758 ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +0200759
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100760 /* if control channel is assigned, the interface is either connected or
761 * connecting */
762 if (conn->control_channel != NULL)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100763 return MEMIF_ERR_ALRCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100764 /* if interface is master and the socket is already listener we are done */
765 if (conn->args.is_master && (ms->listener_fd != -1))
766 return MEMIF_ERR_SUCCESS;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100767
768 sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
769 if (sockfd < 0)
770 {
771 err = memif_syscall_error_handler (errno);
772 goto error;
773 }
774
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100775 un.sun_family = AF_UNIX;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100776
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100777 /* use memcpy to support abstract socket
778 * ms->args.path is already a valid socket path
779 */
780 memcpy (un.sun_path, ms->args.path, sizeof (un.sun_path) - 1);
Jakub Grajciar84b83772019-03-04 12:42:19 +0100781
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100782 /* allocate fd event data */
783 fdata = ms->args.alloc (sizeof (*fdata));
784 if (fdata == NULL)
Jakub Grajciar84b83772019-03-04 12:42:19 +0100785 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100786 err = MEMIF_ERR_NOMEM;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100787 goto error;
788 }
789
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200790 if (memif_path_is_abstract (ms->args.path))
791 {
792 /* Ensure the string is NULL terminated */
793 un.sun_path[sizeof (un.sun_path) - 1] = '\0';
794 /* sunlen is strlen(un.sun_path) + sizeof(un.sun_family) */
795 sunlen = strlen (un.sun_path) + (sizeof (un) - sizeof (un.sun_path));
796 /* Handle abstract socket by converting '@' -> '\0' */
797 un.sun_path[0] = '\0';
798 }
799
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100800 if (conn->args.is_master != 0)
801 {
802 /* Configure socket optins */
803 if (setsockopt (sockfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
804 {
805 err = memif_syscall_error_handler (errno);
806 goto error;
807 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200808 if (bind (sockfd, (struct sockaddr *) &un, sunlen) < 0)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100809 {
810 err = memif_syscall_error_handler (errno);
811 goto error;
812 }
813 if (listen (sockfd, 1) < 0)
814 {
815 err = memif_syscall_error_handler (errno);
816 goto error;
817 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200818 if (!memif_path_is_abstract (ms->args.path))
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100819 {
820 /* Verify that the socket was created */
821 if (stat ((char *) ms->args.path, &file_stat) < 0)
822 {
823 err = memif_syscall_error_handler (errno);
824 goto error;
825 }
826 }
827
828 /* assign listener fd */
829 ms->listener_fd = sockfd;
830
831 fdata->event_handler = memif_listener_handler;
832 fdata->private_ctx = ms;
833 }
834 else
835 {
836 cc = ms->args.alloc (sizeof (*cc));
837 if (cc == NULL)
838 {
839 err = MEMIF_ERR_NOMEM;
840 goto error;
841 }
Nathan Skrzypczak814eee52021-05-07 19:39:07 +0200842 if (connect (sockfd, (struct sockaddr *) &un, sunlen) != 0)
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100843 {
844 err = MEMIF_ERR_CONNREFUSED;
845 goto error;
846 }
847
848 /* Create control channel */
849 cc->fd = sockfd;
850 cc->sock = ms;
851 cc->conn = conn;
852 TAILQ_INIT (&cc->msg_queue);
853
854 /* assign control channel to endpoint */
855 conn->control_channel = cc;
856
857 fdata->event_handler = memif_control_channel_handler;
858 fdata->private_ctx = cc;
859 }
860
861 /* if event polling is done internally, send memif socket as context */
862 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
863 /* send fd to epoll */
864 fde.fd = sockfd;
865 fde.type = MEMIF_FD_EVENT_READ;
866 fde.private_ctx = fdata;
867 ms->args.on_control_fd_update (fde, ctx);
Jakub Grajciar12df4972019-07-01 14:24:48 +0200868
869 return err;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100870
871error:
872 if (sockfd > 0)
873 close (sockfd);
874 sockfd = -1;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100875 if (fdata != NULL)
876 ms->args.free (fdata);
877 fdata = NULL;
878 if (cc != NULL)
879 ms->args.free (cc);
880 conn->control_channel = cc = NULL;
Jakub Grajciar84b83772019-03-04 12:42:19 +0100881 return err;
882}
883
884int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100885memif_control_fd_handler (void *ptr, memif_fd_event_type_t events)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200886{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100887 memif_fd_event_data_t *fdata = (memif_fd_event_data_t *) ptr;
msardara8f554b72018-12-11 18:36:55 +0100888
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100889 if (fdata == NULL)
890 return MEMIF_ERR_INVAL_ARG;
msardara8f554b72018-12-11 18:36:55 +0100891
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100892 return fdata->event_handler (events, fdata->private_ctx);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200893}
894
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100895int
896memif_interrupt_handler (memif_fd_event_type_t type, void *private_ctx)
897{
898 memif_interrupt_t *idata = (memif_interrupt_t *) private_ctx;
899
900 if (idata == NULL)
901 return MEMIF_ERR_INVAL_ARG;
902
903 return idata->c->on_interrupt (idata->c, idata->c->private_ctx, idata->qid);
904}
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200905
906int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100907memif_poll_event (memif_socket_handle_t sock, int timeout)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200908{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100909 memif_socket_t *ms = (memif_socket_t *) sock;
msardara8f554b72018-12-11 18:36:55 +0100910 struct epoll_event evt;
911 int en = 0, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100912 memif_fd_event_type_t events = 0;
Milan Lenco0a47c992017-10-12 14:19:31 +0200913 uint64_t counter = 0;
914 ssize_t r = 0;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100915 sigset_t sigset;
916
917 if (ms == NULL)
918 return MEMIF_ERR_INVAL_ARG;
919
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200920 memset (&evt, 0, sizeof (evt));
921 evt.events = EPOLLIN | EPOLLOUT;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200922 sigemptyset (&sigset);
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100923 en = epoll_pwait (ms->epfd, &evt, 1, timeout, &sigset);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200924 if (en < 0)
925 {
Milan Lenco0a47c992017-10-12 14:19:31 +0200926 err = errno;
927 DBG ("epoll_pwait: %s", strerror (err));
928 return memif_syscall_error_handler (err);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200929 }
930 if (en > 0)
931 {
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200932 if (evt.events & EPOLLIN)
933 events |= MEMIF_FD_EVENT_READ;
934 if (evt.events & EPOLLOUT)
935 events |= MEMIF_FD_EVENT_WRITE;
936 if (evt.events & EPOLLERR)
937 events |= MEMIF_FD_EVENT_ERROR;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100938 return memif_control_fd_handler (evt.data.ptr, events);
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200939 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100940 return MEMIF_ERR_SUCCESS;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200941}
942
943int
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100944memif_cancel_poll_event (memif_socket_handle_t sock)
Milan Lenco0a47c992017-10-12 14:19:31 +0200945{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100946 memif_socket_t *ms = (memif_socket_t *) sock;
Milan Lenco0a47c992017-10-12 14:19:31 +0200947 uint64_t counter = 1;
948 ssize_t w = 0;
949
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100950 if (ms->poll_cancel_fd == -1)
951 return MEMIF_ERR_INVAL_ARG;
952 w = write (ms->poll_cancel_fd, &counter, sizeof (counter));
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200953 if (w < sizeof (counter))
954 return MEMIF_ERR_INT_WRITE;
955
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100956 return MEMIF_ERR_SUCCESS;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200957}
958
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100959void
960memif_close_queues (memif_socket_t *ms, memif_queue_t *queues, int nqueues)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200961{
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100962 memif_fd_event_t fde;
963 memif_queue_t *mq;
964 void *ctx;
965
966 int i;
967 for (i = 0; i < nqueues; i++)
968 {
969 mq = &queues[i];
970 if (mq != NULL)
971 {
972 if (mq->int_fd > 0)
973 {
974 /* Stop listening for events */
975 fde.fd = mq->int_fd;
976 fde.type = MEMIF_FD_EVENT_DEL;
977 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
978 ms->args.on_control_fd_update (fde, ctx);
979 close (mq->int_fd);
980 }
981 mq->int_fd = -1;
982 }
983 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200984}
985
986/* send disconnect msg and close interface */
987int
988memif_disconnect_internal (memif_connection_t * c)
989{
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +0200990 int err = MEMIF_ERR_SUCCESS, i; /* 0 */
991 memif_queue_t *mq;
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100992 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
993 memif_fd_event_t fde;
994 void *ctx;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +0200995
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200996 c->on_disconnect ((void *) c, c->private_ctx);
997
Jakub Grajciar134f1e02021-01-04 11:10:42 +0100998 /* Delete control channel */
999 if (c->control_channel != NULL)
1000 memif_delete_control_channel (c->control_channel);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001001
1002 if (c->tx_queues != NULL)
1003 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001004 memif_close_queues (ms, c->tx_queues, c->tx_queues_num);
1005 ms->args.free (c->tx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001006 c->tx_queues = NULL;
1007 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001008 c->tx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001009
1010 if (c->rx_queues != NULL)
1011 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001012 memif_close_queues (ms, c->rx_queues, c->rx_queues_num);
1013 ms->args.free (c->rx_queues);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001014 c->rx_queues = NULL;
1015 }
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001016 c->rx_queues_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001017
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001018 /* TODO: Slave reuse regions */
1019
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001020 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001021 {
Jakub Grajciar412e7b62018-09-27 10:26:35 +02001022 if (&c->regions[i] == NULL)
1023 continue;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001024 if (c->regions[i].is_external != 0)
1025 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001026 ms->del_external_region (c->regions[i].addr,
1027 c->regions[i].region_size, c->regions[i].fd,
1028 c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001029 }
1030 else
1031 {
1032 if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1033 return memif_syscall_error_handler (errno);
1034 if (c->regions[i].fd > 0)
1035 close (c->regions[i].fd);
1036 c->regions[i].fd = -1;
1037 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001038 }
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001039 ms->args.free (c->regions);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001040 c->regions = NULL;
1041 c->regions_num = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001042
1043 memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1044
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001045 return err;
1046}
1047
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001048const char *
1049memif_get_socket_filename (memif_socket_handle_t sock)
1050{
1051 memif_socket_t *ms = (memif_socket_t *) sock;
1052
1053 if (ms == NULL)
1054 return NULL;
1055
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001056 return (char *) ms->args.path;
Jakub Grajciar17f2a7b2019-07-31 14:40:52 +02001057}
1058
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001059int
Jakub Grajciar12df4972019-07-01 14:24:48 +02001060memif_delete_socket (memif_socket_handle_t * sock)
1061{
1062 memif_socket_t *ms = (memif_socket_t *) * sock;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001063 memif_fd_event_t fde;
1064 void *ctx;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001065
1066 /* check if socket is in use */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001067 if (ms == NULL || !TAILQ_EMPTY (&ms->master_interfaces) ||
1068 !TAILQ_EMPTY (&ms->slave_interfaces))
Jakub Grajciar12df4972019-07-01 14:24:48 +02001069 return MEMIF_ERR_INVAL_ARG;
1070
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001071 if (ms->listener_fd > 0)
1072 {
1073 fde.fd = ms->listener_fd;
1074 fde.type = MEMIF_FD_EVENT_DEL;
1075 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1076 ms->args.on_control_fd_update (fde, ctx);
1077 }
1078 ms->listener_fd = -1;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001079
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001080 if (ms->poll_cancel_fd > 0)
1081 {
1082 fde.fd = ms->poll_cancel_fd;
1083 fde.type = MEMIF_FD_EVENT_DEL;
1084 ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1085 ms->args.on_control_fd_update (fde, ctx);
1086 }
1087 ms->poll_cancel_fd = -1;
1088
1089 if (ms->epfd > 0)
1090 close (ms->epfd);
1091 ms->epfd = -1;
1092
1093 ms->args.free (ms);
Jakub Grajciar12df4972019-07-01 14:24:48 +02001094 *sock = ms = NULL;
1095
1096 return MEMIF_ERR_SUCCESS;
1097}
1098
1099int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001100memif_delete (memif_conn_handle_t * conn)
1101{
1102 memif_connection_t *c = (memif_connection_t *) * conn;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001103 memif_socket_t *ms;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001104 int err = MEMIF_ERR_SUCCESS;
1105
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001106 if (c == NULL)
1107 {
1108 DBG ("no connection");
1109 return MEMIF_ERR_NOCONN;
1110 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001111
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001112 err = memif_disconnect_internal (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001113
Jakub Grajciar12df4972019-07-01 14:24:48 +02001114 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001115
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001116 if (c->args.is_master)
1117 TAILQ_REMOVE (&ms->master_interfaces, c, next);
1118 else
1119 TAILQ_REMOVE (&ms->slave_interfaces, c, next);
1120 /* TODO: don't listen with empty interface queue */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001121
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001122 ms->args.free (c);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001123 c = NULL;
1124
1125 *conn = c;
1126 return err;
1127}
1128
1129int
1130memif_connect1 (memif_connection_t * c)
1131{
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001132 memif_socket_t *ms;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001133 memif_region_t *mr;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001134 memif_queue_t *mq;
1135 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001136
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001137 if (c == NULL)
1138 return MEMIF_ERR_INVAL_ARG;
1139
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001140 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciarbdf3ebe2019-09-09 10:39:08 +02001141
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001142 for (i = 0; i < c->regions_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001143 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001144 mr = &c->regions[i];
1145 if (mr != NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001146 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001147 if (!mr->addr)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001148 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001149 if (mr->is_external)
1150 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001151 if (ms->get_external_region_addr == NULL)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001152 return MEMIF_ERR_INVAL_ARG;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001153 mr->addr = ms->get_external_region_addr (
1154 mr->region_size, mr->fd, c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001155 }
1156 else
1157 {
1158 if (mr->fd < 0)
1159 return MEMIF_ERR_NO_SHMFD;
1160
1161 if ((mr->addr =
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001162 mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1163 MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001164 {
1165 return memif_syscall_error_handler (errno);
1166 }
1167 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001168 }
1169 }
1170 }
1171
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001172 for (i = 0; i < c->rx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001173 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001174 mq = &c->rx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001175 if (mq != NULL)
1176 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001177 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001178 if (mq->ring->cookie != MEMIF_COOKIE)
1179 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001180 DBG ("wrong cookie on rx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001181 return MEMIF_ERR_COOKIE;
1182 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001183 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001184 }
1185 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001186
1187 for (i = 0; i < c->tx_queues_num; i++)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001188 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001189 mq = &c->tx_queues[i];
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001190 if (mq != NULL)
1191 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001192 mq->ring = c->regions[mq->region].addr + mq->offset;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001193 if (mq->ring->cookie != MEMIF_COOKIE)
1194 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001195 DBG ("wrong cookie on tx ring %u", i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001196 return MEMIF_ERR_COOKIE;
1197 }
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001198 mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001199 }
1200 }
1201
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001202 return 0;
1203}
1204
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001205static inline int
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001206memif_add_region (memif_connection_t *conn, uint8_t has_buffers)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001207{
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001208 memif_region_t *r;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001209 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001210
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001211 r = ms->args.realloc (conn->regions,
1212 sizeof (memif_region_t) * ++conn->regions_num);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001213 if (r == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001214 return MEMIF_ERR_NOMEM;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001215
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001216 conn->regions = r;
1217 r = &conn->regions[conn->regions_num - 1];
1218 memset (r, 0, sizeof (memif_region_t));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001219
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001220 if (has_buffers != 0)
1221 {
1222 r->buffer_offset = 0;
1223 }
1224 else
1225 {
1226 r->buffer_offset =
1227 (conn->run_args.num_s2m_rings +
1228 conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1229 sizeof (memif_desc_t) *
Jakub Grajciar568cc462018-09-05 12:11:35 +02001230 (1 << conn->
1231 run_args.log2_ring_size));
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001232 }
1233
1234 r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001235 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1236 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1237
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001238 if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001239 return memif_syscall_error_handler (errno);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001240
1241 if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1242 return memif_syscall_error_handler (errno);
1243
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001244 if ((ftruncate (r->fd, r->region_size)) == -1)
1245 return memif_syscall_error_handler (errno);
1246
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001247 if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1248 MAP_SHARED, r->fd, 0)) == MAP_FAILED)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001249 return memif_syscall_error_handler (errno);
1250
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001251 return MEMIF_ERR_SUCCESS;
1252}
1253
1254static inline int
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001255memif_init_queues (memif_connection_t *conn)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001256{
1257 int i, j;
1258 memif_ring_t *ring;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001259 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001260
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001261 for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1262 {
1263 ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1264 DBG ("RING: %p I: %d", ring, i);
1265 ring->head = ring->tail = 0;
1266 ring->cookie = MEMIF_COOKIE;
1267 ring->flags = 0;
1268 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1269 {
1270 uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001271 ring->desc[j].region = 1;
1272 ring->desc[j].offset =
1273 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001274 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001275 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001276 }
1277 }
1278 for (i = 0; i < conn->run_args.num_m2s_rings; i++)
1279 {
1280 ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
1281 DBG ("RING: %p I: %d", ring, i);
1282 ring->head = ring->tail = 0;
1283 ring->cookie = MEMIF_COOKIE;
1284 ring->flags = 0;
1285 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1286 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001287 uint16_t slot = (i + conn->run_args.num_s2m_rings) *
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001288 (1 << conn->run_args.log2_ring_size) + j;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001289 ring->desc[j].region = 1;
1290 ring->desc[j].offset =
1291 conn->regions[1].buffer_offset +
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001292 (uint32_t) (slot * conn->run_args.buffer_size);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001293 ring->desc[j].length = conn->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001294 }
1295 }
1296 memif_queue_t *mq;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001297 mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1298 conn->run_args.num_s2m_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001299 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001300 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001301
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001302 int x;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001303
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001304 for (x = 0; x < conn->run_args.num_s2m_rings; x++)
1305 {
1306 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1307 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001308
1309 mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
1310 DBG ("RING: %p I: %d", mq[x].ring, x);
1311 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1312 mq[x].region = 0;
1313 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001314 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1315 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001316 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001317 }
1318 conn->tx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001319 conn->tx_queues_num = conn->run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001320
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001321 mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1322 conn->run_args.num_m2s_rings);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001323 if (mq == NULL)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001324 return MEMIF_ERR_NOMEM;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001325
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001326 for (x = 0; x < conn->run_args.num_m2s_rings; x++)
1327 {
1328 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1329 return memif_syscall_error_handler (errno);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001330
1331 mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
1332 DBG ("RING: %p I: %d", mq[x].ring, x);
1333 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1334 mq[x].region = 0;
1335 mq[x].offset =
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001336 (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1337 mq[x].last_head = mq[x].last_tail = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001338 mq[x].next_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001339 }
1340 conn->rx_queues = mq;
Jakub Grajciar718a19b2019-11-05 10:58:00 +01001341 conn->rx_queues_num = conn->run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001342
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001343 return MEMIF_ERR_SUCCESS;
1344}
1345
1346int
1347memif_init_regions_and_queues (memif_connection_t * conn)
1348{
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001349 memif_region_t *r;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001350 memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001351
1352 /* region 0. rings */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001353 memif_add_region (conn, /* has_buffers */ 0);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001354
1355 /* region 1. buffers */
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001356 if (ms->add_external_region)
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001357 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001358 r = (memif_region_t *) ms->args.realloc (
1359 conn->regions, sizeof (memif_region_t) * ++conn->regions_num);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001360 if (r == NULL)
1361 return MEMIF_ERR_NOMEM;
1362 conn->regions = r;
1363
1364 conn->regions[1].region_size =
1365 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1366 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1367 conn->regions[1].buffer_offset = 0;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001368 ms->add_external_region (&conn->regions[1].addr,
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001369 conn->regions[1].region_size,
1370 &conn->regions[1].fd, conn->private_ctx);
1371 conn->regions[1].is_external = 1;
1372 }
1373 else
1374 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001375 memif_add_region (conn, 1);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001376 }
1377
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001378 memif_init_queues (conn);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001379
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001380 return 0;
1381}
1382
Jakub Grajciar47e68de2021-01-08 15:32:43 +01001383int
1384memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
1385 memif_buffer_t *buf)
1386{
1387 memif_connection_t *c = (memif_connection_t *) conn;
1388 if (EXPECT_FALSE (c == NULL))
1389 return MEMIF_ERR_NOCONN;
1390 if (EXPECT_FALSE (qid >= c->tx_queues_num))
1391 return MEMIF_ERR_QID;
1392 if (EXPECT_FALSE (buf == NULL))
1393 return MEMIF_ERR_INVAL_ARG;
1394
1395 uint16_t ring_size, ns;
1396 memif_queue_t *mq = &c->tx_queues[qid];
1397 memif_ring_t *ring = mq->ring;
1398
1399 ring_size = (1 << mq->log2_ring_size);
1400 if (c->args.is_master)
1401 ns = ring->head - mq->next_buf;
1402 else
1403 ns = ring_size - mq->next_buf + ring->tail;
1404
1405 if ((mq->next_buf - buf->desc_index) > ns)
1406 return MEMIF_ERR_INVAL_ARG;
1407
1408 mq->next_buf = buf->desc_index;
1409
1410 return MEMIF_ERR_SUCCESS;
1411}
1412
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001413static void
1414memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
1415 memif_buffer_t *buf, uint16_t slot)
1416{
1417 uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
1418 uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
1419 memif_desc_t *from_d, *to_d, tmp_d;
1420
1421 /* Get the descriptors */
1422 from_d = &from_q->ring->desc[buf->desc_index & from_mask];
1423 to_d = &to_q->ring->desc[slot & to_mask];
1424
1425 /* Swap descriptors */
1426 tmp_d = *from_d;
1427 *from_d = *to_d;
1428 *to_d = tmp_d;
1429
1430 /* Update descriptor index and queue for clients buffer */
1431 buf->desc_index = slot;
1432 buf->queue = to_q;
1433}
1434
1435int
1436memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
1437 memif_buffer_t *buf_b)
1438{
1439 memif_connection_t *c = (memif_connection_t *) conn;
1440 if (EXPECT_FALSE (c == NULL))
1441 return MEMIF_ERR_NOCONN;
1442 if (EXPECT_FALSE (c->args.is_master))
1443 return MEMIF_ERR_INVAL_ARG;
1444 if ((buf_a == NULL) || (buf_b == NULL))
1445 return MEMIF_ERR_INVAL_ARG;
1446
1447 int err;
1448 /* store buf_a information */
1449 uint16_t index_a = buf_a->desc_index;
1450 memif_queue_t *mq_a = buf_a->queue;
1451
1452 /* swap buffers, buf_a was updated with new desc_index and queue */
1453 memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
1454 (memif_queue_t *) buf_b->queue, buf_a,
1455 buf_b->desc_index);
1456
1457 /* update buf_b desc_index and queue */
1458 buf_b->desc_index = index_a;
1459 buf_b->queue = mq_a;
1460
1461 return MEMIF_ERR_SUCCESS;
1462}
1463
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001464int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001465memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
1466 memif_buffer_t * bufs, uint16_t count,
1467 uint16_t * count_out)
1468{
1469 memif_connection_t *c = (memif_connection_t *) conn;
1470 if (EXPECT_FALSE (c == NULL))
1471 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001472 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001473 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001474 if (EXPECT_FALSE (qid >= c->tx_queues_num))
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001475 return MEMIF_ERR_QID;
1476 if (EXPECT_FALSE (!count_out))
1477 return MEMIF_ERR_INVAL_ARG;
1478 if (EXPECT_FALSE (c->args.is_master))
1479 return MEMIF_ERR_INVAL_ARG;
1480
1481 memif_queue_t *mq = &c->tx_queues[qid];
1482 memif_ring_t *ring = mq->ring;
1483 memif_buffer_t *b0;
1484 uint16_t mask = (1 << mq->log2_ring_size) - 1;
1485 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001486 uint16_t ns;
1487 memif_queue_t *bmq;
msardara8f554b72018-12-11 18:36:55 +01001488 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001489 *count_out = 0;
1490
1491 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001492
1493 /* can only be called by slave */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001494 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001495
1496 b0 = bufs;
1497
1498 while (count && ns)
1499 {
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001500 /* Swaps the descriptors, updates next_buf pointer and updates client
1501 * memif buffer */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001502
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001503 memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
1504 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001505
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001506 mq->next_buf++; /* mark the buffer as allocated */
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001507 count--;
1508 ns--;
1509 b0++;
1510 *count_out += 1;
1511 }
1512
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001513 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1514 mq->next_buf);
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001515
1516 if (count)
1517 {
1518 DBG ("ring buffer full! qid: %u", qid);
1519 err = MEMIF_ERR_NOBUF_RING;
1520 }
1521
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001522 return err;
1523}
1524
1525int
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001526memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
1527 memif_buffer_t * bufs, uint16_t count,
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001528 uint16_t * count_out, uint16_t size)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001529{
1530 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001531 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001532 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001533 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001534 return MEMIF_ERR_DISCONNECTED;
1535 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001536 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1537 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001538 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001539 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001540 if (EXPECT_FALSE (!count_out))
1541 return MEMIF_ERR_INVAL_ARG;
1542
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001543 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001544 memif_queue_t *mq = &c->tx_queues[qid];
1545 memif_ring_t *ring = mq->ring;
msardara8f554b72018-12-11 18:36:55 +01001546 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001547 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001548 uint32_t offset_mask = c->run_args.buffer_size - 1;
Chun Li5dca5462018-02-07 09:51:35 +08001549 uint16_t ring_size;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001550 uint16_t ns;
msardara8f554b72018-12-11 18:36:55 +01001551 int err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001552 uint16_t dst_left, src_left;
1553 uint16_t saved_count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001554 uint16_t saved_next_buf;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001555 uint16_t slot;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001556 memif_buffer_t *saved_b;
1557 *count_out = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001558
Chun Li5dca5462018-02-07 09:51:35 +08001559 ring_size = (1 << mq->log2_ring_size);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001560
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001561 if (c->args.is_master)
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001562 ns = ring->head - mq->next_buf;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001563 else
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001564 ns = ring_size - mq->next_buf + ring->tail;
Jakub Grajciar04b68bd2017-10-30 10:34:54 +01001565
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001566 while (count && ns)
1567 {
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001568 b0 = (bufs + *count_out);
1569
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001570 saved_b = b0;
1571 saved_count = count;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001572 saved_next_buf = mq->next_buf;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001573
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001574 b0->desc_index = mq->next_buf;
1575 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciar8caf9ec2021-12-01 09:07:09 +01001576 b0->flags = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001577
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001578 /* slave can produce buffer with original length */
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001579 dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
1580 c->run_args.buffer_size;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001581 src_left = size;
1582
1583 while (src_left)
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001584 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001585 if (EXPECT_FALSE (dst_left == 0))
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001586 {
1587 if (count && ns)
1588 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001589 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001590 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001591 ns--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001592
1593 ring->desc[b0->desc_index & mask].flags |=
1594 MEMIF_DESC_FLAG_NEXT;
1595 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1596
1597 b0 = (bufs + *count_out);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001598 b0->desc_index = mq->next_buf;
1599 dst_left = (c->args.is_master) ?
1600 ring->desc[mq->next_buf & mask].length :
1601 c->run_args.buffer_size;
1602 ring->desc[mq->next_buf & mask].flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001603 }
1604 else
1605 {
1606 /* rollback allocated chain buffers */
1607 memset (saved_b, 0, sizeof (memif_buffer_t)
1608 * (saved_count - count + 1));
1609 *count_out -= saved_count - 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 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001619 memif_desc_t *d = &ring->desc[slot & mask];
1620 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
1623 d->offset = d->offset - (d->offset & offset_mask);
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;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001629 }
1630
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001631 *count_out += 1;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001632 mq->next_buf++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001633 ns--;
1634 count--;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001635 }
1636
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001637no_ns:
1638
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001639 DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1640 mq->next_buf);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001641
1642 if (count)
1643 {
1644 DBG ("ring buffer full! qid: %u", qid);
1645 err = MEMIF_ERR_NOBUF_RING;
1646 }
1647
1648 return err;
1649}
1650
1651int
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001652memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
1653 uint16_t headroom)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001654{
1655 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001656 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001657 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001658 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001659 return MEMIF_ERR_DISCONNECTED;
1660 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001661 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1662 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001663 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001664 return MEMIF_ERR_QID;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001665 memif_socket_t *ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001666 memif_queue_t *mq = &c->rx_queues[qid];
1667 memif_ring_t *ring = mq->ring;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001668 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001669 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001670 uint16_t slot, counter = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001671
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001672 if (c->args.is_master)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001673 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001674 MEMIF_MEMORY_BARRIER ();
1675 ring->tail =
1676 (ring->tail + count <=
1677 mq->last_head) ? ring->tail + count : mq->last_head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001678 return MEMIF_ERR_SUCCESS;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001679 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001680
1681 uint16_t head = ring->head;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001682 slot = head;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001683 uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001684 count = (count < ns) ? count : ns;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001685
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001686 memif_desc_t *d;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001687 while (counter < count)
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001688 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001689 d = &ring->desc[slot & mask];
1690 d->region = 1;
1691 d->length = c->run_args.buffer_size - headroom;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001692 if (ms->get_external_buffer_offset)
1693 d->offset = ms->get_external_buffer_offset (c->private_ctx);
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001694 else
1695 d->offset = d->offset - (d->offset & offset_mask) + headroom;
1696 slot++;
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001697 counter++;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001698 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001699
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001700 MEMIF_MEMORY_BARRIER ();
Jakub Grajciar0dea94b2021-01-26 07:38:30 +01001701 ring->head = slot;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001702
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001703 return MEMIF_ERR_SUCCESS; /* 0 */
1704}
1705
1706int
1707memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
1708 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
1709{
1710 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001711 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001712 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001713 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001714 return MEMIF_ERR_DISCONNECTED;
1715 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001716 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1717 run_args.num_s2m_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001718 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001719 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001720 if (EXPECT_FALSE (!tx))
1721 return MEMIF_ERR_INVAL_ARG;
1722
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001723 memif_queue_t *mq = &c->tx_queues[qid];
1724 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001725 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciar14217482021-01-14 13:23:48 +01001726 uint32_t offset_mask = c->run_args.buffer_size - 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001727 memif_buffer_t *b0;
Jakub Grajciar14217482021-01-14 13:23:48 +01001728 memif_desc_t *d;
1729 int64_t data_offset;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001730 *tx = 0;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001731 int err = MEMIF_ERR_SUCCESS;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001732
1733 if (EXPECT_FALSE (count == 0))
1734 return MEMIF_ERR_SUCCESS;
1735
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001736 uint16_t index;
1737 if (c->args.is_master)
1738 index = ring->tail;
1739 else
1740 index = ring->head;
1741
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001742 while (count)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001743 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001744 b0 = (bufs + *tx);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001745 /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
1746 */
1747 if ((b0->desc_index & mask) != (index & mask))
1748 {
1749 err = MEMIF_ERR_INVAL_ARG;
1750 goto done;
1751 }
Jakub Grajciar14217482021-01-14 13:23:48 +01001752 d = &ring->desc[b0->desc_index & mask];
1753 d->length = b0->len;
Mohsin Kazmi8636a322022-07-18 11:21:05 +00001754 d->flags =
1755 ((b0->flags & MEMIF_BUFFER_FLAG_NEXT) == 1) ? MEMIF_DESC_FLAG_NEXT : 0;
Jakub Grajciar14217482021-01-14 13:23:48 +01001756 if (!c->args.is_master)
1757 {
1758 // reset headroom
1759 d->offset = d->offset - (d->offset & offset_mask);
1760 // calculate offset from user data
1761 data_offset = b0->data - (d->offset + c->regions[d->region].addr);
1762 if (data_offset != 0)
1763 {
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001764 /* verify data offset and buffer length */
Jakub Grajciar14217482021-01-14 13:23:48 +01001765 if ((data_offset < 0) ||
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001766 ((data_offset + b0->len) > c->run_args.buffer_size))
Jakub Grajciar14217482021-01-14 13:23:48 +01001767 {
Nathan Skrzypczak814eee52021-05-07 19:39:07 +02001768 DBG ("slot: %d, data_offset: %ld, length: %d",
Jakub Grajciarcef0cc12021-03-01 08:54:35 +01001769 b0->desc_index & mask, data_offset, b0->len);
Jakub Grajciar14217482021-01-14 13:23:48 +01001770 err = MEMIF_ERR_INVAL_ARG;
1771 goto done;
1772 }
1773 d->offset += data_offset;
1774 }
1775 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001776
1777#ifdef MEMIF_DBG_SHM
1778 printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
1779 printf ("data: %p\n",
1780 memif_get_buffer (c, ring, b0->desc_index & mask));
1781 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001782 print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
1783 ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001784#endif /* MEMIF_DBG_SHM */
1785
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001786 *tx += 1;
1787 count--;
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001788 index++;
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001789 }
1790
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001791done:
Milan Lenco0a47c992017-10-12 14:19:31 +02001792 MEMIF_MEMORY_BARRIER ();
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001793 if (c->args.is_master)
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001794 ring->tail = b0->desc_index + 1;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001795 else
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001796 ring->head = b0->desc_index + 1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001797
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001798 if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
1799 {
1800 uint64_t a = 1;
1801 int r = write (mq->int_fd, &a, sizeof (a));
1802 if (r < 0)
1803 return MEMIF_ERR_INT_WRITE;
1804 }
1805
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001806 return err;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001807}
1808
1809int
1810memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
1811 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
1812{
1813 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001814 if (EXPECT_FALSE (c == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001815 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001816 if (EXPECT_FALSE (c->control_channel == NULL))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001817 return MEMIF_ERR_DISCONNECTED;
1818 uint8_t num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02001819 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1820 run_args.num_m2s_rings;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001821 if (EXPECT_FALSE (qid >= num))
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001822 return MEMIF_ERR_QID;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001823 if (EXPECT_FALSE (!rx))
1824 return MEMIF_ERR_INVAL_ARG;
1825
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001826 memif_queue_t *mq = &c->rx_queues[qid];
1827 memif_ring_t *ring = mq->ring;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001828 uint16_t cur_slot, last_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001829 uint16_t ns;
1830 uint16_t mask = (1 << mq->log2_ring_size) - 1;
msardara8f554b72018-12-11 18:36:55 +01001831 memif_buffer_t *b0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001832 *rx = 0;
1833
1834 uint64_t b;
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001835 ssize_t r;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001836
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001837 cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
1838 last_slot = (c->args.is_master) ? ring->head : ring->tail;
1839 if (cur_slot == last_slot)
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001840 {
1841 r = read (mq->int_fd, &b, sizeof (b));
1842 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1843 return memif_syscall_error_handler (errno);
1844
1845 return MEMIF_ERR_SUCCESS;
1846 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001847
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001848 ns = last_slot - cur_slot;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001849
1850 while (ns && count)
1851 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001852 b0 = (bufs + *rx);
1853
1854 b0->desc_index = cur_slot;
1855 b0->data = memif_get_buffer (c, ring, cur_slot & mask);
1856 b0->len = ring->desc[cur_slot & mask].length;
Jakub Grajciar8caf9ec2021-12-01 09:07:09 +01001857 b0->flags = 0;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001858 /* slave resets buffer length */
1859 if (c->args.is_master == 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001860 {
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001861 ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001862 }
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001863
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001864 if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
1865 {
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001866 b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001867 ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
1868 }
Jakub Grajciar14217482021-01-14 13:23:48 +01001869
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001870 b0->queue = mq;
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02001871#ifdef MEMIF_DBG_SHM
Jakub Grajciar3744fc72018-03-29 13:15:10 +02001872 printf ("data: %p\n", b0->data);
1873 printf ("index: %u\n", b0->desc_index);
Jakub Grajciarf35fef22021-01-08 15:01:13 +01001874 printf ("queue: %p\n", b0->queue);
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001875 print_bytes (b0->data, b0->len, DBG_RX_BUF);
Jakub Grajciarba3c4e82017-09-18 11:21:40 +02001876#endif /* MEMIF_DBG_SHM */
1877 ns--;
1878 *rx += 1;
1879
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001880 count--;
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001881 cur_slot++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001882 }
1883
Jakub Grajciarecfa2aa2018-03-26 11:26:34 +02001884 if (c->args.is_master)
1885 mq->last_head = cur_slot;
1886 else
1887 mq->last_tail = cur_slot;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001888
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001889 if (ns)
1890 {
1891 DBG ("not enough buffers!");
1892 return MEMIF_ERR_NOBUF;
1893 }
1894
Jan Cavojsky77a95cd2020-03-03 16:25:58 +01001895 r = read (mq->int_fd, &b, sizeof (b));
1896 if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1897 return memif_syscall_error_handler (errno);
1898
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001899 return MEMIF_ERR_SUCCESS; /* 0 */
1900}
1901
1902int
1903memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
1904 char *buf, ssize_t buflen)
1905{
1906 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02001907 memif_socket_t *ms;
1908 int err = MEMIF_ERR_SUCCESS, i;
1909 ssize_t l0 = 0, l1;
1910
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001911 if (c == NULL)
1912 return MEMIF_ERR_NOCONN;
1913
Jakub Grajciar12df4972019-07-01 14:24:48 +02001914 ms = (memif_socket_t *) c->args.socket;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001915
1916 l1 = strlen ((char *) c->args.interface_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001917 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001918 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001919 md->if_name =
1920 (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001921 l0 += l1 + 1;
1922 }
1923 else
1924 err = MEMIF_ERR_NOBUF_DET;
1925
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001926 l1 = strlen ((char *) ms->args.app_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001927 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001928 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001929 md->inst_name =
1930 (uint8_t *) strcpy (buf + l0, (char *) ms->args.app_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001931 l0 += l1 + 1;
1932 }
1933 else
1934 err = MEMIF_ERR_NOBUF_DET;
1935
1936 l1 = strlen ((char *) c->remote_if_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001937 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001938 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001939 md->remote_if_name =
1940 (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001941 l0 += l1 + 1;
1942 }
1943 else
1944 err = MEMIF_ERR_NOBUF_DET;
1945
1946 l1 = strlen ((char *) c->remote_name);
Milan Lenco0a47c992017-10-12 14:19:31 +02001947 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001948 {
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001949 md->remote_inst_name =
1950 (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001951 l0 += l1 + 1;
1952 }
1953 else
1954 err = MEMIF_ERR_NOBUF_DET;
1955
1956 md->id = c->args.interface_id;
1957
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001958 if (strlen ((char *) c->args.secret) > 0)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001959 {
1960 l1 = strlen ((char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02001961 if (l0 + l1 < buflen)
1962 {
Jakub Grajciar5e1f69a2018-04-12 13:56:29 +02001963 md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
Milan Lenco0a47c992017-10-12 14:19:31 +02001964 l0 += l1 + 1;
1965 }
1966 else
1967 err = MEMIF_ERR_NOBUF_DET;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001968 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001969
1970 md->role = (c->args.is_master) ? 0 : 1;
1971 md->mode = c->args.mode;
1972
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001973 l1 = 108;
Milan Lenco0a47c992017-10-12 14:19:31 +02001974 if (l0 + l1 < buflen)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001975 {
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001976 md->socket_path = (uint8_t *) memcpy (buf + l0, ms->args.path, 108);
Jakub Grajciar134f1e02021-01-04 11:10:42 +01001977 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001978 }
1979 else
1980 err = MEMIF_ERR_NOBUF_DET;
1981
Jakub Grajciar568cc462018-09-05 12:11:35 +02001982 l1 = strlen ((char *) c->remote_disconnect_string);
1983 if (l0 + l1 < buflen)
1984 {
1985 md->error =
1986 (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
1987 l0 += l1 + 1;
1988 }
1989 else
1990 err = MEMIF_ERR_NOBUF_DET;
1991
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02001992 md->regions_num = c->regions_num;
1993 l1 = sizeof (memif_region_details_t) * md->regions_num;
1994 if (l0 + l1 <= buflen)
1995 {
Koichiro Den33331ed2019-01-03 00:22:24 +09001996 md->regions = (memif_region_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09001997 for (i = 0; i < md->regions_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02001998 {
1999 md->regions[i].index = i;
2000 md->regions[i].addr = c->regions[i].addr;
2001 md->regions[i].size = c->regions[i].region_size;
2002 md->regions[i].fd = c->regions[i].fd;
2003 md->regions[i].is_external = c->regions[i].is_external;
2004 }
Jakub Grajciar93a5dd12018-08-20 14:26:32 +02002005 l0 += l1;
2006 }
2007 else
2008 err = MEMIF_ERR_NOBUF_DET;
2009
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002010 md->rx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002011 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2012 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002013
2014 l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2015 if (l0 + l1 <= buflen)
2016 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002017 md->rx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002018 for (i = 0; i < md->rx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002019 {
2020 md->rx_queues[i].region = c->rx_queues[i].region;
2021 md->rx_queues[i].qid = i;
2022 md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2023 md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2024 md->rx_queues[i].head = c->rx_queues[i].ring->head;
2025 md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2026 md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2027 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002028 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002029 }
2030 else
2031 err = MEMIF_ERR_NOBUF_DET;
2032
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002033 md->tx_queues_num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002034 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2035 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002036
2037 l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2038 if (l0 + l1 <= buflen)
2039 {
Koichiro Den33331ed2019-01-03 00:22:24 +09002040 md->tx_queues = (memif_queue_details_t *) (buf + l0);
Koichiro Denbe420e52018-12-15 00:31:34 +09002041 for (i = 0; i < md->tx_queues_num; i++)
Jakub Grajciar12df4972019-07-01 14:24:48 +02002042 {
2043 md->tx_queues[i].region = c->tx_queues[i].region;
2044 md->tx_queues[i].qid = i;
2045 md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2046 md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2047 md->tx_queues[i].head = c->tx_queues[i].ring->head;
2048 md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2049 md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2050 }
Milan Lenco0a47c992017-10-12 14:19:31 +02002051 l0 += l1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002052 }
2053 else
2054 err = MEMIF_ERR_NOBUF_DET;
2055
Jakub Grajciar134f1e02021-01-04 11:10:42 +01002056 /* This is not completely true, clients should relay on
2057 * on_connect/on_disconnect callbacks */
2058 md->link_up_down = (c->control_channel != NULL) ? 1 : 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002059
2060 return err; /* 0 */
2061}
2062
2063int
2064memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2065{
2066 memif_connection_t *c = (memif_connection_t *) conn;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002067 uint8_t num;
2068
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002069 *efd = -1;
2070 if (c == NULL)
2071 return MEMIF_ERR_NOCONN;
Jakub Grajciar134f1e02021-01-04 11:10:42 +01002072 if (c->control_channel == NULL)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002073 return MEMIF_ERR_DISCONNECTED;
Jakub Grajciar12df4972019-07-01 14:24:48 +02002074
2075 num =
Jakub Grajciar568cc462018-09-05 12:11:35 +02002076 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2077 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02002078 if (qid >= num)
2079 return MEMIF_ERR_QID;
2080
2081 *efd = c->rx_queues[qid].int_fd;
2082
2083 return MEMIF_ERR_SUCCESS;
2084}