blob: 49bf50cb5e04ac44ae4d780db32cf3bdfa315136 [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
18#include <stdint.h>
19#include <net/if.h>
20#include <sys/types.h>
21#include <fcntl.h>
22#include <sys/ioctl.h>
23#include <sys/socket.h>
24#include <sys/un.h>
25#include <sys/uio.h>
26#include <sys/mman.h>
27#include <sys/prctl.h>
28#include <inttypes.h>
29#include <string.h>
30#include <stdio.h>
31#include <netdb.h>
32#include <linux/ip.h>
33#include <linux/icmp.h>
34#include <arpa/inet.h>
35#include <stdlib.h>
36#include <netinet/if_ether.h>
37#include <net/if_arp.h>
38#include <asm/byteorder.h>
39#include <byteswap.h>
40#include <string.h>
41#include <errno.h>
42#include <sys/stat.h>
43#include <sys/eventfd.h>
44#include <sys/timerfd.h>
45#include <sys/epoll.h>
46#include <signal.h>
47
48/* memif protocol msg, ring and descriptor definitions */
49#include <memif.h>
50/* memif api */
51#include <libmemif.h>
52/* socket messaging functions */
53#include <socket.h>
54/* private structs and functions */
55#include <memif_private.h>
56
57#define ERRLIST_LEN 36
58#define MAX_ERRBUF_LEN 256
59
60#if __x86_x64__
61#define MEMIF_MEMORY_BARRIER() __builtin_ia32_sfence ()
62#else
63#define MEMIF_MEORY_BARRIER() __sync_synchronize ()
64#endif /* __x86_x64__ */
65
66libmemif_main_t libmemif_main;
67int memif_epfd;
68
69static char memif_buf[MAX_ERRBUF_LEN];
70
71const char *memif_errlist[ERRLIST_LEN] = { /* MEMIF_ERR_SUCCESS */
72 "Success.",
73 /* MEMIF_ERR_SYSCALL */
74 "Unspecified syscall error (build with -DMEMIF_DBG or make debug).",
75 /* MEMIF_ERR_ACCES */
76 "Permission to resoure denied.",
77 /* MEMIF_ERR_NO_FILE */
78 "Socket file does not exist",
79 /* MEMIF_ERR_FILE_LIMIT */
80 "System limit on total numer of open files reached.",
81 /* MEMIF_ERR_PROC_FILE_LIMIT */
82 "Per-process limit on total number of open files reached.",
83 /* MEMIF_ERR_ALREADY */
84 "Connection already requested.",
85 /* MEMIF_ERR_AGAIN */
86 "File descriptor refers to file other than socket, or operation would block.",
87 /* MEMIF_ERR_BAD_FD */
88 "Bad file descriptor.",
89 /* MEMIF_ERR_NOMEM */
90 "Out of memory.",
91 /* MEMIF_ERR_INVAL_ARG */
92 "Invalid argument.",
93 /* MEMIF_ERR_NOCONN */
94 "Memif connection handle does not point to existing conenction",
95 /* MEMIF_ERR_CONN */
96 "Memif connection handle points to existing connection",
97 /* MEMIF_ERR_CB_FDUPDATE */
98 "Callback memif_control_fd_update_t returned error",
99 /* MEMIF_ERR_FILE_NOT_SOCK */
100 "File specified by socket filename exists and is not socket.",
101 /* MEMIF_ERR_NO_SHMFD */
102 "Missing shared memory file descriptor. (internal error)",
103 /* MEMIF_ERR_COOKIE */
104 "Invalid cookie on ring. (internal error)",
105 /* MEMIF_ERR_NOBUF_RING */
106 "Ring buffer full.",
107 /* MEMIF_ERR_NOBUF */
108 "Not enough memif buffers. There are unreceived data in shared memory.",
109 /* MEMIF_ERR_NOBUF_DET */
110 "Not enough space for memif details in suplied buffer. String data might be malformed.",
111 /* MEMIF_ERR_INT_WRITE */
112 "Send interrupt error.",
113 /* MEMIF_ERR_MFMSG */
114 "Malformed message received on control channel.",
115 /* MEMIF_ERR_QID */
116 "Invalid queue id",
117 /* MEMIF_ERR_PROTO */
118 "Incompatible memory interface protocol version.",
119 /* MEMIF_ERR_ID */
120 "Unmatched interface id.",
121 /* MEMIF_ERR_ACCSLAVE */
122 "Slave cannot accept connection reqest.",
123 /* MEMIF_ERR_ALRCONN */
124 "Interface is already connected.",
125 /* MEMIF_ERR_MODE */
126 "Mode mismatch.",
127 /* MEMIF_ERR_SECRET */
128 "Secret mismatch.",
129 /* MEMIF_ERR_NOSECRET */
130 "Secret required.",
131 /* MEMIF_ERR_MAXREG */
132 "Limit on total number of regions reached.",
133 /* MEMIF_ERR_MAXRING */
134 "Limit on total number of ring reached.",
135 /* MEMIF_ERR_NO_INTFD */
136 "Missing interrupt file descriptor. (internal error)",
137 /* MEMIF_ERR_DISCONNECT */
138 "Interface received disconnect request.",
139 /* MEMIF_ERR_DISCONNECTED */
140 "Interface is disconnected.",
141 /* MEMIF_ERR_UNKNOWN_MSG */
142 "Unknown message type received on control channel. (internal error)"
143};
144
145#define MEMIF_ERR_UNDEFINED "undefined error"
146
147char *
148memif_strerror (int err_code)
149{
150 if (err_code >= ERRLIST_LEN)
151 {
152 strncpy (memif_buf, MEMIF_ERR_UNDEFINED, strlen (MEMIF_ERR_UNDEFINED));
153 memif_buf[strlen (MEMIF_ERR_UNDEFINED)] = '\0';
154 }
155 else
156 {
157 strncpy (memif_buf, memif_errlist[err_code],
158 strlen (memif_errlist[err_code]));
159 memif_buf[strlen (memif_errlist[err_code])] = '\0';
160 }
161 return memif_buf;
162}
163
164#define DBG_TX_BUF (0)
165#define DBG_RX_BUF (1)
166
167#ifdef MEMIF_DBG_SHM
168static void
169print_bytes (void *data, uint16_t len, uint8_t q)
170{
171 if (q == DBG_TX_BUF)
172 printf ("\nTX:\n\t");
173 else
174 printf ("\nRX:\n\t");
175 int i;
176 for (i = 0; i < len; i++)
177 {
178 if (i % 8 == 0)
179 printf ("\n%d:\t", i);
180 printf ("%02X ", ((uint8_t *) (data))[i]);
181 }
182 printf ("\n\n");
183}
184#endif /* MEMIF_DBG */
185
186int
187memif_syscall_error_handler (int err_code)
188{
189 DBG_UNIX ("%s", strerror (err_code));
190
191 if (err_code == 0)
192 return MEMIF_ERR_SUCCESS;
193 if (err_code == EACCES)
194 return MEMIF_ERR_ACCES;
195 if (err_code == ENFILE)
196 return MEMIF_ERR_FILE_LIMIT;
197 if (err_code == EMFILE)
198 return MEMIF_ERR_PROC_FILE_LIMIT;
199 if (err_code == ENOMEM)
200 return MEMIF_ERR_NOMEM;
201/* connection refused if master dows not exist
202 this error would spam the user until master was created */
203 if (err_code == ECONNREFUSED)
204 return MEMIF_ERR_SUCCESS;
205 if (err_code == EALREADY)
206 return MEMIF_ERR_ALREADY;
207 if (err_code == EAGAIN)
208 return MEMIF_ERR_AGAIN;
209 if (err_code == EBADF)
210 return MEMIF_ERR_BAD_FD;
211 if (err_code == ENOENT)
212 return MEMIF_ERR_NO_FILE;
213
214 /* other syscall errors */
215 return MEMIF_ERR_SYSCALL;
216}
217
218static int
219memif_add_epoll_fd (int fd, uint32_t events)
220{
221 if (fd < 0)
222 {
223 DBG ("invalid fd %d", fd);
224 return -1;
225 }
226 struct epoll_event evt;
227 memset (&evt, 0, sizeof (evt));
228 evt.events = events;
229 evt.data.fd = fd;
230 if (epoll_ctl (memif_epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
231 {
232 DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
233 return -1;
234 }
235 DBG ("fd %d added to epoll", fd);
236 return 0;
237}
238
239static int
240memif_mod_epoll_fd (int fd, uint32_t events)
241{
242 if (fd < 0)
243 {
244 DBG ("invalid fd %d", fd);
245 return -1;
246 }
247 struct epoll_event evt;
248 memset (&evt, 0, sizeof (evt));
249 evt.events = events;
250 evt.data.fd = fd;
251 if (epoll_ctl (memif_epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
252 {
253 DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
254 return -1;
255 }
256 DBG ("fd %d moddified on epoll", fd);
257 return 0;
258}
259
260static int
261memif_del_epoll_fd (int fd)
262{
263 if (fd < 0)
264 {
265 DBG ("invalid fd %d", fd);
266 return -1;
267 }
268 struct epoll_event evt;
269 memset (&evt, 0, sizeof (evt));
270 if (epoll_ctl (memif_epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
271 {
272 DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
273 return -1;
274 }
275 DBG ("fd %d removed from epoll", fd);
276 return 0;
277}
278
279int
280memif_control_fd_update (int fd, uint8_t events)
281{
282 if (events & MEMIF_FD_EVENT_DEL)
283 return memif_del_epoll_fd (fd);
284
285 uint32_t evt = 0;
286 if (events & MEMIF_FD_EVENT_READ)
287 evt |= EPOLLIN;
288 if (events & MEMIF_FD_EVENT_WRITE)
289 evt |= EPOLLOUT;
290
291 if (events & MEMIF_FD_EVENT_MOD)
292 return memif_mod_epoll_fd (fd, evt);
293
294 return memif_add_epoll_fd (fd, evt);
295}
296
297int
298add_list_elt (memif_list_elt_t * e, memif_list_elt_t ** list, uint16_t * len)
299{
300 libmemif_main_t *lm = &libmemif_main;
301
302 int i;
303 for (i = 0; i < *len; i++)
304 {
305 if ((*list)[i].data_struct == NULL)
306 {
307 (*list)[i].key = e->key;
308 (*list)[i].data_struct = e->data_struct;
309 return i;
310 }
311 }
312 memif_list_elt_t *tmp;
313 tmp = realloc (*list, sizeof (memif_list_elt_t) * *len * 2);
314 if (tmp == NULL)
315 return -1;
316
317 for (i = *len; i < *len * 2; i++)
318 {
319 tmp[i].key = -1;
320 tmp[i].data_struct = NULL;
321 }
322
323 tmp[*len].key = e->key;
324 tmp[*len].data_struct = e->data_struct;
325 i = *len;
326 *len = *len * 2;
327 *list = tmp;
328
329 return i;
330}
331
332int
333get_list_elt (memif_list_elt_t ** e, memif_list_elt_t * list, uint16_t len,
334 int key)
335{
336 if (key == -1)
337 {
338 *e = NULL;
339 return -1;
340 }
341 int i;
342 for (i = 0; i < len; i++)
343 {
344 if (list[i].key == key)
345 {
346 *e = &list[i];
347 return 0;
348 }
349 }
350 *e = NULL;
351 return -1;
352}
353
354/* does not free memory, only marks element as free */
355int
356free_list_elt (memif_list_elt_t * list, uint16_t len, int key)
357{
358 int i;
359 for (i = 0; i < len; i++)
360 {
361 if (list[i].key == key)
362 {
363 list[i].key = -1;
364 list[i].data_struct = NULL;
365 return 0;
366 }
367 }
368
369 return -1;
370}
371
372int
373free_list_elt_ctx (memif_list_elt_t * list, uint16_t len,
374 memif_connection_t * ctx)
375{
376 int i;
377 for (i = 0; i < len; i++)
378 {
379 if (list[i].key == -1)
380 {
381 if (list[i].data_struct == ctx)
382 {
383 list[i].data_struct = NULL;
384 return 0;
385 }
386 }
387 }
388
389 return -1;
390}
391
392static void
393memif_control_fd_update_register (memif_control_fd_update_t * cb)
394{
395 libmemif_main_t *lm = &libmemif_main;
396 lm->control_fd_update = cb;
397}
398
399int
400memif_init (memif_control_fd_update_t * on_control_fd_update, char *app_name)
401{
402 int err = MEMIF_ERR_SUCCESS; /* 0 */
403 libmemif_main_t *lm = &libmemif_main;
404
405 if (app_name)
406 {
407 lm->app_name = malloc (strlen (app_name) + sizeof (char));
408 memset (lm->app_name, 0, strlen (app_name) + sizeof (char));
409 strncpy ((char *) lm->app_name, app_name, strlen (app_name));
410 }
411 else
412 {
413 lm->app_name = malloc (strlen (MEMIF_DEFAULT_APP_NAME) + sizeof (char));
414 memset (lm->app_name, 0, strlen (app_name) + sizeof (char));
415 strncpy ((char *) lm->app_name, MEMIF_DEFAULT_APP_NAME,
416 strlen (MEMIF_DEFAULT_APP_NAME));
417 }
418
419 /* register control fd update callback */
420 if (on_control_fd_update != NULL)
421 memif_control_fd_update_register (on_control_fd_update);
422 else
423 {
424 memif_epfd = epoll_create (1);
425 memif_control_fd_update_register (memif_control_fd_update);
426 DBG ("libmemif event polling initialized");
427 }
428
429 memset (&lm->ms, 0, sizeof (memif_socket_t));
430
431 lm->control_list_len = 2;
432 lm->interrupt_list_len = 2;
433 lm->listener_list_len = 1;
434 lm->pending_list_len = 1;
435
436 lm->control_list =
437 malloc (sizeof (memif_list_elt_t) * lm->control_list_len);
438 lm->interrupt_list =
439 malloc (sizeof (memif_list_elt_t) * lm->interrupt_list_len);
440 lm->listener_list =
441 malloc (sizeof (memif_list_elt_t) * lm->listener_list_len);
442 lm->pending_list =
443 malloc (sizeof (memif_list_elt_t) * lm->pending_list_len);
444
445 int i;
446 for (i = 0; i < lm->control_list_len; i++)
447 {
448 lm->control_list[i].key = -1;
449 lm->control_list[i].data_struct = NULL;
450 }
451 for (i = 0; i < lm->interrupt_list_len; i++)
452 {
453 lm->interrupt_list[i].key = -1;
454 lm->interrupt_list[i].data_struct = NULL;
455 }
456 for (i = 0; i < lm->listener_list_len; i++)
457 {
458 lm->listener_list[i].key = -1;
459 lm->listener_list[i].data_struct = NULL;
460 }
461 for (i = 0; i < lm->pending_list_len; i++)
462 {
463 lm->pending_list[i].key = -1;
464 lm->pending_list[i].data_struct = NULL;
465 }
466
467 lm->disconn_slaves = 0;
468
469 lm->timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
470 if (lm->timerfd < 0)
471 {
472 err = errno;
473 DBG ("timerfd: %s", strerror (err));
474 return memif_syscall_error_handler (err);
475 }
476
477 lm->arm.it_value.tv_sec = 2;
478 lm->arm.it_value.tv_nsec = 0;
479 lm->arm.it_interval.tv_sec = 2;
480 lm->arm.it_interval.tv_nsec = 0;
481 memset (&lm->disarm, 0, sizeof (lm->disarm));
482
483 if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ) < 0)
484 {
485 DBG ("callback type memif_control_fd_update_t error!");
486 return MEMIF_ERR_CB_FDUPDATE;
487 }
488
489 return 0;
490}
491
492static inline memif_ring_t *
493memif_get_ring (memif_connection_t * conn, memif_ring_type_t type,
494 uint16_t ring_num)
495{
496 if (&conn->regions[0] == NULL)
497 return NULL;
498 void *p = conn->regions[0].shm;
499 int ring_size =
500 sizeof (memif_ring_t) +
501 sizeof (memif_desc_t) * (1 << conn->run_args.log2_ring_size);
502 p += (ring_num + type * conn->run_args.num_s2m_rings) * ring_size;
503
504 return (memif_ring_t *) p;
505}
506
507int
508memif_set_rx_mode (memif_conn_handle_t c, memif_rx_mode_t rx_mode,
509 uint16_t qid)
510{
511 memif_connection_t *conn = (memif_connection_t *) c;
512 if (conn == NULL)
513 return MEMIF_ERR_NOCONN;
514 uint8_t num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200515 (conn->args.is_master) ? conn->run_args.num_s2m_rings : conn->
516 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200517 if (qid >= num)
518 return MEMIF_ERR_QID;
519
520 conn->rx_queues[qid].ring->flags = rx_mode;
521 DBG ("rx_mode flag: %u", conn->rx_queues[qid].ring->flags);
522 return MEMIF_ERR_SUCCESS;
523}
524
525int
526memif_create (memif_conn_handle_t * c, memif_conn_args_t * args,
527 memif_connection_update_t * on_connect,
528 memif_connection_update_t * on_disconnect,
529 memif_interrupt_t * on_interrupt, void *private_ctx)
530{
531 int err, i, index, sockfd = -1;
532 memif_list_elt_t list_elt;
533 memif_connection_t *conn = (memif_connection_t *) * c;
534 if (conn != NULL)
535 {
536 DBG ("This handle already points to existing memif.");
537 return MEMIF_ERR_CONN;
538 }
539 conn = (memif_connection_t *) malloc (sizeof (memif_connection_t));
540 if (conn == NULL)
541 {
542 err = memif_syscall_error_handler (errno);
543 goto error;
544 }
545 memset (conn, 0, sizeof (memif_connection_t));
546
547 libmemif_main_t *lm = &libmemif_main;
548
549 conn->args.interface_id = args->interface_id;
550
551 if (args->log2_ring_size == 0)
552 args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
553 if (args->buffer_size == 0)
554 args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
555 if (args->num_s2m_rings == 0)
556 args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
557 if (args->num_m2s_rings == 0)
558 args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
559
560 conn->args.num_s2m_rings = args->num_s2m_rings;
561 conn->args.num_m2s_rings = args->num_m2s_rings;
562 conn->args.buffer_size = args->buffer_size;
563 conn->args.log2_ring_size = args->log2_ring_size;
564 conn->args.is_master = args->is_master;
565 conn->args.mode = args->mode;
566 conn->msg_queue = NULL;
567 conn->regions = NULL;
568 conn->tx_queues = NULL;
569 conn->rx_queues = NULL;
570 conn->fd = -1;
571 conn->on_connect = on_connect;
572 conn->on_disconnect = on_disconnect;
573 conn->on_interrupt = on_interrupt;
574 conn->private_ctx = private_ctx;
575 memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
576
577 uint8_t l = strlen ((char *) args->interface_name);
578 strncpy ((char *) conn->args.interface_name, (char *) args->interface_name,
579 l);
580
581 l = strlen ((char *) args->instance_name);
582 strncpy ((char *) conn->args.instance_name, (char *) args->instance_name,
583 l);
584
585 /* allocate and initialize socket_filename so it can be copyed to sun_path
586 without memory leaks */
587 conn->args.socket_filename = malloc (sizeof (char *) * 108);
588 memset (conn->args.socket_filename, 0, 108 * sizeof (char *));
589
590 if (args->socket_filename)
591 {
592 if (conn->args.socket_filename == NULL)
593 {
594 err = memif_syscall_error_handler (errno);
595 goto error;
596 }
597 strncpy ((char *) conn->args.socket_filename,
598 (char *) args->socket_filename,
599 strlen ((char *) args->socket_filename));
600 }
601 else
602 {
603 uint16_t sdl = strlen (MEMIF_DEFAULT_SOCKET_DIR);
604 uint16_t sfl = strlen (MEMIF_DEFAULT_SOCKET_FILENAME);
605 if (conn->args.socket_filename == NULL)
606 {
607 err = memif_syscall_error_handler (errno);
608 goto error;
609 }
610 strncpy ((char *) conn->args.socket_filename,
611 MEMIF_DEFAULT_SOCKET_DIR, sdl);
612 conn->args.socket_filename[sdl] = '/';
613 strncpy ((char *) (conn->args.socket_filename + 1 + sdl),
614 MEMIF_DEFAULT_SOCKET_FILENAME, sfl);
615 }
616
617 if (args->secret)
618 {
619 l = strlen ((char *) args->secret);
620 strncpy ((char *) conn->args.secret, (char *) args->secret, l);
621 }
622
623 if (conn->args.is_master)
624 {
625 conn->run_args.buffer_size = conn->args.buffer_size;
626 memif_socket_t *ms;
627 memif_list_elt_t elt;
628 for (i = 0; i < lm->listener_list_len; i++)
629 {
630 if ((ms =
631 (memif_socket_t *) lm->listener_list[i].data_struct) != NULL)
632 {
633 if (strncmp
634 ((char *) ms->filename, (char *) conn->args.socket_filename,
635 strlen ((char *) ms->filename)) == 0)
636 {
637 /* add interface to listener socket */
638 elt.key = conn->args.interface_id;
639 *c = elt.data_struct = conn;
640 add_list_elt (&elt, &ms->interface_list,
641 &ms->interface_list_len);
642 ms->use_count++;
643 conn->listener_fd = ms->fd;
644 break;
645 }
646 }
647 else
648 {
649 struct stat file_stat;
650 if (stat ((char *) conn->args.socket_filename, &file_stat) == 0)
651 {
652 if (S_ISSOCK (file_stat.st_mode))
653 unlink ((char *) conn->args.socket_filename);
654 else
655 return memif_syscall_error_handler (errno);
656 }
657 DBG ("creating socket file");
658 ms = malloc (sizeof (memif_socket_t));
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200659 ms->filename =
660 malloc (strlen ((char *) conn->args.socket_filename) +
661 sizeof (char));
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200662 memset (ms->filename, 0,
663 strlen ((char *) conn->args.socket_filename) +
664 sizeof (char));
665 strncpy ((char *) ms->filename,
666 (char *) conn->args.socket_filename,
667 strlen ((char *) conn->args.socket_filename));
668 ms->interface_list_len = 1;
669 ms->interface_list =
670 malloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
671 ms->interface_list[0].key = -1;
672 ms->interface_list[0].data_struct = NULL;
673 struct sockaddr_un un = { 0 };
674 int on = 1;
675
676 ms->fd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
677 if (ms->fd < 0)
678 {
679 err = memif_syscall_error_handler (errno);
680 goto error;
681 }
682 DBG ("socket %d created", ms->fd);
683 un.sun_family = AF_UNIX;
684 strncpy ((char *) un.sun_path, (char *) ms->filename,
685 sizeof (un.sun_path) - 1);
686 DBG ("sockopt");
687 if (setsockopt
688 (ms->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
689 {
690 err = memif_syscall_error_handler (errno);
691 goto error;
692 }
693 DBG ("bind");
694 if (bind (ms->fd, (struct sockaddr *) &un, sizeof (un)) < 0)
695 {
696 err = memif_syscall_error_handler (errno);
697 goto error;
698 }
699 DBG ("listen");
700 if (listen (ms->fd, 1) < 0)
701 {
702 err = memif_syscall_error_handler (errno);
703 goto error;
704 }
705 DBG ("stat");
706 if (stat ((char *) ms->filename, &file_stat) < 0)
707 {
708 err = memif_syscall_error_handler (errno);
709 goto error;
710 }
711
712 /* add interface to listener socket */
713 elt.key = conn->args.interface_id;
714 *c = elt.data_struct = conn;
715 add_list_elt (&elt, &ms->interface_list,
716 &ms->interface_list_len);
717 ms->use_count = 1;
718 conn->listener_fd = ms->fd;
719
720 /* add listener socket to libmemif main */
721 elt.key = ms->fd;
722 elt.data_struct = ms;
723 add_list_elt (&elt, &lm->listener_list, &lm->listener_list_len);
724 lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_READ);
725 break;
726 }
727 }
728 }
729 else
730 {
731 if (lm->disconn_slaves == 0)
732 {
733 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
734 {
735 err = memif_syscall_error_handler (errno);
736 goto error;
737 }
738 }
739
740 lm->disconn_slaves++;
741
742 list_elt.key = -1;
743 *c = list_elt.data_struct = conn;
744 if ((index =
745 add_list_elt (&list_elt, &lm->control_list,
746 &lm->control_list_len)) < 0)
747 {
748 err = MEMIF_ERR_NOMEM;
749 goto error;
750 }
751 }
752
753 conn->index = index;
754
755 return 0;
756
757error:
758 if (sockfd > 0)
759 close (sockfd);
760 sockfd = -1;
761 if (conn->args.socket_filename)
762 free (conn->args.socket_filename);
763 if (conn != NULL)
764 free (conn);
765 *c = conn = NULL;
766 return err;
767}
768
769int
770memif_control_fd_handler (int fd, uint8_t events)
771{
772 int i, rv, sockfd = -1, err = MEMIF_ERR_SUCCESS; /* 0 */
773 uint16_t num;
774 memif_list_elt_t *e = NULL;
775 memif_connection_t *conn;
776 libmemif_main_t *lm = &libmemif_main;
777 if (fd == lm->timerfd)
778 {
779 uint64_t b;
780 ssize_t size;
781 size = read (fd, &b, sizeof (b));
782 for (i = 0; i < lm->control_list_len; i++)
783 {
784 if ((lm->control_list[i].key < 0)
785 && (lm->control_list[i].data_struct != NULL))
786 {
787 conn = lm->control_list[i].data_struct;
788 if (conn->args.is_master)
789 continue;
790
791 struct sockaddr_un sun;
792 sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
793 if (sockfd < 0)
794 {
795 err = memif_syscall_error_handler (errno);
796 goto error;
797 }
798
799 sun.sun_family = AF_UNIX;
800
801 strncpy (sun.sun_path, conn->args.socket_filename,
802 sizeof (sun.sun_path) - 1);
803
804 if (connect (sockfd, (struct sockaddr *) &sun,
805 sizeof (struct sockaddr_un)) == 0)
806 {
807 conn->fd = sockfd;
808 conn->read_fn = memif_conn_fd_read_ready;
809 conn->write_fn = memif_conn_fd_write_ready;
810 conn->error_fn = memif_conn_fd_error;
811
812 lm->control_list[conn->index].key = conn->fd;
813
814 lm->control_fd_update (sockfd,
815 MEMIF_FD_EVENT_READ |
816 MEMIF_FD_EVENT_WRITE);
817
818 lm->disconn_slaves--;
819 if (lm->disconn_slaves == 0)
820 {
821 if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL)
822 < 0)
823 {
824 err = memif_syscall_error_handler (errno);
825 goto error;
826 }
827 }
828 }
829 else
830 {
831 err = memif_syscall_error_handler (errno);
832 goto error;
833 }
834 }
835 }
836 }
837 else
838 {
839 get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
840 if (e != NULL)
841 {
842 if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
843 {
844 num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200845 (((memif_connection_t *) e->data_struct)->
846 args.is_master) ? ((memif_connection_t *) e->
847 data_struct)->run_args.
848 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
849 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200850 for (i = 0; i < num; i++)
851 {
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200852 if (((memif_connection_t *) e->data_struct)->
853 rx_queues[i].int_fd == fd)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200854 {
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200855 ((memif_connection_t *) e->data_struct)->
856 on_interrupt ((void *) e->data_struct,
857 ((memif_connection_t *) e->
858 data_struct)->private_ctx, i);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200859 return MEMIF_ERR_SUCCESS;
860 }
861 }
862 }
863 return MEMIF_ERR_SUCCESS;
864 }
865 get_list_elt (&e, lm->listener_list, lm->listener_list_len, fd);
866 if (e != NULL)
867 {
868 memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
869 return MEMIF_ERR_SUCCESS;
870 }
871
872 get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
873 if (e != NULL)
874 {
875 memif_read_ready (fd);
876 return MEMIF_ERR_SUCCESS;
877 }
878
879 get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
880 if (e != NULL)
881 {
882 if (events & MEMIF_FD_EVENT_READ)
883 {
884 err =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200885 ((memif_connection_t *) e->data_struct)->
886 read_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200887 if (err != MEMIF_ERR_SUCCESS)
888 return err;
889 }
890 if (events & MEMIF_FD_EVENT_WRITE)
891 {
892 err =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200893 ((memif_connection_t *) e->data_struct)->
894 write_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200895 if (err != MEMIF_ERR_SUCCESS)
896 return err;
897 }
898 if (events & MEMIF_FD_EVENT_ERROR)
899 {
900 err =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200901 ((memif_connection_t *) e->data_struct)->
902 error_fn (e->data_struct);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200903 if (err != MEMIF_ERR_SUCCESS)
904 return err;
905 }
906 }
907 }
908
909 return MEMIF_ERR_SUCCESS; /* 0 */
910
911error:
912 if (sockfd > 0)
913 close (sockfd);
914 sockfd = -1;
915 return err;
916}
917
918int
919memif_poll_event (int timeout)
920{
921 libmemif_main_t *lm = &libmemif_main;
922 memif_list_elt_t *elt;
923 struct epoll_event evt, *e;
924 int en = 0, err = MEMIF_ERR_SUCCESS, i = 0; /* 0 */
925 uint16_t num;
926 uint32_t events = 0;
927 memset (&evt, 0, sizeof (evt));
928 evt.events = EPOLLIN | EPOLLOUT;
929 sigset_t sigset;
930 sigemptyset (&sigset);
931 en = epoll_pwait (memif_epfd, &evt, 1, timeout, &sigset);
932 if (en < 0)
933 {
934 DBG ("epoll_pwait: %s", strerror (errno));
935 return -1;
936 }
937 if (en > 0)
938 {
939 if (evt.events & EPOLLIN)
940 events |= MEMIF_FD_EVENT_READ;
941 if (evt.events & EPOLLOUT)
942 events |= MEMIF_FD_EVENT_WRITE;
943 if (evt.events & EPOLLERR)
944 events |= MEMIF_FD_EVENT_ERROR;
945 err = memif_control_fd_handler (evt.data.fd, events);
946 return err;
947 }
948 return 0;
949}
950
951static void
952memif_msg_queue_free (memif_msg_queue_elt_t ** e)
953{
954 if (*e == NULL)
955 return;
956 memif_msg_queue_free (&(*e)->next);
957 free (*e);
958 *e = NULL;
959 return;
960}
961
962/* send disconnect msg and close interface */
963int
964memif_disconnect_internal (memif_connection_t * c)
965{
966 if (c == NULL)
967 {
968 DBG ("no connection");
969 return MEMIF_ERR_NOCONN;
970 }
971 uint16_t num;
972 int err = MEMIF_ERR_SUCCESS, i; /* 0 */
973 memif_queue_t *mq;
974 libmemif_main_t *lm = &libmemif_main;
975 memif_list_elt_t *e;
976
977 c->on_disconnect ((void *) c, c->private_ctx);
978
979 if (c->fd > 0)
980 {
981 memif_msg_send_disconnect (c->fd, "interface deleted", 0);
982 lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL);
983 close (c->fd);
984 }
985 get_list_elt (&e, lm->control_list, lm->control_list_len, c->fd);
986 if (e != NULL)
987 {
988 if (c->args.is_master)
989 free_list_elt (lm->control_list, lm->control_list_len, c->fd);
990 e->key = c->fd = -1;
991 }
992
993 if (c->tx_queues != NULL)
994 {
995 num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +0200996 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
997 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +0200998 for (i = 0; i < num; i++)
999 {
1000 mq = &c->tx_queues[i];
1001 if (mq != NULL)
1002 {
1003 if (mq->int_fd > 0)
1004 close (mq->int_fd);
1005 free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1006 mq->int_fd);
1007 mq->int_fd = -1;
1008 }
1009 }
1010 free (c->tx_queues);
1011 c->tx_queues = NULL;
1012 }
1013
1014 if (c->rx_queues != NULL)
1015 {
1016 num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001017 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1018 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001019 for (i = 0; i < num; i++)
1020 {
1021 mq = &c->rx_queues[i];
1022 if (mq != NULL)
1023 {
1024 if (mq->int_fd > 0)
1025 {
1026 if (c->on_interrupt != NULL)
1027 lm->control_fd_update (mq->int_fd, MEMIF_FD_EVENT_DEL);
1028 close (mq->int_fd);
1029 }
1030 free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1031 mq->int_fd);
1032 mq->int_fd = -1;
1033 }
1034 }
1035 free (c->rx_queues);
1036 c->rx_queues = NULL;
1037 }
1038
1039 if (c->regions != NULL)
1040 {
1041 if (munmap (c->regions[0].shm, c->regions[0].region_size) < 0)
1042 return memif_syscall_error_handler (errno);
1043 if (c->regions[0].fd > 0)
1044 close (c->regions[0].fd);
1045 c->regions[0].fd = -1;
1046 free (c->regions);
1047 c->regions = NULL;
1048 }
1049
1050 memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1051
1052 memif_msg_queue_free (&c->msg_queue);
1053
1054 if (!(c->args.is_master))
1055 {
1056 if (lm->disconn_slaves == 0)
1057 {
1058 if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1059 {
1060 err = memif_syscall_error_handler (errno);
1061 DBG_UNIX ("timerfd_settime: arm");
1062 }
1063 }
1064 lm->disconn_slaves++;
1065 }
1066
1067 return err;
1068}
1069
1070int
1071memif_delete (memif_conn_handle_t * conn)
1072{
1073 memif_connection_t *c = (memif_connection_t *) * conn;
1074 if (c == NULL)
1075 {
1076 DBG ("no connection");
1077 return MEMIF_ERR_NOCONN;
1078 }
1079 libmemif_main_t *lm = &libmemif_main;
1080 memif_list_elt_t *e = NULL;
1081 memif_socket_t *ms = NULL;
1082
1083 int err = MEMIF_ERR_SUCCESS;
1084
1085 if (c->fd > 0)
1086 {
1087 DBG ("DISCONNECTING");
1088 err = memif_disconnect_internal (c);
1089 if (err == MEMIF_ERR_NOCONN)
1090 return err;
1091 }
1092
1093 free_list_elt_ctx (lm->control_list, lm->control_list_len, c);
1094
1095 if (c->args.is_master)
1096 {
1097 get_list_elt (&e, lm->listener_list, lm->listener_list_len,
1098 c->listener_fd);
1099 if (e != NULL)
1100 {
1101 ms = (memif_socket_t *) e->data_struct;
1102 ms->use_count--;
1103 free_list_elt (ms->interface_list, ms->interface_list_len,
1104 c->args.interface_id);
1105 if (ms->use_count <= 0)
1106 {
1107 lm->control_fd_update (c->listener_fd, MEMIF_FD_EVENT_DEL);
1108 free_list_elt (lm->listener_list, lm->listener_list_len,
1109 c->listener_fd);
1110 close (c->listener_fd);
1111 c->listener_fd = ms->fd = -1;
1112 free (ms->interface_list);
1113 ms->interface_list = NULL;
1114 free (ms->filename);
1115 ms->filename = NULL;
1116 free (ms);
1117 ms = NULL;
1118 }
1119 }
1120 }
1121 else
1122 {
1123 lm->disconn_slaves--;
1124 if (lm->disconn_slaves <= 0)
1125 {
1126 if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1127 {
1128 err = memif_syscall_error_handler (errno);
1129 DBG ("timerfd_settime: disarm");
1130 }
1131 }
1132 }
1133
1134 if (c->args.socket_filename)
1135 free (c->args.socket_filename);
1136 c->args.socket_filename = NULL;
1137
1138 free (c);
1139 c = NULL;
1140
1141 *conn = c;
1142 return err;
1143}
1144
1145int
1146memif_connect1 (memif_connection_t * c)
1147{
1148 libmemif_main_t *lm = &libmemif_main;
1149 memif_region_t *mr = c->regions;
1150 memif_queue_t *mq;
1151 int i;
1152 uint16_t num;
1153
1154 if (mr != NULL)
1155 {
1156 if (!mr->shm)
1157 {
1158 if (mr->fd < 0)
1159 return MEMIF_ERR_NO_SHMFD;
1160
1161 if ((mr->shm = mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1162 MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
1163 {
1164 return memif_syscall_error_handler (errno);
1165 }
1166 }
1167 }
1168
1169 num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001170 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1171 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001172 for (i = 0; i < num; i++)
1173 {
1174 mq = &c->tx_queues[i];
1175 if (mq != NULL)
1176 {
1177 mq->ring = c->regions[mq->region].shm + mq->offset;
1178 if (mq->ring->cookie != MEMIF_COOKIE)
1179 {
1180 DBG ("wrong cookie on tx ring %u", i);
1181 return MEMIF_ERR_COOKIE;
1182 }
1183 mq->ring->head = mq->ring->tail = mq->last_head = mq->alloc_bufs =
1184 0;
1185 }
1186 }
1187 num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001188 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1189 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001190 for (i = 0; i < num; i++)
1191 {
1192 mq = &c->rx_queues[i];
1193 if (mq != NULL)
1194 {
1195 mq->ring = c->regions[mq->region].shm + mq->offset;
1196 if (mq->ring->cookie != MEMIF_COOKIE)
1197 {
1198 DBG ("wrong cookie on rx ring %u", i);
1199 return MEMIF_ERR_COOKIE;
1200 }
1201 mq->ring->head = mq->ring->tail = mq->last_head = mq->alloc_bufs =
1202 0;
1203 }
1204 }
1205
1206 lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD);
1207
1208 return 0;
1209}
1210
1211int
1212memif_init_regions_and_queues (memif_connection_t * conn)
1213{
1214 memif_ring_t *ring = NULL;
1215 uint64_t buffer_offset;
1216 memif_region_t *r;
1217 int i, j;
1218 libmemif_main_t *lm = &libmemif_main;
1219 memif_list_elt_t e;
1220
1221 conn->regions = (memif_region_t *) malloc (sizeof (memif_region_t));
1222 if (conn->regions == NULL)
1223 return memif_syscall_error_handler (errno);
1224 r = conn->regions;
1225
1226 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) *
1230 (1 << conn->run_args.log2_ring_size));
1231
1232 r->region_size = buffer_offset +
1233 conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1234 (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1235
1236 if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
1237 return memif_syscall_error_handler (errno);
1238/*
1239 if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1240 return memif_syscall_error_handler (errno);
1241*/
1242 if ((ftruncate (r->fd, r->region_size)) == -1)
1243 return memif_syscall_error_handler (errno);
1244
1245 if ((r->shm = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1246 MAP_SHARED, r->fd, 0)) == MAP_FAILED)
1247 return memif_syscall_error_handler (errno);
1248
1249 for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1250 {
1251 ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1252 DBG ("RING: %p I: %d", ring, i);
1253 ring->head = ring->tail = 0;
1254 ring->cookie = MEMIF_COOKIE;
1255 ring->flags = 0;
1256 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1257 {
1258 uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
1259 ring->desc[j].region = 0;
1260 ring->desc[j].offset = buffer_offset +
1261 (uint32_t) (slot * conn->run_args.buffer_size);
1262 ring->desc[j].buffer_length = conn->run_args.buffer_size;
1263 }
1264 }
1265 for (i = 0; i < conn->run_args.num_m2s_rings; i++)
1266 {
1267 ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
1268 DBG ("RING: %p I: %d", ring, i);
1269 ring->head = ring->tail = 0;
1270 ring->cookie = MEMIF_COOKIE;
1271 ring->flags = 0;
1272 for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1273 {
1274 uint16_t slot =
1275 (i +
1276 conn->run_args.num_s2m_rings) *
1277 (1 << conn->run_args.log2_ring_size) + j;
1278 ring->desc[j].region = 0;
1279 ring->desc[j].offset = buffer_offset +
1280 (uint32_t) (slot * conn->run_args.buffer_size);
1281 ring->desc[j].buffer_length = conn->run_args.buffer_size;
1282 }
1283 }
1284 memif_queue_t *mq;
1285 mq =
1286 (memif_queue_t *) malloc (sizeof (memif_queue_t) *
1287 conn->run_args.num_s2m_rings);
1288 if (mq == NULL)
1289 return memif_syscall_error_handler (errno);
1290 int x;
1291 for (x = 0; x < conn->run_args.num_s2m_rings; x++)
1292 {
1293 if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1294 return memif_syscall_error_handler (errno);
1295 /* add int fd to interrupt fd list */
1296 e.key = mq[x].int_fd;
1297 e.data_struct = conn;
1298 add_list_elt (&e, &lm->interrupt_list, &lm->interrupt_list_len);
1299
1300 mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
1301 DBG ("RING: %p I: %d", mq[x].ring, x);
1302 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1303 mq[x].region = 0;
1304 mq[x].offset =
1305 (void *) mq[x].ring - (void *) conn->regions[mq->region].shm;
1306 mq[x].last_head = 0;
1307 mq[x].alloc_bufs = 0;
1308 }
1309 conn->tx_queues = mq;
1310
1311 mq =
1312 (memif_queue_t *) malloc (sizeof (memif_queue_t) *
1313 conn->run_args.num_m2s_rings);
1314 if (mq == NULL)
1315 return memif_syscall_error_handler (errno);
1316 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);
1320 /* add int fd to interrupt fd list */
1321 e.key = mq[x].int_fd;
1322 e.data_struct = conn;
1323 add_list_elt (&e, &lm->interrupt_list, &lm->interrupt_list_len);
1324
1325 mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
1326 DBG ("RING: %p I: %d", mq[x].ring, x);
1327 mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1328 mq[x].region = 0;
1329 mq[x].offset =
1330 (void *) mq[x].ring - (void *) conn->regions[mq->region].shm;
1331 mq[x].last_head = 0;
1332 mq[x].alloc_bufs = 0;
1333 }
1334 conn->rx_queues = mq;
1335
1336 return 0;
1337}
1338
1339int
1340memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
1341 memif_buffer_t * bufs, uint16_t count,
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001342 uint16_t * count_out, uint16_t size)
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001343{
1344 memif_connection_t *c = (memif_connection_t *) conn;
1345 if (c == NULL)
1346 return MEMIF_ERR_NOCONN;
1347 if (c->fd < 0)
1348 return MEMIF_ERR_DISCONNECTED;
1349 uint8_t num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001350 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1351 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001352 if (qid >= num)
1353 return MEMIF_ERR_QID;
1354 memif_queue_t *mq = &c->tx_queues[qid];
1355 memif_ring_t *ring = mq->ring;
1356 memif_buffer_t *b0, *b1;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001357 uint8_t chain_buf0, chain_buf1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001358 uint16_t mask = (1 << mq->log2_ring_size) - 1;
1359 uint16_t s0, s1, ns;
1360 *count_out = 0;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001361 int i, err = MEMIF_ERR_SUCCESS; /* 0 */
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001362
1363 if (ring->tail != ring->head)
1364 {
1365 if (ring->head > ring->tail)
1366 ns = (1 << mq->log2_ring_size) - ring->head + ring->tail;
1367 else
1368 ns = ring->tail - ring->head;
1369 }
1370 else
1371 ns = (1 << mq->log2_ring_size);
1372
1373 /* (head == tail) ? receive function will asume that no packets are available */
1374 ns -= 1;
1375
1376 while (count && ns)
1377 {
1378 while ((count > 2) && (ns > 2))
1379 {
1380 s0 = (ring->head + mq->alloc_bufs + *count_out) & mask;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001381 chain_buf0 = size / ring->desc[s0].buffer_length;
1382 if (((size % ring->desc[s0].buffer_length) != 0) || (size == 0))
1383 chain_buf0++;
1384
1385 if (chain_buf0 > ns)
1386 break;
1387
1388 s1 = (ring->head + mq->alloc_bufs + *count_out + chain_buf0) & mask;
1389 chain_buf1 = size / ring->desc[s1].buffer_length;
1390 if (((size % ring->desc[s1].buffer_length) != 0) || (size == 0))
1391 chain_buf1++;
1392
1393 if ((chain_buf0 + chain_buf1) > ns)
1394 break;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001395
1396 b0 = (bufs + *count_out);
1397 b1 = (bufs + *count_out + 1);
1398
1399 b0->desc_index = s0;
1400 b1->desc_index = s1;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001401 b0->buffer_len = ring->desc[s0].buffer_length * chain_buf0;
1402 b1->buffer_len = ring->desc[s1].buffer_length * chain_buf1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001403 /* TODO: support multiple regions -> ring descriptor contains region index */
1404 b0->data = c->regions->shm + ring->desc[s0].offset;
1405 b1->data = c->regions->shm + ring->desc[s1].offset;
1406
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001407 for (i = 0; i < (memif_min (chain_buf0, chain_buf1) - 1); i++)
1408 {
1409 ring->desc[(s0 + i) & mask].flags |= MEMIF_DESC_FLAG_NEXT;
1410 ring->desc[(s1 + i) & mask].flags |= MEMIF_DESC_FLAG_NEXT;
1411 DBG ("allocating chained buffers");
1412 }
1413
1414 if (chain_buf0 > chain_buf1)
1415 {
1416 for (; i < (chain_buf0 - 1); i++)
1417 ring->desc[(s0 + i) & mask].flags |= MEMIF_DESC_FLAG_NEXT;
1418 }
1419 else
1420 {
1421 for (; i < (chain_buf1 - 1); i++)
1422 ring->desc[(s1 + i) & mask].flags |= MEMIF_DESC_FLAG_NEXT;
1423 }
1424
1425 mq->alloc_bufs += chain_buf0 + chain_buf1;
1426
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001427 DBG ("allocated ring slots %u, %u", s0, s1);
1428 count -= 2;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001429 ns -= chain_buf0 + chain_buf1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001430 *count_out += 2;
1431 }
1432 s0 = (ring->head + mq->alloc_bufs + *count_out) & mask;
1433
1434 b0 = (bufs + *count_out);
1435
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001436 chain_buf0 = size / ring->desc[s0].buffer_length;
1437 if (((size % ring->desc[s0].buffer_length) != 0) || (size == 0))
1438 chain_buf0++;
1439
1440 if (chain_buf0 > ns)
1441 break;
1442
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001443 b0->desc_index = s0;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001444 b0->buffer_len = ring->desc[s0].buffer_length * chain_buf0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001445 b0->data = c->regions->shm + ring->desc[s0].offset;
1446
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001447 for (i = 0; i < (chain_buf0 - 1); i++)
1448 {
1449 ring->desc[(s0 + i) & mask].flags |= MEMIF_DESC_FLAG_NEXT;
1450 DBG ("allocating chained buffers");
1451 }
1452
1453 mq->alloc_bufs += chain_buf0;
1454
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001455 DBG ("allocated ring slot %u", s0);
1456 count--;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001457 ns -= chain_buf0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001458 *count_out += 1;
1459 }
1460
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001461 DBG ("allocated: %u/%u bufs. Total %u allocated bufs", *count_out, count,
1462 mq->alloc_bufs);
1463
1464 if (count)
1465 {
1466 DBG ("ring buffer full! qid: %u", qid);
1467 err = MEMIF_ERR_NOBUF_RING;
1468 }
1469
1470 return err;
1471}
1472
1473int
1474memif_buffer_free (memif_conn_handle_t conn, uint16_t qid,
1475 memif_buffer_t * bufs, uint16_t count,
1476 uint16_t * count_out)
1477{
1478 memif_connection_t *c = (memif_connection_t *) conn;
1479 if (c == NULL)
1480 return MEMIF_ERR_NOCONN;
1481 if (c->fd < 0)
1482 return MEMIF_ERR_DISCONNECTED;
1483 uint8_t num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001484 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1485 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001486 if (qid >= num)
1487 return MEMIF_ERR_QID;
1488 libmemif_main_t *lm = &libmemif_main;
1489 memif_queue_t *mq = &c->rx_queues[qid];
1490 memif_ring_t *ring = mq->ring;
1491 uint16_t tail = ring->tail;
1492 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001493 uint8_t chain_buf0, chain_buf1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001494 memif_buffer_t *b0, *b1;
1495 *count_out = 0;
1496
1497 if (mq->alloc_bufs < count)
1498 count = mq->alloc_bufs;
1499
1500 while (count)
1501 {
1502 while (count > 2)
1503 {
1504 b0 = (bufs + *count_out);
1505 b1 = (bufs + *count_out + 1);
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001506 chain_buf0 =
1507 b0->buffer_len / ring->desc[b0->desc_index].buffer_length;
1508 if ((b0->buffer_len % ring->desc[b0->desc_index].buffer_length) !=
1509 0)
1510 chain_buf0++;
1511 chain_buf1 =
1512 b1->buffer_len / ring->desc[b1->desc_index].buffer_length;
1513 if ((b1->buffer_len % ring->desc[b1->desc_index].buffer_length) !=
1514 0)
1515 chain_buf1++;
1516 tail = (b0->desc_index + chain_buf0) & mask;
1517 tail = (b1->desc_index + chain_buf1) & mask;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001518 b0->data = NULL;
1519 b1->data = NULL;
1520
1521 count -= 2;
1522 *count_out += 2;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001523 mq->alloc_bufs -= chain_buf0 + chain_buf1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001524 }
1525 b0 = (bufs + *count_out);
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001526 chain_buf0 = b0->buffer_len / ring->desc[b0->desc_index].buffer_length;
1527 if ((b0->buffer_len % ring->desc[b0->desc_index].buffer_length) != 0)
1528 chain_buf0++;
1529 tail = (b0->desc_index + chain_buf0) & mask;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001530 b0->data = NULL;
1531
1532 count--;
1533 *count_out += 1;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001534 mq->alloc_bufs -= chain_buf0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001535 }
1536 MEMIF_MEORY_BARRIER ();
1537 ring->tail = tail;
1538
1539 return MEMIF_ERR_SUCCESS; /* 0 */
1540}
1541
1542int
1543memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
1544 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
1545{
1546 memif_connection_t *c = (memif_connection_t *) conn;
1547 if (c == NULL)
1548 return MEMIF_ERR_NOCONN;
1549 if (c->fd < 0)
1550 return MEMIF_ERR_DISCONNECTED;
1551 uint8_t num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001552 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1553 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001554 if (qid >= num)
1555 return MEMIF_ERR_QID;
1556 memif_queue_t *mq = &c->tx_queues[qid];
1557 memif_ring_t *ring = mq->ring;
1558 uint16_t head = ring->head;
1559 uint16_t mask = (1 << mq->log2_ring_size) - 1;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001560 uint8_t chain_buf0, chain_buf1;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001561 *tx = 0;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001562 uint16_t curr_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001563 memif_buffer_t *b0, *b1;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001564 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001565
1566 while (count)
1567 {
1568 while (count > 2)
1569 {
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001570 b0 = (bufs + curr_buf);
1571 b1 = (bufs + curr_buf + 1);
1572 chain_buf0 =
1573 b0->buffer_len / ring->desc[b0->desc_index].buffer_length;
1574 if ((b0->buffer_len % ring->desc[b0->desc_index].buffer_length) !=
1575 0)
1576 chain_buf0++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001577
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001578 chain_buf1 =
1579 b1->buffer_len / ring->desc[b1->desc_index].buffer_length;
1580 if ((b1->buffer_len % ring->desc[b1->desc_index].buffer_length) !=
1581 0)
1582 chain_buf1++;
1583
1584 for (i = 0; i < memif_min (chain_buf0, chain_buf1); i++)
1585 {
1586 ring->desc[(b0->desc_index + i) & mask].length = b0->data_len;
1587 ring->desc[(b1->desc_index + i) & mask].length = b1->data_len;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001588#ifdef MEMIF_DBG_SHM
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001589 print_bytes (b0->data +
1590 ring->desc[(b0->desc_index +
1591 i) & mask].buffer_length *
1592 (chain_buf0 - 1),
1593 ring->desc[(b0->desc_index +
1594 i) & mask].buffer_length, DBG_TX_BUF);
1595 print_bytes (b1->data +
1596 ring->desc[(b1->desc_index +
1597 i) & mask].buffer_length *
1598 (chain_buf1 - 1),
1599 ring->desc[(b1->desc_index +
1600 i) & mask].buffer_length, DBG_TX_BUF);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001601#endif
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001602 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001603
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001604 if (chain_buf0 > chain_buf1)
1605 {
1606 for (; i < chain_buf0; i++)
1607 {
1608 ring->desc[(b0->desc_index + i) & mask].length =
1609 b0->data_len;
1610#ifdef MEMIF_DBG_SHM
1611 print_bytes (b0->data +
1612 ring->desc[(b0->desc_index +
1613 i) & mask].buffer_length *
1614 (chain_buf0 - 1),
1615 ring->desc[(b0->desc_index +
1616 i) & mask].buffer_length,
1617 DBG_TX_BUF);
1618#endif
1619 }
1620 }
1621 else
1622 {
1623 for (; i < chain_buf1; i++)
1624 {
1625 ring->desc[b1->desc_index + i].length = b1->data_len;
1626#ifdef MEMIF_DBG_SHM
1627 print_bytes (b1->data +
1628 ring->desc[(b1->desc_index +
1629 i) & mask].buffer_length *
1630 (chain_buf1 - 1),
1631 ring->desc[(b1->desc_index +
1632 i) & mask].buffer_length,
1633 DBG_TX_BUF);
1634#endif
1635 }
1636 }
1637
1638 head = (b0->desc_index + chain_buf0) & mask;
1639 head = (b1->desc_index + chain_buf1) & mask;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001640
1641 b0->data = NULL;
1642 b0->data_len = 0;
1643 b1->data = NULL;
1644 b1->data_len = 0;
1645
1646 count -= 2;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001647 *tx += chain_buf0 + chain_buf1;
1648 curr_buf += 2;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001649 }
1650
1651 b0 = (bufs + *tx);
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001652 chain_buf0 = b0->buffer_len / ring->desc[b0->desc_index].buffer_length;
1653 if ((b0->buffer_len % ring->desc[b0->desc_index].buffer_length) != 0)
1654 chain_buf0++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001655
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001656 for (i = 0; i < chain_buf0; i++)
1657 {
1658 ring->desc[(b0->desc_index + i) & mask].length = b0->data_len;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001659#ifdef MEMIF_DBG_SHM
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001660 print_bytes (b0->data +
1661 ring->desc[(b0->desc_index + i) & mask].buffer_length *
1662 (chain_buf0 - 1),
1663 ring->desc[(b0->desc_index + i) & mask].buffer_length,
1664 DBG_TX_BUF);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001665#endif
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001666 }
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001667
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001668 head = (b0->desc_index + chain_buf0) & mask;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001669
1670 b0->data = NULL;
1671 b0->data_len = 0;
1672
1673 count--;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001674 *tx += chain_buf0;
1675 curr_buf++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001676 }
1677 MEMIF_MEORY_BARRIER ();
1678 ring->head = head;
1679
1680 mq->alloc_bufs -= *tx;
1681
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001682 /* TODO: return num of buffers and packets */
1683 *tx = curr_buf;
1684
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001685 if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
1686 {
1687 uint64_t a = 1;
1688 int r = write (mq->int_fd, &a, sizeof (a));
1689 if (r < 0)
1690 return MEMIF_ERR_INT_WRITE;
1691 }
1692
1693 return MEMIF_ERR_SUCCESS; /* 0 */
1694}
1695
1696int
1697memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
1698 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
1699{
1700 memif_connection_t *c = (memif_connection_t *) conn;
1701 if (c == NULL)
1702 return MEMIF_ERR_NOCONN;
1703 if (c->fd < 0)
1704 return MEMIF_ERR_DISCONNECTED;
1705 uint8_t num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001706 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1707 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001708 if (qid >= num)
1709 return MEMIF_ERR_QID;
1710 memif_queue_t *mq = &c->rx_queues[qid];
1711 memif_ring_t *ring = mq->ring;
1712 uint16_t head = ring->head;
1713 uint16_t ns;
1714 uint16_t mask = (1 << mq->log2_ring_size) - 1;
1715 memif_buffer_t *b0, *b1;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001716 uint16_t curr_buf = 0;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001717 *rx = 0;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001718 int i;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001719
1720 uint64_t b;
1721 ssize_t r = read (mq->int_fd, &b, sizeof (b));
1722 if ((r == -1) && (errno != EAGAIN))
1723 return memif_syscall_error_handler (errno);
1724
1725 if (head == mq->last_head)
1726 return 0;
1727
1728 if (head > mq->last_head)
1729 ns = head - mq->last_head;
1730 else
1731 ns = (1 << mq->log2_ring_size) - mq->last_head + head;
1732
1733 while (ns && count)
1734 {
1735 while ((ns > 2) && (count > 2))
1736 {
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001737 b0 = (bufs + curr_buf);
1738 b1 = (bufs + curr_buf + 1);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001739
1740 b0->desc_index = mq->last_head;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001741 i = 0;
1742 do
1743 {
1744 b0->data = memif_get_buffer (conn, ring, mq->last_head);
1745 b0->data_len = ring->desc[mq->last_head].length;
1746 b0->buffer_len = ring->desc[mq->last_head].buffer_length;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001747#ifdef MEMIF_DBG_SHM
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001748 print_bytes (b0->data +
1749 ring->desc[b0->desc_index].buffer_length * i++,
1750 ring->desc[b0->desc_index].buffer_length,
1751 DBG_TX_BUF);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001752#endif
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001753 mq->last_head = (mq->last_head + 1) & mask;
1754 ns--;
1755 *rx += 1;
1756 }
1757 while (ring->desc[mq->last_head].flags & MEMIF_DESC_FLAG_NEXT);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001758
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001759 b1->desc_index = mq->last_head;
1760 i = 0;
1761 do
1762 {
1763 b1->data = memif_get_buffer (conn, ring, mq->last_head);
1764 b1->data_len = ring->desc[mq->last_head].length;
1765 b1->buffer_len = ring->desc[mq->last_head].buffer_length;
1766#ifdef MEMIF_DBG_SHM
1767 print_bytes (b1->data +
1768 ring->desc[b1->desc_index].buffer_length * i++,
1769 ring->desc[b1->desc_index].buffer_length,
1770 DBG_TX_BUF);
1771#endif
1772 mq->last_head = (mq->last_head + 1) & mask;
1773 ns--;
1774 *rx += 1;
1775 }
1776 while (ring->desc[mq->last_head].flags & MEMIF_DESC_FLAG_NEXT);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001777
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001778 count -= 2;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001779 curr_buf += 2;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001780 }
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001781 b0 = (bufs + curr_buf);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001782
1783 b0->desc_index = mq->last_head;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001784 i = 0;
1785 do
1786 {
1787 b0->data = memif_get_buffer (conn, ring, mq->last_head);
1788 b0->data_len = ring->desc[mq->last_head].length;
1789 b0->buffer_len = ring->desc[mq->last_head].buffer_length;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001790#ifdef MEMIF_DBG_SHM
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001791 print_bytes (b0->data +
1792 ring->desc[b0->desc_index].buffer_length * i++,
1793 ring->desc[b0->desc_index].buffer_length, DBG_TX_BUF);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001794#endif
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001795 mq->last_head = (mq->last_head + 1) & mask;
1796 ns--;
1797 *rx += 1;
1798 }
1799 while (ring->desc[mq->last_head].flags & MEMIF_DESC_FLAG_NEXT);
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001800
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001801 count--;
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001802 curr_buf++;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001803 }
1804
1805 mq->alloc_bufs += *rx;
1806
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001807 /* TODO: return num of buffers and packets */
1808 *rx = curr_buf;
1809
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001810 if (ns)
1811 {
1812 DBG ("not enough buffers!");
1813 return MEMIF_ERR_NOBUF;
1814 }
1815
1816 return MEMIF_ERR_SUCCESS; /* 0 */
1817}
1818
1819int
1820memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
1821 char *buf, ssize_t buflen)
1822{
1823 memif_connection_t *c = (memif_connection_t *) conn;
1824 if (c == NULL)
1825 return MEMIF_ERR_NOCONN;
1826
1827 int err = MEMIF_ERR_SUCCESS, i;
1828 ssize_t l0, l1, total_l;
1829 l0 = 0;
1830
1831 l1 = strlen ((char *) c->args.interface_name);
1832 if (l0 + l1 <= buflen)
1833 {
1834 md->if_name = strncpy (buf + l0, (char *) c->args.interface_name, l1);
1835 md->if_name[l0 + l1] = '\0';
1836 l0 += l1 + 1;
1837 }
1838 else
1839 err = MEMIF_ERR_NOBUF_DET;
1840
1841 l1 = strlen ((char *) c->args.instance_name);
1842 if (l0 + l1 <= buflen)
1843 {
1844 md->inst_name = strncpy (buf + l0, (char *) c->args.instance_name, l1);
1845 md->inst_name[l0 + l1] = '\0';
1846 l0 += l1 + 1;
1847 }
1848 else
1849 err = MEMIF_ERR_NOBUF_DET;
1850
1851 l1 = strlen ((char *) c->remote_if_name);
1852 if (l0 + l1 <= buflen)
1853 {
1854 md->remote_if_name = strncpy (buf + l0, (char *) c->remote_if_name, l1);
1855 md->remote_if_name[l0 + l1] = '\0';
1856 l0 += l1 + 1;
1857 }
1858 else
1859 err = MEMIF_ERR_NOBUF_DET;
1860
1861 l1 = strlen ((char *) c->remote_name);
1862 if (l0 + l1 <= buflen)
1863 {
1864 md->remote_inst_name = strncpy (buf + l0, (char *) c->remote_name, l1);
1865 md->remote_inst_name[l0 + l1] = '\0';
1866 l0 += l1 + 1;
1867 }
1868 else
1869 err = MEMIF_ERR_NOBUF_DET;
1870
1871 md->id = c->args.interface_id;
1872
1873 if (c->args.secret)
1874 {
1875 l1 = strlen ((char *) c->args.secret);
1876 md->secret = strncpy (buf + l0, (char *) c->args.secret, l1);
1877 md->secret[l0 + l1] = '\0';
1878 l0 += l1 + 1;
1879 }
1880 else
1881 err = MEMIF_ERR_NOBUF_DET;
1882
1883 md->role = (c->args.is_master) ? 0 : 1;
1884 md->mode = c->args.mode;
1885
1886 l1 = strlen ((char *) c->args.socket_filename);
1887 if (l0 + l1 <= buflen)
1888 {
1889 md->socket_filename =
1890 strncpy (buf + l0, (char *) c->args.socket_filename, l1);
1891 md->socket_filename[l0 + l1] = '\0';
1892 l0 += l1 + 1;
1893 }
1894 else
1895 err = MEMIF_ERR_NOBUF_DET;
1896
1897 md->rx_queues_num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001898 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1899 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001900
1901 l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
1902 if (l0 + l1 <= buflen)
1903 {
1904 md->rx_queues = (memif_queue_details_t *) buf + l0;
1905 l0 = l1 + 1;
1906 }
1907 else
1908 err = MEMIF_ERR_NOBUF_DET;
1909
1910 for (i = 0; i < md->rx_queues_num; i++)
1911 {
1912 md->rx_queues[i].qid = i;
1913 md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
1914 md->rx_queues[i].buffer_size = c->run_args.buffer_size;
1915 }
1916
1917 md->tx_queues_num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001918 (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1919 run_args.num_s2m_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001920
1921 l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
1922 if (l0 + l1 <= buflen)
1923 {
1924 md->tx_queues = (memif_queue_details_t *) buf + l0;
1925 l0 = l1 + 1;
1926 }
1927 else
1928 err = MEMIF_ERR_NOBUF_DET;
1929
1930 for (i = 0; i < md->tx_queues_num; i++)
1931 {
1932 md->tx_queues[i].qid = i;
1933 md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
1934 md->tx_queues[i].buffer_size = c->run_args.buffer_size;
1935 }
1936
1937 md->link_up_down = (c->fd > 0) ? 1 : 0;
1938
1939 return err; /* 0 */
1940}
1941
1942int
1943memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
1944{
1945 memif_connection_t *c = (memif_connection_t *) conn;
1946 *efd = -1;
1947 if (c == NULL)
1948 return MEMIF_ERR_NOCONN;
1949 if (c->fd < 0)
1950 return MEMIF_ERR_DISCONNECTED;
1951 uint8_t num =
Jakub Grajciarb467b2a2017-09-14 14:12:10 +02001952 (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1953 run_args.num_m2s_rings;
Jakub Grajciar7c5c40d2017-08-30 10:13:25 +02001954 if (qid >= num)
1955 return MEMIF_ERR_QID;
1956
1957 *efd = c->rx_queues[qid].int_fd;
1958
1959 return MEMIF_ERR_SUCCESS;
1960}
1961
1962int
1963memif_cleanup ()
1964{
1965 libmemif_main_t *lm = &libmemif_main;
1966 if (lm->app_name)
1967 free (lm->app_name);
1968 lm->app_name = NULL;
1969 if (lm->control_list)
1970 free (lm->control_list);
1971 lm->control_list = NULL;
1972 if (lm->interrupt_list)
1973 free (lm->interrupt_list);
1974 lm->interrupt_list = NULL;
1975 if (lm->listener_list)
1976 free (lm->listener_list);
1977 lm->listener_list = NULL;
1978 if (lm->pending_list)
1979 free (lm->pending_list);
1980 lm->pending_list = NULL;
1981
1982 return MEMIF_ERR_SUCCESS; /* 0 */
1983}