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