6a8e8b942dd5be5849fae2d99ddd0cc5b82dd4c3
[vpp.git] / extras / libmemif / src / main.c
1 /*
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 #define _GNU_SOURCE
19 #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>
48 #include <linux/memfd.h>
49
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
59 #define ERRLIST_LEN 40
60 #define MAX_ERRBUF_LEN 256
61
62 #if __x86_x64__
63 #define MEMIF_MEMORY_BARRIER() __builtin_ia32_sfence ()
64 #else
65 #define MEMIF_MEMORY_BARRIER() __sync_synchronize ()
66 #endif /* __x86_x64__ */
67
68 static char memif_buf[MAX_ERRBUF_LEN];
69
70 const 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).",
74   /* MEMIF_ERR_CONNREFUSED */
75   "Connection refused",
76   /* MEMIF_ERR_ACCES */
77   "Permission to resource denied.",
78   /* 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 */
95   "Memif connection handle does not point to existing connection",
96   /* 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 */
111   "Not enough space for memif details in supplied buffer. String data might be malformed.",
112   /* 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 */
123   "Slave cannot accept connection request.",
124   /* 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 */
143   "Unknown message type received on control channel. (internal error)",
144   /* MEMIF_ERR_POLL_CANCEL */
145   "Memif event polling was canceled.",
146   /* MEMIF_ERR_MAX_RING */
147   "Maximum log2 ring size is 15",
148   /* MEMIF_ERR_PRIVHDR */
149   "Private headers not supported."
150 };
151
152 #define MEMIF_ERR_UNDEFINED "undefined error"
153
154 char *
155 memif_strerror (int err_code)
156 {
157   if (err_code >= ERRLIST_LEN)
158     {
159       strlcpy (memif_buf, MEMIF_ERR_UNDEFINED, sizeof (memif_buf));
160     }
161   else
162     {
163       strlcpy (memif_buf, memif_errlist[err_code], sizeof (memif_buf));
164       memif_buf[strlen (memif_errlist[err_code])] = '\0';
165     }
166   return memif_buf;
167 }
168
169 uint16_t
170 memif_get_version ()
171 {
172   return MEMIF_VERSION;
173 }
174
175 const char *
176 memif_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
185 #define DBG_TX_BUF (0)
186 #define DBG_RX_BUF (1)
187
188 #ifdef MEMIF_DBG_SHM
189 static void
190 print_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 }
205 #endif /* MEMIF_DBG_SHM */
206
207 int
208 memif_syscall_error_handler (int err_code)
209 {
210   DBG ("%s", strerror (err_code));
211
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;
222 /* connection refused if master does not exist
223     this error would spam the user until master was created */
224 /*
225   if (err_code == ECONNREFUSED)
226     return MEMIF_ERR_SUCCESS;
227 */
228   if (err_code == ECONNREFUSED)
229     return MEMIF_ERR_CONNREFUSED;
230   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
243 static int
244 memif_add_epoll_fd (memif_socket_t *ms, memif_fd_event_t fde, uint32_t events)
245 {
246   if (fde.fd < 0)
247     {
248       DBG ("invalid fd %d", fde.fd);
249       return -1;
250     }
251   struct epoll_event evt;
252   memset (&evt, 0, sizeof (evt));
253   evt.events = events;
254   evt.data.ptr = fde.private_ctx;
255   if (epoll_ctl (ms->epfd, EPOLL_CTL_ADD, fde.fd, &evt) < 0)
256     {
257       DBG ("epoll_ctl: %s fd %d", strerror (errno), fde.fd);
258       return -1;
259     }
260   DBG ("fd %d added to epoll", fde.fd);
261   return 0;
262 }
263
264 static int
265 memif_mod_epoll_fd (memif_socket_t *ms, memif_fd_event_t fde, uint32_t events)
266 {
267   if (fde.fd < 0)
268     {
269       DBG ("invalid fd %d", fde.fd);
270       return -1;
271     }
272   struct epoll_event evt;
273   memset (&evt, 0, sizeof (evt));
274   evt.events = events;
275   evt.data.ptr = fde.private_ctx;
276   if (epoll_ctl (ms->epfd, EPOLL_CTL_MOD, fde.fd, &evt) < 0)
277     {
278       DBG ("epoll_ctl: %s fd %d", strerror (errno), fde.fd);
279       return -1;
280     }
281   DBG ("fd %d modified on epoll", fde.fd);
282   return 0;
283 }
284
285 static int
286 memif_del_epoll_fd (memif_socket_t *ms, memif_fd_event_t fde)
287 {
288   if (fde.fd < 0)
289     {
290       DBG ("invalid fd %d", fde.fd);
291       return -1;
292     }
293   struct epoll_event evt;
294   memset (&evt, 0, sizeof (evt));
295   if (epoll_ctl (ms->epfd, EPOLL_CTL_DEL, fde.fd, &evt) < 0)
296     {
297       DBG ("epoll_ctl: %s fd %d", strerror (errno), fde.fd);
298       return -1;
299     }
300   DBG ("fd %d removed from epoll", fde.fd);
301   return 0;
302 }
303
304 int
305 memif_control_fd_update (memif_fd_event_t fde, void *private_ctx)
306 {
307   memif_socket_t *ms = (memif_socket_t *) private_ctx;
308   int fd;
309
310   if (ms == NULL)
311     return MEMIF_ERR_INVAL_ARG;
312
313   if (fde.type & MEMIF_FD_EVENT_DEL)
314     return memif_del_epoll_fd (ms, fde);
315
316   uint32_t evt = 0;
317   if (fde.type & MEMIF_FD_EVENT_READ)
318     evt |= EPOLLIN;
319   if (fde.type & MEMIF_FD_EVENT_WRITE)
320     evt |= EPOLLOUT;
321
322   if (fde.type & MEMIF_FD_EVENT_MOD)
323     return memif_mod_epoll_fd (ms, fde, evt);
324
325   return memif_add_epoll_fd (ms, fde, evt);
326 }
327
328 static void
329 memif_control_fd_update_register (memif_socket_t *ms,
330                                   memif_control_fd_update_t *cb)
331 {
332   ms->args.on_control_fd_update = cb;
333 }
334
335 void
336 memif_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)
341 {
342   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;
347 }
348
349 static void
350 memif_alloc_register (memif_socket_t *ms, memif_alloc_t *ma)
351 {
352   ms->args.alloc = ma;
353 }
354
355 static void
356 memif_realloc_register (memif_socket_t *ms, memif_realloc_t *mr)
357 {
358   ms->args.realloc = mr;
359 }
360
361 static void
362 memif_free_register (memif_socket_t *ms, memif_free_t *mf)
363 {
364   ms->args.free = mf;
365 }
366
367 static inline memif_ring_t *
368 memif_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;
373   void *p = conn->regions[0].addr;
374   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
382 int
383 memif_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 =
390     (conn->args.is_master) ? conn->run_args.num_s2m_rings : conn->
391     run_args.num_m2s_rings;
392   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
400 int
401 memif_poll_cancel_handler (memif_fd_event_type_t type, void *private_ctx)
402 {
403   return MEMIF_ERR_POLL_CANCEL;
404 }
405
406 int
407 memif_connect_handler (memif_fd_event_type_t type, void *private_ctx)
408 {
409   memif_socket_t *ms = (memif_socket_t *) private_ctx;
410   memif_connection_t *c;
411
412   /* loop ms->slave_interfaces and request connection for disconnected ones */
413   TAILQ_FOREACH (c, &ms->slave_interfaces, next)
414   {
415     /* connected or connecting */
416     if (c->control_channel != NULL)
417       continue;
418
419     /* ignore errors */
420     memif_request_connection (c);
421   }
422
423   return MEMIF_ERR_SUCCESS;
424 }
425
426 int
427 memif_set_connection_request_timer (memif_socket_handle_t sock,
428                                     struct itimerspec timer)
429 {
430   memif_socket_t *ms = (memif_socket_t *) sock;
431   memif_fd_event_t fde;
432   memif_fd_event_data_t *fdata;
433   void *ctx;
434
435   if (ms == NULL)
436     return MEMIF_ERR_INVAL_ARG;
437
438   if (ms->timer_fd < 0)
439     {
440       /* only create new timer if there is a valid interval */
441       if (timer.it_interval.tv_sec == 0 && timer.it_interval.tv_nsec == 0)
442         return MEMIF_ERR_SUCCESS;
443
444       /* create timerfd */
445       ms->timer_fd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
446       if (ms->timer_fd < 0)
447         return memif_syscall_error_handler (errno);
448
449       /* start listening for events */
450       fdata = ms->args.alloc (sizeof (*fdata));
451       fdata->event_handler = memif_connect_handler;
452       fdata->private_ctx = ms;
453
454       fde.fd = ms->timer_fd;
455       fde.type = MEMIF_FD_EVENT_READ;
456       fde.private_ctx = fdata;
457
458       ctx = ms->epfd != -1 ? ms : ms->private_ctx;
459       ms->args.on_control_fd_update (fde, ctx);
460     }
461
462   ms->args.connection_request_timer = timer;
463
464   /* arm the timer */
465   if (timerfd_settime (ms->timer_fd, 0, &ms->args.connection_request_timer,
466                        NULL) < 0)
467     return memif_syscall_error_handler (errno);
468
469   return MEMIF_ERR_SUCCESS;
470 }
471
472 int
473 memif_create_socket (memif_socket_handle_t *sock, memif_socket_args_t *args,
474                      void *private_ctx)
475 {
476   memif_socket_t *ms = (memif_socket_t *) * sock;
477   memif_fd_event_t fde;
478   memif_fd_event_data_t *fdata;
479   int i, err = MEMIF_ERR_SUCCESS;
480   void *ctx;
481
482   /* allocate memif_socket_t */
483   ms = NULL;
484   if (args->alloc != NULL)
485     ms = args->alloc (sizeof (memif_socket_t));
486   else
487     ms = malloc (sizeof (memif_socket_t));
488   if (ms == NULL)
489     {
490       err = MEMIF_ERR_NOMEM;
491       goto error;
492     }
493
494   /* default values */
495   memset (ms, 0, sizeof (memif_socket_t));
496   ms->epfd = -1;
497   ms->listener_fd = -1;
498   ms->poll_cancel_fd = -1;
499   ms->timer_fd = -1;
500
501   /* copy arguments to internal struct */
502   memcpy (&ms->args, args, sizeof (*args));
503   /* Handle abstract socket by converting '@' -> '\0' */
504   if (ms->args.path[0] == '@')
505     ms->args.path[0] = '\0';
506   ms->private_ctx = private_ctx;
507
508   if (ms->args.alloc == NULL)
509     memif_alloc_register (ms, malloc);
510   if (ms->args.realloc == NULL)
511     memif_realloc_register (ms, realloc);
512   if (ms->args.free == NULL)
513     memif_free_register (ms, free);
514
515   TAILQ_INIT (&ms->master_interfaces);
516   TAILQ_INIT (&ms->slave_interfaces);
517
518   /* FIXME: implement connection request timer */
519
520   /* initialize internal epoll */
521   if (ms->args.on_control_fd_update == NULL)
522     {
523       ms->epfd = epoll_create (1);
524       /* register default fd update callback */
525       memif_control_fd_update_register (ms, memif_control_fd_update);
526       ms->poll_cancel_fd = eventfd (0, EFD_NONBLOCK);
527       if (ms->poll_cancel_fd < 0)
528         {
529           err = errno;
530           DBG ("eventfd: %s", strerror (err));
531           return memif_syscall_error_handler (err);
532         }
533       /* add interrupt fd to epfd */
534       fdata = ms->args.alloc (sizeof (*fdata));
535       fdata->event_handler = memif_poll_cancel_handler;
536       fdata->private_ctx = ms;
537
538       fde.fd = ms->poll_cancel_fd;
539       fde.type = MEMIF_FD_EVENT_READ;
540       fde.private_ctx = fdata;
541
542       ctx = ms->epfd != -1 ? ms : ms->private_ctx;
543       ms->args.on_control_fd_update (fde, ctx);
544     }
545
546   err =
547     memif_set_connection_request_timer (ms, ms->args.connection_request_timer);
548   if (err != MEMIF_ERR_SUCCESS)
549     goto error;
550
551   *sock = ms;
552
553   return err;
554
555 error:
556   if (ms != NULL)
557     {
558       ms->args.free (ms);
559       if (ms->epfd != -1)
560         close (ms->epfd);
561       if (ms->poll_cancel_fd != -1)
562         close (ms->poll_cancel_fd);
563     }
564   return err;
565 }
566
567 memif_socket_handle_t
568 memif_get_socket_handle (memif_conn_handle_t conn)
569 {
570   memif_connection_t *c = (memif_connection_t *) conn;
571
572   if (c == NULL)
573     return NULL;
574
575   return c->args.socket;
576 }
577
578 const char *
579 memif_get_socket_path (memif_socket_handle_t sock)
580 {
581   memif_socket_t *ms = (memif_socket_t *) sock;
582
583   if (ms == NULL)
584     return NULL;
585
586   return ms->args.path;
587 }
588
589 int
590 memif_get_listener_fd (memif_socket_handle_t sock)
591 {
592   memif_socket_t *ms = (memif_socket_t *) sock;
593
594   if (ms == NULL)
595     return -1;
596
597   return ms->listener_fd;
598 }
599
600 int
601 memif_set_listener_fd (memif_socket_handle_t sock, int fd)
602 {
603   memif_socket_t *ms = (memif_socket_t *) sock;
604   memif_fd_event_t fde;
605   memif_fd_event_data_t *fdata;
606   void *ctx;
607
608   if ((ms == NULL) || (fd < 0))
609     return MEMIF_ERR_INVAL_ARG;
610
611   fdata = ms->args.alloc (sizeof (*fdata));
612   if (fdata == NULL)
613     return MEMIF_ERR_NOMEM;
614
615   ms->listener_fd = fd;
616
617   fdata->event_handler = memif_listener_handler;
618   fdata->private_ctx = ms;
619   ctx = ms->epfd != -1 ? ms : ms->private_ctx;
620   /* send fd to epoll */
621   fde.fd = ms->listener_fd;
622   fde.type = MEMIF_FD_EVENT_READ;
623   fde.private_ctx = fdata;
624   ms->args.on_control_fd_update (fde, ctx);
625
626   return MEMIF_ERR_SUCCESS;
627 }
628
629 int
630 memif_create (memif_conn_handle_t *c, memif_conn_args_t *args,
631               memif_connection_update_t *on_connect,
632               memif_connection_update_t *on_disconnect,
633               memif_on_interrupt_t *on_interrupt, void *private_ctx)
634 {
635   int err, index = 0;
636   memif_connection_t *conn = (memif_connection_t *) * c;
637   memif_socket_t *ms = (memif_socket_t *) args->socket;
638
639   if (conn != NULL)
640     {
641       DBG ("This handle already points to existing memif.");
642       return MEMIF_ERR_CONN;
643     }
644
645   if (ms == NULL)
646     {
647       DBG ("Missing memif socket");
648       return MEMIF_ERR_INVAL_ARG;
649     }
650
651   conn = (memif_connection_t *) ms->args.alloc (sizeof (*conn));
652   if (conn == NULL)
653     {
654       err = MEMIF_ERR_NOMEM;
655       goto error;
656     }
657   memset (conn, 0, sizeof (memif_connection_t));
658
659   conn->args.interface_id = args->interface_id;
660
661   if (args->log2_ring_size == 0)
662     args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
663   else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
664     {
665       err = MEMIF_ERR_MAX_RING;
666       goto error;
667     }
668   if (args->buffer_size == 0)
669     args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
670   if (args->num_s2m_rings == 0)
671     args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
672   if (args->num_m2s_rings == 0)
673     args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
674
675   conn->args.num_s2m_rings = args->num_s2m_rings;
676   conn->args.num_m2s_rings = args->num_m2s_rings;
677   conn->args.buffer_size = args->buffer_size;
678   conn->args.log2_ring_size = args->log2_ring_size;
679   conn->args.is_master = args->is_master;
680   conn->args.mode = args->mode;
681   conn->args.socket = args->socket;
682   conn->regions = NULL;
683   conn->tx_queues = NULL;
684   conn->rx_queues = NULL;
685   conn->control_channel = NULL;
686   conn->on_connect = on_connect;
687   conn->on_disconnect = on_disconnect;
688   conn->on_interrupt = on_interrupt;
689   conn->private_ctx = private_ctx;
690   memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
691
692   uint8_t l = sizeof (conn->args.interface_name);
693   strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
694            l);
695
696   if ((l = strlen ((char *) args->secret)) > 0)
697     strlcpy ((char *) conn->args.secret, (char *) args->secret,
698              sizeof (conn->args.secret));
699
700   if (args->is_master)
701     TAILQ_INSERT_TAIL (&ms->master_interfaces, conn, next);
702   else
703     TAILQ_INSERT_TAIL (&ms->slave_interfaces, conn, next);
704
705   err = memif_request_connection (conn);
706   if (err != MEMIF_ERR_SUCCESS && err != MEMIF_ERR_CONNREFUSED)
707     {
708       if (args->is_master)
709         TAILQ_REMOVE (&ms->master_interfaces, conn, next);
710       else
711         TAILQ_REMOVE (&ms->slave_interfaces, conn, next);
712       goto error;
713     }
714
715   *c = conn;
716
717   return 0;
718
719 error:
720   if (conn != NULL)
721     ms->args.free (conn);
722   *c = conn = NULL;
723   return err;
724 }
725
726 int
727 memif_request_connection (memif_conn_handle_t c)
728 {
729   memif_connection_t *conn = (memif_connection_t *) c;
730   memif_socket_t *ms;
731   int err = MEMIF_ERR_SUCCESS;
732   int sockfd = -1;
733   struct sockaddr_un un = { 0 };
734   struct stat file_stat;
735   int on = 1;
736   memif_control_channel_t *cc = NULL;
737   memif_fd_event_t fde;
738   memif_fd_event_data_t *fdata = NULL;
739   void *ctx;
740
741   if (conn == NULL)
742     return MEMIF_ERR_NOCONN;
743
744   ms = (memif_socket_t *) conn->args.socket;
745
746   /* if control channel is assigned, the interface is either connected or
747    * connecting */
748   if (conn->control_channel != NULL)
749     return MEMIF_ERR_ALRCONN;
750   /* if interface is master and the socket is already listener we are done */
751   if (conn->args.is_master && (ms->listener_fd != -1))
752     return MEMIF_ERR_SUCCESS;
753
754   sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
755   if (sockfd < 0)
756     {
757       err = memif_syscall_error_handler (errno);
758       goto error;
759     }
760
761   un.sun_family = AF_UNIX;
762
763   /* use memcpy to support abstract socket
764    * ms->args.path is already a valid socket path
765    */
766   memcpy (un.sun_path, ms->args.path, sizeof (un.sun_path) - 1);
767
768   /* allocate fd event data */
769   fdata = ms->args.alloc (sizeof (*fdata));
770   if (fdata == NULL)
771     {
772       err = MEMIF_ERR_NOMEM;
773       goto error;
774     }
775
776   if (conn->args.is_master != 0)
777     {
778       /* Configure socket optins */
779       if (setsockopt (sockfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
780         {
781           err = memif_syscall_error_handler (errno);
782           goto error;
783         }
784       if (bind (sockfd, (struct sockaddr *) &un, sizeof (un)) < 0)
785         {
786           err = memif_syscall_error_handler (errno);
787           goto error;
788         }
789       if (listen (sockfd, 1) < 0)
790         {
791           err = memif_syscall_error_handler (errno);
792           goto error;
793         }
794       if (ms->args.path[0] != '\0')
795         {
796           /* Verify that the socket was created */
797           if (stat ((char *) ms->args.path, &file_stat) < 0)
798             {
799               err = memif_syscall_error_handler (errno);
800               goto error;
801             }
802         }
803
804       /* assign listener fd */
805       ms->listener_fd = sockfd;
806
807       fdata->event_handler = memif_listener_handler;
808       fdata->private_ctx = ms;
809     }
810   else
811     {
812       cc = ms->args.alloc (sizeof (*cc));
813       if (cc == NULL)
814         {
815           err = MEMIF_ERR_NOMEM;
816           goto error;
817         }
818       if (connect (sockfd, (struct sockaddr *) &un,
819                    sizeof (struct sockaddr_un)) != 0)
820         {
821           err = MEMIF_ERR_CONNREFUSED;
822           goto error;
823         }
824
825       /* Create control channel */
826       cc->fd = sockfd;
827       cc->sock = ms;
828       cc->conn = conn;
829       TAILQ_INIT (&cc->msg_queue);
830
831       /* assign control channel to endpoint */
832       conn->control_channel = cc;
833
834       fdata->event_handler = memif_control_channel_handler;
835       fdata->private_ctx = cc;
836     }
837
838   /* if event polling is done internally, send memif socket as context */
839   ctx = ms->epfd != -1 ? ms : ms->private_ctx;
840   /* send fd to epoll */
841   fde.fd = sockfd;
842   fde.type = MEMIF_FD_EVENT_READ;
843   fde.private_ctx = fdata;
844   ms->args.on_control_fd_update (fde, ctx);
845
846   return err;
847
848 error:
849   if (sockfd > 0)
850     close (sockfd);
851   sockfd = -1;
852   if (fdata != NULL)
853     ms->args.free (fdata);
854   fdata = NULL;
855   if (cc != NULL)
856     ms->args.free (cc);
857   conn->control_channel = cc = NULL;
858   return err;
859 }
860
861 int
862 memif_control_fd_handler (void *ptr, memif_fd_event_type_t events)
863 {
864   memif_fd_event_data_t *fdata = (memif_fd_event_data_t *) ptr;
865
866   if (fdata == NULL)
867     return MEMIF_ERR_INVAL_ARG;
868
869   return fdata->event_handler (events, fdata->private_ctx);
870 }
871
872 int
873 memif_interrupt_handler (memif_fd_event_type_t type, void *private_ctx)
874 {
875   memif_interrupt_t *idata = (memif_interrupt_t *) private_ctx;
876
877   if (idata == NULL)
878     return MEMIF_ERR_INVAL_ARG;
879
880   return idata->c->on_interrupt (idata->c, idata->c->private_ctx, idata->qid);
881 }
882
883 int
884 memif_poll_event (memif_socket_handle_t sock, int timeout)
885 {
886   memif_socket_t *ms = (memif_socket_t *) sock;
887   struct epoll_event evt;
888   int en = 0, err = MEMIF_ERR_SUCCESS;  /* 0 */
889   memif_fd_event_type_t events = 0;
890   uint64_t counter = 0;
891   ssize_t r = 0;
892   sigset_t sigset;
893
894   if (ms == NULL)
895     return MEMIF_ERR_INVAL_ARG;
896
897   memset (&evt, 0, sizeof (evt));
898   evt.events = EPOLLIN | EPOLLOUT;
899   sigemptyset (&sigset);
900   en = epoll_pwait (ms->epfd, &evt, 1, timeout, &sigset);
901   if (en < 0)
902     {
903       err = errno;
904       DBG ("epoll_pwait: %s", strerror (err));
905       return memif_syscall_error_handler (err);
906     }
907   if (en > 0)
908     {
909       if (evt.events & EPOLLIN)
910         events |= MEMIF_FD_EVENT_READ;
911       if (evt.events & EPOLLOUT)
912         events |= MEMIF_FD_EVENT_WRITE;
913       if (evt.events & EPOLLERR)
914         events |= MEMIF_FD_EVENT_ERROR;
915       return memif_control_fd_handler (evt.data.ptr, events);
916     }
917   return MEMIF_ERR_SUCCESS;
918 }
919
920 int
921 memif_cancel_poll_event (memif_socket_handle_t sock)
922 {
923   memif_socket_t *ms = (memif_socket_t *) sock;
924   uint64_t counter = 1;
925   ssize_t w = 0;
926
927   if (ms->poll_cancel_fd == -1)
928     return MEMIF_ERR_INVAL_ARG;
929   w = write (ms->poll_cancel_fd, &counter, sizeof (counter));
930   if (w < sizeof (counter))
931     return MEMIF_ERR_INT_WRITE;
932
933   return MEMIF_ERR_SUCCESS;
934 }
935
936 void
937 memif_close_queues (memif_socket_t *ms, memif_queue_t *queues, int nqueues)
938 {
939   memif_fd_event_t fde;
940   memif_queue_t *mq;
941   void *ctx;
942
943   int i;
944   for (i = 0; i < nqueues; i++)
945     {
946       mq = &queues[i];
947       if (mq != NULL)
948         {
949           if (mq->int_fd > 0)
950             {
951               /* Stop listening for events */
952               fde.fd = mq->int_fd;
953               fde.type = MEMIF_FD_EVENT_DEL;
954               ctx = ms->epfd != -1 ? ms : ms->private_ctx;
955               ms->args.on_control_fd_update (fde, ctx);
956               close (mq->int_fd);
957             }
958           mq->int_fd = -1;
959         }
960     }
961 }
962
963 /* send disconnect msg and close interface */
964 int
965 memif_disconnect_internal (memif_connection_t * c)
966 {
967   int err = MEMIF_ERR_SUCCESS, i;       /* 0 */
968   memif_queue_t *mq;
969   memif_socket_t *ms = (memif_socket_t *) c->args.socket;
970   memif_fd_event_t fde;
971   void *ctx;
972
973   c->on_disconnect ((void *) c, c->private_ctx);
974
975   /* Delete control channel */
976   if (c->control_channel != NULL)
977     memif_delete_control_channel (c->control_channel);
978
979   if (c->tx_queues != NULL)
980     {
981       memif_close_queues (ms, c->tx_queues, c->tx_queues_num);
982       ms->args.free (c->tx_queues);
983       c->tx_queues = NULL;
984     }
985   c->tx_queues_num = 0;
986
987   if (c->rx_queues != NULL)
988     {
989       memif_close_queues (ms, c->rx_queues, c->rx_queues_num);
990       ms->args.free (c->rx_queues);
991       c->rx_queues = NULL;
992     }
993   c->rx_queues_num = 0;
994
995   /* TODO: Slave reuse regions */
996
997   for (i = 0; i < c->regions_num; i++)
998     {
999       if (&c->regions[i] == NULL)
1000         continue;
1001       if (c->regions[i].is_external != 0)
1002         {
1003           ms->del_external_region (c->regions[i].addr,
1004                                    c->regions[i].region_size, c->regions[i].fd,
1005                                    c->private_ctx);
1006         }
1007       else
1008         {
1009           if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1010             return memif_syscall_error_handler (errno);
1011           if (c->regions[i].fd > 0)
1012             close (c->regions[i].fd);
1013           c->regions[i].fd = -1;
1014         }
1015     }
1016   ms->args.free (c->regions);
1017   c->regions = NULL;
1018   c->regions_num = 0;
1019
1020   memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1021
1022   return err;
1023 }
1024
1025 const char *
1026 memif_get_socket_filename (memif_socket_handle_t sock)
1027 {
1028   memif_socket_t *ms = (memif_socket_t *) sock;
1029
1030   if (ms == NULL)
1031     return NULL;
1032
1033   return (char *) ms->args.path;
1034 }
1035
1036 int
1037 memif_delete_socket (memif_socket_handle_t * sock)
1038 {
1039   memif_socket_t *ms = (memif_socket_t *) * sock;
1040   memif_fd_event_t fde;
1041   void *ctx;
1042
1043   /* check if socket is in use */
1044   if (ms == NULL || !TAILQ_EMPTY (&ms->master_interfaces) ||
1045       !TAILQ_EMPTY (&ms->slave_interfaces))
1046     return MEMIF_ERR_INVAL_ARG;
1047
1048   if (ms->listener_fd > 0)
1049     {
1050       fde.fd = ms->listener_fd;
1051       fde.type = MEMIF_FD_EVENT_DEL;
1052       ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1053       ms->args.on_control_fd_update (fde, ctx);
1054     }
1055   ms->listener_fd = -1;
1056
1057   if (ms->poll_cancel_fd > 0)
1058     {
1059       fde.fd = ms->poll_cancel_fd;
1060       fde.type = MEMIF_FD_EVENT_DEL;
1061       ctx = ms->epfd != -1 ? ms : ms->private_ctx;
1062       ms->args.on_control_fd_update (fde, ctx);
1063     }
1064   ms->poll_cancel_fd = -1;
1065
1066   if (ms->epfd > 0)
1067     close (ms->epfd);
1068   ms->epfd = -1;
1069
1070   ms->args.free (ms);
1071   *sock = ms = NULL;
1072
1073   return MEMIF_ERR_SUCCESS;
1074 }
1075
1076 int
1077 memif_delete (memif_conn_handle_t * conn)
1078 {
1079   memif_connection_t *c = (memif_connection_t *) * conn;
1080   memif_socket_t *ms;
1081   int err = MEMIF_ERR_SUCCESS;
1082
1083   if (c == NULL)
1084     {
1085       DBG ("no connection");
1086       return MEMIF_ERR_NOCONN;
1087     }
1088
1089   err = memif_disconnect_internal (c);
1090
1091   ms = (memif_socket_t *) c->args.socket;
1092
1093   if (c->args.is_master)
1094     TAILQ_REMOVE (&ms->master_interfaces, c, next);
1095   else
1096     TAILQ_REMOVE (&ms->slave_interfaces, c, next);
1097   /* TODO: don't listen with empty interface queue */
1098
1099   ms->args.free (c);
1100   c = NULL;
1101
1102   *conn = c;
1103   return err;
1104 }
1105
1106 int
1107 memif_connect1 (memif_connection_t * c)
1108 {
1109   memif_socket_t *ms;
1110   memif_region_t *mr;
1111   memif_queue_t *mq;
1112   int i;
1113
1114   if (c == NULL)
1115     return MEMIF_ERR_INVAL_ARG;
1116
1117   ms = (memif_socket_t *) c->args.socket;
1118
1119   for (i = 0; i < c->regions_num; i++)
1120     {
1121       mr = &c->regions[i];
1122       if (mr != NULL)
1123         {
1124           if (!mr->addr)
1125             {
1126               if (mr->is_external)
1127                 {
1128                   if (ms->get_external_region_addr == NULL)
1129                     return MEMIF_ERR_INVAL_ARG;
1130                   mr->addr = ms->get_external_region_addr (
1131                     mr->region_size, mr->fd, c->private_ctx);
1132                 }
1133               else
1134                 {
1135                   if (mr->fd < 0)
1136                     return MEMIF_ERR_NO_SHMFD;
1137
1138                   if ((mr->addr =
1139                          mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1140                                MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
1141                     {
1142                       return memif_syscall_error_handler (errno);
1143                     }
1144                 }
1145             }
1146         }
1147     }
1148
1149   for (i = 0; i < c->rx_queues_num; i++)
1150     {
1151       mq = &c->rx_queues[i];
1152       if (mq != NULL)
1153         {
1154           mq->ring = c->regions[mq->region].addr + mq->offset;
1155           if (mq->ring->cookie != MEMIF_COOKIE)
1156             {
1157               DBG ("wrong cookie on rx ring %u", i);
1158               return MEMIF_ERR_COOKIE;
1159             }
1160           mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
1161         }
1162     }
1163
1164   for (i = 0; i < c->tx_queues_num; i++)
1165     {
1166       mq = &c->tx_queues[i];
1167       if (mq != NULL)
1168         {
1169           mq->ring = c->regions[mq->region].addr + mq->offset;
1170           if (mq->ring->cookie != MEMIF_COOKIE)
1171             {
1172               DBG ("wrong cookie on tx ring %u", i);
1173               return MEMIF_ERR_COOKIE;
1174             }
1175           mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
1176         }
1177     }
1178
1179   return 0;
1180 }
1181
1182 static inline int
1183 memif_add_region (memif_connection_t *conn, uint8_t has_buffers)
1184 {
1185   memif_region_t *r;
1186   memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
1187
1188   r = ms->args.realloc (conn->regions,
1189                         sizeof (memif_region_t) * ++conn->regions_num);
1190   if (r == NULL)
1191     return MEMIF_ERR_NOMEM;
1192
1193   conn->regions = r;
1194   r = &conn->regions[conn->regions_num - 1];
1195   memset (r, 0, sizeof (memif_region_t));
1196
1197   if (has_buffers != 0)
1198     {
1199       r->buffer_offset = 0;
1200     }
1201   else
1202     {
1203       r->buffer_offset =
1204         (conn->run_args.num_s2m_rings +
1205          conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1206                                           sizeof (memif_desc_t) *
1207                                           (1 << conn->
1208                                            run_args.log2_ring_size));
1209     }
1210
1211   r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
1212     conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1213     (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1214
1215   if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
1216     return memif_syscall_error_handler (errno);
1217
1218   if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1219     return memif_syscall_error_handler (errno);
1220
1221   if ((ftruncate (r->fd, r->region_size)) == -1)
1222     return memif_syscall_error_handler (errno);
1223
1224   if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1225                        MAP_SHARED, r->fd, 0)) == MAP_FAILED)
1226     return memif_syscall_error_handler (errno);
1227
1228   return MEMIF_ERR_SUCCESS;
1229 }
1230
1231 static inline int
1232 memif_init_queues (memif_connection_t *conn)
1233 {
1234   int i, j;
1235   memif_ring_t *ring;
1236   memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
1237
1238   for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1239     {
1240       ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1241       DBG ("RING: %p I: %d", ring, i);
1242       ring->head = ring->tail = 0;
1243       ring->cookie = MEMIF_COOKIE;
1244       ring->flags = 0;
1245       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1246         {
1247           uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
1248           ring->desc[j].region = 1;
1249           ring->desc[j].offset =
1250             conn->regions[1].buffer_offset +
1251             (uint32_t) (slot * conn->run_args.buffer_size);
1252           ring->desc[j].length = conn->run_args.buffer_size;
1253         }
1254     }
1255   for (i = 0; i < conn->run_args.num_m2s_rings; i++)
1256     {
1257       ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
1258       DBG ("RING: %p I: %d", ring, i);
1259       ring->head = ring->tail = 0;
1260       ring->cookie = MEMIF_COOKIE;
1261       ring->flags = 0;
1262       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1263         {
1264           uint16_t slot = (i + conn->run_args.num_s2m_rings) *
1265             (1 << conn->run_args.log2_ring_size) + j;
1266           ring->desc[j].region = 1;
1267           ring->desc[j].offset =
1268             conn->regions[1].buffer_offset +
1269             (uint32_t) (slot * conn->run_args.buffer_size);
1270           ring->desc[j].length = conn->run_args.buffer_size;
1271         }
1272     }
1273   memif_queue_t *mq;
1274   mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1275                                          conn->run_args.num_s2m_rings);
1276   if (mq == NULL)
1277     return MEMIF_ERR_NOMEM;
1278
1279   int x;
1280
1281   for (x = 0; x < conn->run_args.num_s2m_rings; x++)
1282     {
1283       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1284         return memif_syscall_error_handler (errno);
1285
1286       mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
1287       DBG ("RING: %p I: %d", mq[x].ring, x);
1288       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1289       mq[x].region = 0;
1290       mq[x].offset =
1291         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1292       mq[x].last_head = mq[x].last_tail = 0;
1293       mq[x].next_buf = 0;
1294     }
1295   conn->tx_queues = mq;
1296   conn->tx_queues_num = conn->run_args.num_s2m_rings;
1297
1298   mq = (memif_queue_t *) ms->args.alloc (sizeof (memif_queue_t) *
1299                                          conn->run_args.num_m2s_rings);
1300   if (mq == NULL)
1301     return MEMIF_ERR_NOMEM;
1302
1303   for (x = 0; x < conn->run_args.num_m2s_rings; x++)
1304     {
1305       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1306         return memif_syscall_error_handler (errno);
1307
1308       mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
1309       DBG ("RING: %p I: %d", mq[x].ring, x);
1310       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1311       mq[x].region = 0;
1312       mq[x].offset =
1313         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1314       mq[x].last_head = mq[x].last_tail = 0;
1315       mq[x].next_buf = 0;
1316     }
1317   conn->rx_queues = mq;
1318   conn->rx_queues_num = conn->run_args.num_m2s_rings;
1319
1320   return MEMIF_ERR_SUCCESS;
1321 }
1322
1323 int
1324 memif_init_regions_and_queues (memif_connection_t * conn)
1325 {
1326   memif_region_t *r;
1327   memif_socket_t *ms = (memif_socket_t *) conn->args.socket;
1328
1329   /* region 0. rings */
1330   memif_add_region (conn, /* has_buffers */ 0);
1331
1332   /* region 1. buffers */
1333   if (ms->add_external_region)
1334     {
1335       r = (memif_region_t *) ms->args.realloc (
1336         conn->regions, sizeof (memif_region_t) * ++conn->regions_num);
1337       if (r == NULL)
1338         return MEMIF_ERR_NOMEM;
1339       conn->regions = r;
1340
1341       conn->regions[1].region_size =
1342         conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1343         (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1344       conn->regions[1].buffer_offset = 0;
1345       ms->add_external_region (&conn->regions[1].addr,
1346                                conn->regions[1].region_size,
1347                                &conn->regions[1].fd, conn->private_ctx);
1348       conn->regions[1].is_external = 1;
1349     }
1350   else
1351     {
1352       memif_add_region (conn, 1);
1353     }
1354
1355   memif_init_queues (conn);
1356
1357   return 0;
1358 }
1359
1360 int
1361 memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
1362                             memif_buffer_t *buf)
1363 {
1364   memif_connection_t *c = (memif_connection_t *) conn;
1365   if (EXPECT_FALSE (c == NULL))
1366     return MEMIF_ERR_NOCONN;
1367   if (EXPECT_FALSE (qid >= c->tx_queues_num))
1368     return MEMIF_ERR_QID;
1369   if (EXPECT_FALSE (buf == NULL))
1370     return MEMIF_ERR_INVAL_ARG;
1371
1372   uint16_t ring_size, ns;
1373   memif_queue_t *mq = &c->tx_queues[qid];
1374   memif_ring_t *ring = mq->ring;
1375
1376   ring_size = (1 << mq->log2_ring_size);
1377   if (c->args.is_master)
1378     ns = ring->head - mq->next_buf;
1379   else
1380     ns = ring_size - mq->next_buf + ring->tail;
1381
1382   if ((mq->next_buf - buf->desc_index) > ns)
1383     return MEMIF_ERR_INVAL_ARG;
1384
1385   mq->next_buf = buf->desc_index;
1386
1387   return MEMIF_ERR_SUCCESS;
1388 }
1389
1390 static void
1391 memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
1392                                   memif_buffer_t *buf, uint16_t slot)
1393 {
1394   uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
1395   uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
1396   memif_desc_t *from_d, *to_d, tmp_d;
1397
1398   /* Get the descriptors */
1399   from_d = &from_q->ring->desc[buf->desc_index & from_mask];
1400   to_d = &to_q->ring->desc[slot & to_mask];
1401
1402   /* Swap descriptors */
1403   tmp_d = *from_d;
1404   *from_d = *to_d;
1405   *to_d = tmp_d;
1406
1407   /* Update descriptor index and queue for clients buffer */
1408   buf->desc_index = slot;
1409   buf->queue = to_q;
1410 }
1411
1412 int
1413 memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
1414                       memif_buffer_t *buf_b)
1415 {
1416   memif_connection_t *c = (memif_connection_t *) conn;
1417   if (EXPECT_FALSE (c == NULL))
1418     return MEMIF_ERR_NOCONN;
1419   if (EXPECT_FALSE (c->args.is_master))
1420     return MEMIF_ERR_INVAL_ARG;
1421   if ((buf_a == NULL) || (buf_b == NULL))
1422     return MEMIF_ERR_INVAL_ARG;
1423
1424   int err;
1425   /* store buf_a information */
1426   uint16_t index_a = buf_a->desc_index;
1427   memif_queue_t *mq_a = buf_a->queue;
1428
1429   /* swap buffers, buf_a was updated with new desc_index and queue */
1430   memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
1431                                     (memif_queue_t *) buf_b->queue, buf_a,
1432                                     buf_b->desc_index);
1433
1434   /* update buf_b desc_index and queue */
1435   buf_b->desc_index = index_a;
1436   buf_b->queue = mq_a;
1437
1438   return MEMIF_ERR_SUCCESS;
1439 }
1440
1441 int
1442 memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
1443                      memif_buffer_t * bufs, uint16_t count,
1444                      uint16_t * count_out)
1445 {
1446   memif_connection_t *c = (memif_connection_t *) conn;
1447   if (EXPECT_FALSE (c == NULL))
1448     return MEMIF_ERR_NOCONN;
1449   if (EXPECT_FALSE (c->control_channel == NULL))
1450     return MEMIF_ERR_DISCONNECTED;
1451   if (EXPECT_FALSE (qid >= c->tx_queues_num))
1452     return MEMIF_ERR_QID;
1453   if (EXPECT_FALSE (!count_out))
1454     return MEMIF_ERR_INVAL_ARG;
1455   if (EXPECT_FALSE (c->args.is_master))
1456     return MEMIF_ERR_INVAL_ARG;
1457
1458   memif_queue_t *mq = &c->tx_queues[qid];
1459   memif_ring_t *ring = mq->ring;
1460   memif_buffer_t *b0;
1461   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1462   uint16_t ring_size;
1463   uint16_t ns;
1464   memif_queue_t *bmq;
1465   int err = MEMIF_ERR_SUCCESS;  /* 0 */
1466   *count_out = 0;
1467
1468   ring_size = (1 << mq->log2_ring_size);
1469
1470   /* can only be called by slave */
1471   ns = ring_size - mq->next_buf + ring->tail;
1472
1473   b0 = bufs;
1474
1475   while (count && ns)
1476     {
1477       /* Swaps the descriptors, updates next_buf pointer and updates client
1478        * memif buffer */
1479
1480       memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
1481                                         mq->next_buf);
1482
1483       mq->next_buf++; /* mark the buffer as allocated */
1484       count--;
1485       ns--;
1486       b0++;
1487       *count_out += 1;
1488     }
1489
1490   DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1491        mq->next_buf);
1492
1493   if (count)
1494     {
1495       DBG ("ring buffer full! qid: %u", qid);
1496       err = MEMIF_ERR_NOBUF_RING;
1497     }
1498
1499   return err;
1500 }
1501
1502 int
1503 memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
1504                     memif_buffer_t * bufs, uint16_t count,
1505                     uint16_t * count_out, uint16_t size)
1506 {
1507   memif_connection_t *c = (memif_connection_t *) conn;
1508   if (EXPECT_FALSE (c == NULL))
1509     return MEMIF_ERR_NOCONN;
1510   if (EXPECT_FALSE (c->control_channel == NULL))
1511     return MEMIF_ERR_DISCONNECTED;
1512   uint8_t num =
1513     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1514     run_args.num_s2m_rings;
1515   if (EXPECT_FALSE (qid >= num))
1516     return MEMIF_ERR_QID;
1517   if (EXPECT_FALSE (!count_out))
1518     return MEMIF_ERR_INVAL_ARG;
1519
1520   memif_socket_t *ms = (memif_socket_t *) c->args.socket;
1521   memif_queue_t *mq = &c->tx_queues[qid];
1522   memif_ring_t *ring = mq->ring;
1523   memif_buffer_t *b0;
1524   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1525   uint32_t offset_mask = c->run_args.buffer_size - 1;
1526   uint16_t ring_size;
1527   uint16_t ns;
1528   int err = MEMIF_ERR_SUCCESS;  /* 0 */
1529   uint16_t dst_left, src_left;
1530   uint16_t saved_count;
1531   uint16_t saved_next_buf;
1532   uint16_t slot;
1533   memif_buffer_t *saved_b;
1534   *count_out = 0;
1535
1536   ring_size = (1 << mq->log2_ring_size);
1537
1538   if (c->args.is_master)
1539     ns = ring->head - mq->next_buf;
1540   else
1541     ns = ring_size - mq->next_buf + ring->tail;
1542
1543   while (count && ns)
1544     {
1545       b0 = (bufs + *count_out);
1546
1547       saved_b = b0;
1548       saved_count = count;
1549       saved_next_buf = mq->next_buf;
1550
1551       b0->desc_index = mq->next_buf;
1552       ring->desc[mq->next_buf & mask].flags = 0;
1553
1554       /* slave can produce buffer with original length */
1555       dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
1556                                        c->run_args.buffer_size;
1557       src_left = size;
1558
1559       while (src_left)
1560         {
1561           if (EXPECT_FALSE (dst_left == 0))
1562             {
1563               if (count && ns)
1564                 {
1565                   *count_out += 1;
1566                   mq->next_buf++;
1567                   ns--;
1568
1569                   ring->desc[b0->desc_index & mask].flags |=
1570                     MEMIF_DESC_FLAG_NEXT;
1571                   b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1572
1573                   b0 = (bufs + *count_out);
1574                   b0->desc_index = mq->next_buf;
1575                   dst_left = (c->args.is_master) ?
1576                                ring->desc[mq->next_buf & mask].length :
1577                                c->run_args.buffer_size;
1578                   ring->desc[mq->next_buf & mask].flags = 0;
1579                 }
1580               else
1581                 {
1582                   /* rollback allocated chain buffers */
1583                   memset (saved_b, 0, sizeof (memif_buffer_t)
1584                           * (saved_count - count + 1));
1585                   *count_out -= saved_count - count;
1586                   mq->next_buf = saved_next_buf;
1587                   goto no_ns;
1588                 }
1589             }
1590           b0->len = memif_min (dst_left, src_left);
1591
1592           /* slave resets buffer offset */
1593           if (c->args.is_master == 0)
1594             {
1595               memif_desc_t *d = &ring->desc[slot & mask];
1596               if (ms->get_external_buffer_offset)
1597                 d->offset = ms->get_external_buffer_offset (c->private_ctx);
1598               else
1599                 d->offset = d->offset - (d->offset & offset_mask);
1600             }
1601           b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
1602
1603           src_left -= b0->len;
1604           dst_left -= b0->len;
1605         }
1606
1607       *count_out += 1;
1608       mq->next_buf++;
1609       ns--;
1610       count--;
1611     }
1612
1613 no_ns:
1614
1615   DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1616        mq->next_buf);
1617
1618   if (count)
1619     {
1620       DBG ("ring buffer full! qid: %u", qid);
1621       err = MEMIF_ERR_NOBUF_RING;
1622     }
1623
1624   return err;
1625 }
1626
1627 int
1628 memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
1629                     uint16_t headroom)
1630 {
1631   memif_connection_t *c = (memif_connection_t *) conn;
1632   if (EXPECT_FALSE (c == NULL))
1633     return MEMIF_ERR_NOCONN;
1634   if (EXPECT_FALSE (c->control_channel == NULL))
1635     return MEMIF_ERR_DISCONNECTED;
1636   uint8_t num =
1637     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1638     run_args.num_m2s_rings;
1639   if (EXPECT_FALSE (qid >= num))
1640     return MEMIF_ERR_QID;
1641   memif_socket_t *ms = (memif_socket_t *) c->args.socket;
1642   memif_queue_t *mq = &c->rx_queues[qid];
1643   memif_ring_t *ring = mq->ring;
1644   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1645   uint32_t offset_mask = c->run_args.buffer_size - 1;
1646   uint16_t slot, counter = 0;
1647
1648   if (c->args.is_master)
1649     {
1650       MEMIF_MEMORY_BARRIER ();
1651       ring->tail =
1652         (ring->tail + count <=
1653          mq->last_head) ? ring->tail + count : mq->last_head;
1654       return MEMIF_ERR_SUCCESS;
1655     }
1656
1657   uint16_t head = ring->head;
1658   slot = head;
1659   uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
1660   count = (count < ns) ? count : ns;
1661
1662   memif_desc_t *d;
1663   while (counter < count)
1664     {
1665       d = &ring->desc[slot & mask];
1666       d->region = 1;
1667       d->length = c->run_args.buffer_size - headroom;
1668       if (ms->get_external_buffer_offset)
1669         d->offset = ms->get_external_buffer_offset (c->private_ctx);
1670       else
1671         d->offset = d->offset - (d->offset & offset_mask) + headroom;
1672       slot++;
1673       counter++;
1674     }
1675
1676   MEMIF_MEMORY_BARRIER ();
1677   ring->head = slot;
1678
1679   return MEMIF_ERR_SUCCESS;     /* 0 */
1680 }
1681
1682 int
1683 memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
1684                 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
1685 {
1686   memif_connection_t *c = (memif_connection_t *) conn;
1687   if (EXPECT_FALSE (c == NULL))
1688     return MEMIF_ERR_NOCONN;
1689   if (EXPECT_FALSE (c->control_channel == NULL))
1690     return MEMIF_ERR_DISCONNECTED;
1691   uint8_t num =
1692     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1693     run_args.num_s2m_rings;
1694   if (EXPECT_FALSE (qid >= num))
1695     return MEMIF_ERR_QID;
1696   if (EXPECT_FALSE (!tx))
1697     return MEMIF_ERR_INVAL_ARG;
1698
1699   memif_queue_t *mq = &c->tx_queues[qid];
1700   memif_ring_t *ring = mq->ring;
1701   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1702   uint32_t offset_mask = c->run_args.buffer_size - 1;
1703   memif_buffer_t *b0;
1704   memif_desc_t *d;
1705   int64_t data_offset;
1706   *tx = 0;
1707   int err = MEMIF_ERR_SUCCESS;
1708
1709   if (EXPECT_FALSE (count == 0))
1710     return MEMIF_ERR_SUCCESS;
1711
1712   uint16_t index;
1713   if (c->args.is_master)
1714     index = ring->tail;
1715   else
1716     index = ring->head;
1717
1718   while (count)
1719     {
1720       b0 = (bufs + *tx);
1721       /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
1722        */
1723       if ((b0->desc_index & mask) != (index & mask))
1724         {
1725           err = MEMIF_ERR_INVAL_ARG;
1726           goto done;
1727         }
1728       d = &ring->desc[b0->desc_index & mask];
1729       d->length = b0->len;
1730       if (!c->args.is_master)
1731         {
1732           // reset headroom
1733           d->offset = d->offset - (d->offset & offset_mask);
1734           // calculate offset from user data
1735           data_offset = b0->data - (d->offset + c->regions[d->region].addr);
1736           if (data_offset != 0)
1737             {
1738               /* verify data offset and buffer length */
1739               if ((data_offset < 0) ||
1740                   ((data_offset + b0->len) > c->run_args.buffer_size))
1741                 {
1742                   DBG ("slot: %d, data_offset: %d, length: %d",
1743                        b0->desc_index & mask, data_offset, b0->len);
1744                   err = MEMIF_ERR_INVAL_ARG;
1745                   goto done;
1746                 }
1747               d->offset += data_offset;
1748             }
1749         }
1750
1751 #ifdef MEMIF_DBG_SHM
1752       printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
1753       printf ("data: %p\n",
1754               memif_get_buffer (c, ring, b0->desc_index & mask));
1755       printf ("index: %u\n", b0->desc_index);
1756       print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
1757                    ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
1758 #endif /* MEMIF_DBG_SHM */
1759
1760       *tx += 1;
1761       count--;
1762       index++;
1763     }
1764
1765 done:
1766   MEMIF_MEMORY_BARRIER ();
1767   if (c->args.is_master)
1768     ring->tail = b0->desc_index + 1;
1769   else
1770     ring->head = b0->desc_index + 1;
1771
1772   if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
1773     {
1774       uint64_t a = 1;
1775       int r = write (mq->int_fd, &a, sizeof (a));
1776       if (r < 0)
1777         return MEMIF_ERR_INT_WRITE;
1778     }
1779
1780   return err;
1781 }
1782
1783 int
1784 memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
1785                 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
1786 {
1787   memif_connection_t *c = (memif_connection_t *) conn;
1788   if (EXPECT_FALSE (c == NULL))
1789     return MEMIF_ERR_NOCONN;
1790   if (EXPECT_FALSE (c->control_channel == NULL))
1791     return MEMIF_ERR_DISCONNECTED;
1792   uint8_t num =
1793     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1794     run_args.num_m2s_rings;
1795   if (EXPECT_FALSE (qid >= num))
1796     return MEMIF_ERR_QID;
1797   if (EXPECT_FALSE (!rx))
1798     return MEMIF_ERR_INVAL_ARG;
1799
1800   memif_queue_t *mq = &c->rx_queues[qid];
1801   memif_ring_t *ring = mq->ring;
1802   uint16_t cur_slot, last_slot;
1803   uint16_t ns;
1804   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1805   memif_buffer_t *b0;
1806   *rx = 0;
1807
1808   uint64_t b;
1809   ssize_t r;
1810
1811   cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
1812   last_slot = (c->args.is_master) ? ring->head : ring->tail;
1813   if (cur_slot == last_slot)
1814     {
1815       r = read (mq->int_fd, &b, sizeof (b));
1816       if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1817                         return memif_syscall_error_handler (errno);
1818
1819       return MEMIF_ERR_SUCCESS;
1820     }
1821
1822   ns = last_slot - cur_slot;
1823
1824   while (ns && count)
1825     {
1826       b0 = (bufs + *rx);
1827
1828       b0->desc_index = cur_slot;
1829       b0->data = memif_get_buffer (c, ring, cur_slot & mask);
1830       b0->len = ring->desc[cur_slot & mask].length;
1831       /* slave resets buffer length */
1832       if (c->args.is_master == 0)
1833         {
1834           ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
1835         }
1836
1837       if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
1838         {
1839           b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1840           ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
1841         }
1842
1843       b0->queue = mq;
1844 #ifdef MEMIF_DBG_SHM
1845       printf ("data: %p\n", b0->data);
1846       printf ("index: %u\n", b0->desc_index);
1847       printf ("queue: %p\n", b0->queue);
1848       print_bytes (b0->data, b0->len, DBG_RX_BUF);
1849 #endif /* MEMIF_DBG_SHM */
1850       ns--;
1851       *rx += 1;
1852
1853       count--;
1854       cur_slot++;
1855     }
1856
1857   if (c->args.is_master)
1858     mq->last_head = cur_slot;
1859   else
1860     mq->last_tail = cur_slot;
1861
1862   if (ns)
1863     {
1864       DBG ("not enough buffers!");
1865       return MEMIF_ERR_NOBUF;
1866     }
1867
1868   r = read (mq->int_fd, &b, sizeof (b));
1869   if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1870     return memif_syscall_error_handler (errno);
1871
1872   return MEMIF_ERR_SUCCESS;     /* 0 */
1873 }
1874
1875 int
1876 memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
1877                    char *buf, ssize_t buflen)
1878 {
1879   memif_connection_t *c = (memif_connection_t *) conn;
1880   memif_socket_t *ms;
1881   int err = MEMIF_ERR_SUCCESS, i;
1882   ssize_t l0 = 0, l1;
1883
1884   if (c == NULL)
1885     return MEMIF_ERR_NOCONN;
1886
1887   ms = (memif_socket_t *) c->args.socket;
1888
1889   l1 = strlen ((char *) c->args.interface_name);
1890   if (l0 + l1 < buflen)
1891     {
1892       md->if_name =
1893         (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
1894       l0 += l1 + 1;
1895     }
1896   else
1897     err = MEMIF_ERR_NOBUF_DET;
1898
1899   l1 = strlen ((char *) ms->args.app_name);
1900   if (l0 + l1 < buflen)
1901     {
1902       md->inst_name =
1903         (uint8_t *) strcpy (buf + l0, (char *) ms->args.app_name);
1904       l0 += l1 + 1;
1905     }
1906   else
1907     err = MEMIF_ERR_NOBUF_DET;
1908
1909   l1 = strlen ((char *) c->remote_if_name);
1910   if (l0 + l1 < buflen)
1911     {
1912       md->remote_if_name =
1913         (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
1914       l0 += l1 + 1;
1915     }
1916   else
1917     err = MEMIF_ERR_NOBUF_DET;
1918
1919   l1 = strlen ((char *) c->remote_name);
1920   if (l0 + l1 < buflen)
1921     {
1922       md->remote_inst_name =
1923         (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
1924       l0 += l1 + 1;
1925     }
1926   else
1927     err = MEMIF_ERR_NOBUF_DET;
1928
1929   md->id = c->args.interface_id;
1930
1931   if (strlen ((char *) c->args.secret) > 0)
1932     {
1933       l1 = strlen ((char *) c->args.secret);
1934       if (l0 + l1 < buflen)
1935         {
1936           md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
1937           l0 += l1 + 1;
1938         }
1939       else
1940         err = MEMIF_ERR_NOBUF_DET;
1941     }
1942
1943   md->role = (c->args.is_master) ? 0 : 1;
1944   md->mode = c->args.mode;
1945
1946   l1 = 108;
1947   if (l0 + l1 < buflen)
1948     {
1949       md->socket_path = (uint8_t *) memcpy (buf + l0, ms->args.path, 108);
1950       if (md->socket_path[0] == '\0')
1951         {
1952           md->socket_path[0] = '@';
1953         }
1954       l0 += l1;
1955     }
1956   else
1957     err = MEMIF_ERR_NOBUF_DET;
1958
1959   l1 = strlen ((char *) c->remote_disconnect_string);
1960   if (l0 + l1 < buflen)
1961     {
1962       md->error =
1963         (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
1964       l0 += l1 + 1;
1965     }
1966   else
1967     err = MEMIF_ERR_NOBUF_DET;
1968
1969   md->regions_num = c->regions_num;
1970   l1 = sizeof (memif_region_details_t) * md->regions_num;
1971   if (l0 + l1 <= buflen)
1972     {
1973       md->regions = (memif_region_details_t *) (buf + l0);
1974       for (i = 0; i < md->regions_num; i++)
1975         {
1976           md->regions[i].index = i;
1977           md->regions[i].addr = c->regions[i].addr;
1978           md->regions[i].size = c->regions[i].region_size;
1979           md->regions[i].fd = c->regions[i].fd;
1980           md->regions[i].is_external = c->regions[i].is_external;
1981         }
1982       l0 += l1;
1983     }
1984   else
1985     err = MEMIF_ERR_NOBUF_DET;
1986
1987   md->rx_queues_num =
1988     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1989     run_args.num_m2s_rings;
1990
1991   l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
1992   if (l0 + l1 <= buflen)
1993     {
1994       md->rx_queues = (memif_queue_details_t *) (buf + l0);
1995       for (i = 0; i < md->rx_queues_num; i++)
1996         {
1997           md->rx_queues[i].region = c->rx_queues[i].region;
1998           md->rx_queues[i].qid = i;
1999           md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2000           md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2001           md->rx_queues[i].head = c->rx_queues[i].ring->head;
2002           md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2003           md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2004         }
2005       l0 += l1;
2006     }
2007   else
2008     err = MEMIF_ERR_NOBUF_DET;
2009
2010   md->tx_queues_num =
2011     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2012     run_args.num_s2m_rings;
2013
2014   l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2015   if (l0 + l1 <= buflen)
2016     {
2017       md->tx_queues = (memif_queue_details_t *) (buf + l0);
2018       for (i = 0; i < md->tx_queues_num; i++)
2019         {
2020           md->tx_queues[i].region = c->tx_queues[i].region;
2021           md->tx_queues[i].qid = i;
2022           md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2023           md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2024           md->tx_queues[i].head = c->tx_queues[i].ring->head;
2025           md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2026           md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2027         }
2028       l0 += l1;
2029     }
2030   else
2031     err = MEMIF_ERR_NOBUF_DET;
2032
2033   /* This is not completely true, clients should relay on
2034    * on_connect/on_disconnect callbacks */
2035   md->link_up_down = (c->control_channel != NULL) ? 1 : 0;
2036
2037   return err;                   /* 0 */
2038 }
2039
2040 int
2041 memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2042 {
2043   memif_connection_t *c = (memif_connection_t *) conn;
2044   uint8_t num;
2045
2046   *efd = -1;
2047   if (c == NULL)
2048     return MEMIF_ERR_NOCONN;
2049   if (c->control_channel == NULL)
2050     return MEMIF_ERR_DISCONNECTED;
2051
2052   num =
2053     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2054     run_args.num_m2s_rings;
2055   if (qid >= num)
2056     return MEMIF_ERR_QID;
2057
2058   *efd = c->rx_queues[qid].int_fd;
2059
2060   return MEMIF_ERR_SUCCESS;
2061 }