libmemif: reset memif buffer flags
[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       b0->flags = 0;
1567
1568       /* slave can produce buffer with original length */
1569       dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
1570                                        c->run_args.buffer_size;
1571       src_left = size;
1572
1573       while (src_left)
1574         {
1575           if (EXPECT_FALSE (dst_left == 0))
1576             {
1577               if (count && ns)
1578                 {
1579                   *count_out += 1;
1580                   mq->next_buf++;
1581                   ns--;
1582
1583                   ring->desc[b0->desc_index & mask].flags |=
1584                     MEMIF_DESC_FLAG_NEXT;
1585                   b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1586
1587                   b0 = (bufs + *count_out);
1588                   b0->desc_index = mq->next_buf;
1589                   dst_left = (c->args.is_master) ?
1590                                ring->desc[mq->next_buf & mask].length :
1591                                c->run_args.buffer_size;
1592                   ring->desc[mq->next_buf & mask].flags = 0;
1593                 }
1594               else
1595                 {
1596                   /* rollback allocated chain buffers */
1597                   memset (saved_b, 0, sizeof (memif_buffer_t)
1598                           * (saved_count - count + 1));
1599                   *count_out -= saved_count - count;
1600                   mq->next_buf = saved_next_buf;
1601                   goto no_ns;
1602                 }
1603             }
1604           b0->len = memif_min (dst_left, src_left);
1605
1606           /* slave resets buffer offset */
1607           if (c->args.is_master == 0)
1608             {
1609               memif_desc_t *d = &ring->desc[slot & mask];
1610               if (ms->get_external_buffer_offset)
1611                 d->offset = ms->get_external_buffer_offset (c->private_ctx);
1612               else
1613                 d->offset = d->offset - (d->offset & offset_mask);
1614             }
1615           b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
1616
1617           src_left -= b0->len;
1618           dst_left -= b0->len;
1619         }
1620
1621       *count_out += 1;
1622       mq->next_buf++;
1623       ns--;
1624       count--;
1625     }
1626
1627 no_ns:
1628
1629   DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
1630        mq->next_buf);
1631
1632   if (count)
1633     {
1634       DBG ("ring buffer full! qid: %u", qid);
1635       err = MEMIF_ERR_NOBUF_RING;
1636     }
1637
1638   return err;
1639 }
1640
1641 int
1642 memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
1643                     uint16_t headroom)
1644 {
1645   memif_connection_t *c = (memif_connection_t *) conn;
1646   if (EXPECT_FALSE (c == NULL))
1647     return MEMIF_ERR_NOCONN;
1648   if (EXPECT_FALSE (c->control_channel == NULL))
1649     return MEMIF_ERR_DISCONNECTED;
1650   uint8_t num =
1651     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1652     run_args.num_m2s_rings;
1653   if (EXPECT_FALSE (qid >= num))
1654     return MEMIF_ERR_QID;
1655   memif_socket_t *ms = (memif_socket_t *) c->args.socket;
1656   memif_queue_t *mq = &c->rx_queues[qid];
1657   memif_ring_t *ring = mq->ring;
1658   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1659   uint32_t offset_mask = c->run_args.buffer_size - 1;
1660   uint16_t slot, counter = 0;
1661
1662   if (c->args.is_master)
1663     {
1664       MEMIF_MEMORY_BARRIER ();
1665       ring->tail =
1666         (ring->tail + count <=
1667          mq->last_head) ? ring->tail + count : mq->last_head;
1668       return MEMIF_ERR_SUCCESS;
1669     }
1670
1671   uint16_t head = ring->head;
1672   slot = head;
1673   uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
1674   count = (count < ns) ? count : ns;
1675
1676   memif_desc_t *d;
1677   while (counter < count)
1678     {
1679       d = &ring->desc[slot & mask];
1680       d->region = 1;
1681       d->length = c->run_args.buffer_size - headroom;
1682       if (ms->get_external_buffer_offset)
1683         d->offset = ms->get_external_buffer_offset (c->private_ctx);
1684       else
1685         d->offset = d->offset - (d->offset & offset_mask) + headroom;
1686       slot++;
1687       counter++;
1688     }
1689
1690   MEMIF_MEMORY_BARRIER ();
1691   ring->head = slot;
1692
1693   return MEMIF_ERR_SUCCESS;     /* 0 */
1694 }
1695
1696 int
1697 memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
1698                 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
1699 {
1700   memif_connection_t *c = (memif_connection_t *) conn;
1701   if (EXPECT_FALSE (c == NULL))
1702     return MEMIF_ERR_NOCONN;
1703   if (EXPECT_FALSE (c->control_channel == NULL))
1704     return MEMIF_ERR_DISCONNECTED;
1705   uint8_t num =
1706     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1707     run_args.num_s2m_rings;
1708   if (EXPECT_FALSE (qid >= num))
1709     return MEMIF_ERR_QID;
1710   if (EXPECT_FALSE (!tx))
1711     return MEMIF_ERR_INVAL_ARG;
1712
1713   memif_queue_t *mq = &c->tx_queues[qid];
1714   memif_ring_t *ring = mq->ring;
1715   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1716   uint32_t offset_mask = c->run_args.buffer_size - 1;
1717   memif_buffer_t *b0;
1718   memif_desc_t *d;
1719   int64_t data_offset;
1720   *tx = 0;
1721   int err = MEMIF_ERR_SUCCESS;
1722
1723   if (EXPECT_FALSE (count == 0))
1724     return MEMIF_ERR_SUCCESS;
1725
1726   uint16_t index;
1727   if (c->args.is_master)
1728     index = ring->tail;
1729   else
1730     index = ring->head;
1731
1732   while (count)
1733     {
1734       b0 = (bufs + *tx);
1735       /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
1736        */
1737       if ((b0->desc_index & mask) != (index & mask))
1738         {
1739           err = MEMIF_ERR_INVAL_ARG;
1740           goto done;
1741         }
1742       d = &ring->desc[b0->desc_index & mask];
1743       d->length = b0->len;
1744       if (!c->args.is_master)
1745         {
1746           // reset headroom
1747           d->offset = d->offset - (d->offset & offset_mask);
1748           // calculate offset from user data
1749           data_offset = b0->data - (d->offset + c->regions[d->region].addr);
1750           if (data_offset != 0)
1751             {
1752               /* verify data offset and buffer length */
1753               if ((data_offset < 0) ||
1754                   ((data_offset + b0->len) > c->run_args.buffer_size))
1755                 {
1756                   DBG ("slot: %d, data_offset: %ld, length: %d",
1757                        b0->desc_index & mask, data_offset, b0->len);
1758                   err = MEMIF_ERR_INVAL_ARG;
1759                   goto done;
1760                 }
1761               d->offset += data_offset;
1762             }
1763         }
1764
1765 #ifdef MEMIF_DBG_SHM
1766       printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
1767       printf ("data: %p\n",
1768               memif_get_buffer (c, ring, b0->desc_index & mask));
1769       printf ("index: %u\n", b0->desc_index);
1770       print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
1771                    ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
1772 #endif /* MEMIF_DBG_SHM */
1773
1774       *tx += 1;
1775       count--;
1776       index++;
1777     }
1778
1779 done:
1780   MEMIF_MEMORY_BARRIER ();
1781   if (c->args.is_master)
1782     ring->tail = b0->desc_index + 1;
1783   else
1784     ring->head = b0->desc_index + 1;
1785
1786   if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
1787     {
1788       uint64_t a = 1;
1789       int r = write (mq->int_fd, &a, sizeof (a));
1790       if (r < 0)
1791         return MEMIF_ERR_INT_WRITE;
1792     }
1793
1794   return err;
1795 }
1796
1797 int
1798 memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
1799                 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
1800 {
1801   memif_connection_t *c = (memif_connection_t *) conn;
1802   if (EXPECT_FALSE (c == NULL))
1803     return MEMIF_ERR_NOCONN;
1804   if (EXPECT_FALSE (c->control_channel == NULL))
1805     return MEMIF_ERR_DISCONNECTED;
1806   uint8_t num =
1807     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1808     run_args.num_m2s_rings;
1809   if (EXPECT_FALSE (qid >= num))
1810     return MEMIF_ERR_QID;
1811   if (EXPECT_FALSE (!rx))
1812     return MEMIF_ERR_INVAL_ARG;
1813
1814   memif_queue_t *mq = &c->rx_queues[qid];
1815   memif_ring_t *ring = mq->ring;
1816   uint16_t cur_slot, last_slot;
1817   uint16_t ns;
1818   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1819   memif_buffer_t *b0;
1820   *rx = 0;
1821
1822   uint64_t b;
1823   ssize_t r;
1824
1825   cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
1826   last_slot = (c->args.is_master) ? ring->head : ring->tail;
1827   if (cur_slot == last_slot)
1828     {
1829       r = read (mq->int_fd, &b, sizeof (b));
1830       if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1831                         return memif_syscall_error_handler (errno);
1832
1833       return MEMIF_ERR_SUCCESS;
1834     }
1835
1836   ns = last_slot - cur_slot;
1837
1838   while (ns && count)
1839     {
1840       b0 = (bufs + *rx);
1841
1842       b0->desc_index = cur_slot;
1843       b0->data = memif_get_buffer (c, ring, cur_slot & mask);
1844       b0->len = ring->desc[cur_slot & mask].length;
1845       b0->flags = 0;
1846       /* slave resets buffer length */
1847       if (c->args.is_master == 0)
1848         {
1849           ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
1850         }
1851
1852       if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
1853         {
1854           b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1855           ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
1856         }
1857
1858       b0->queue = mq;
1859 #ifdef MEMIF_DBG_SHM
1860       printf ("data: %p\n", b0->data);
1861       printf ("index: %u\n", b0->desc_index);
1862       printf ("queue: %p\n", b0->queue);
1863       print_bytes (b0->data, b0->len, DBG_RX_BUF);
1864 #endif /* MEMIF_DBG_SHM */
1865       ns--;
1866       *rx += 1;
1867
1868       count--;
1869       cur_slot++;
1870     }
1871
1872   if (c->args.is_master)
1873     mq->last_head = cur_slot;
1874   else
1875     mq->last_tail = cur_slot;
1876
1877   if (ns)
1878     {
1879       DBG ("not enough buffers!");
1880       return MEMIF_ERR_NOBUF;
1881     }
1882
1883   r = read (mq->int_fd, &b, sizeof (b));
1884   if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1885     return memif_syscall_error_handler (errno);
1886
1887   return MEMIF_ERR_SUCCESS;     /* 0 */
1888 }
1889
1890 int
1891 memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
1892                    char *buf, ssize_t buflen)
1893 {
1894   memif_connection_t *c = (memif_connection_t *) conn;
1895   memif_socket_t *ms;
1896   int err = MEMIF_ERR_SUCCESS, i;
1897   ssize_t l0 = 0, l1;
1898
1899   if (c == NULL)
1900     return MEMIF_ERR_NOCONN;
1901
1902   ms = (memif_socket_t *) c->args.socket;
1903
1904   l1 = strlen ((char *) c->args.interface_name);
1905   if (l0 + l1 < buflen)
1906     {
1907       md->if_name =
1908         (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
1909       l0 += l1 + 1;
1910     }
1911   else
1912     err = MEMIF_ERR_NOBUF_DET;
1913
1914   l1 = strlen ((char *) ms->args.app_name);
1915   if (l0 + l1 < buflen)
1916     {
1917       md->inst_name =
1918         (uint8_t *) strcpy (buf + l0, (char *) ms->args.app_name);
1919       l0 += l1 + 1;
1920     }
1921   else
1922     err = MEMIF_ERR_NOBUF_DET;
1923
1924   l1 = strlen ((char *) c->remote_if_name);
1925   if (l0 + l1 < buflen)
1926     {
1927       md->remote_if_name =
1928         (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
1929       l0 += l1 + 1;
1930     }
1931   else
1932     err = MEMIF_ERR_NOBUF_DET;
1933
1934   l1 = strlen ((char *) c->remote_name);
1935   if (l0 + l1 < buflen)
1936     {
1937       md->remote_inst_name =
1938         (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
1939       l0 += l1 + 1;
1940     }
1941   else
1942     err = MEMIF_ERR_NOBUF_DET;
1943
1944   md->id = c->args.interface_id;
1945
1946   if (strlen ((char *) c->args.secret) > 0)
1947     {
1948       l1 = strlen ((char *) c->args.secret);
1949       if (l0 + l1 < buflen)
1950         {
1951           md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
1952           l0 += l1 + 1;
1953         }
1954       else
1955         err = MEMIF_ERR_NOBUF_DET;
1956     }
1957
1958   md->role = (c->args.is_master) ? 0 : 1;
1959   md->mode = c->args.mode;
1960
1961   l1 = 108;
1962   if (l0 + l1 < buflen)
1963     {
1964       md->socket_path = (uint8_t *) memcpy (buf + l0, ms->args.path, 108);
1965       l0 += l1;
1966     }
1967   else
1968     err = MEMIF_ERR_NOBUF_DET;
1969
1970   l1 = strlen ((char *) c->remote_disconnect_string);
1971   if (l0 + l1 < buflen)
1972     {
1973       md->error =
1974         (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
1975       l0 += l1 + 1;
1976     }
1977   else
1978     err = MEMIF_ERR_NOBUF_DET;
1979
1980   md->regions_num = c->regions_num;
1981   l1 = sizeof (memif_region_details_t) * md->regions_num;
1982   if (l0 + l1 <= buflen)
1983     {
1984       md->regions = (memif_region_details_t *) (buf + l0);
1985       for (i = 0; i < md->regions_num; i++)
1986         {
1987           md->regions[i].index = i;
1988           md->regions[i].addr = c->regions[i].addr;
1989           md->regions[i].size = c->regions[i].region_size;
1990           md->regions[i].fd = c->regions[i].fd;
1991           md->regions[i].is_external = c->regions[i].is_external;
1992         }
1993       l0 += l1;
1994     }
1995   else
1996     err = MEMIF_ERR_NOBUF_DET;
1997
1998   md->rx_queues_num =
1999     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2000     run_args.num_m2s_rings;
2001
2002   l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2003   if (l0 + l1 <= buflen)
2004     {
2005       md->rx_queues = (memif_queue_details_t *) (buf + l0);
2006       for (i = 0; i < md->rx_queues_num; i++)
2007         {
2008           md->rx_queues[i].region = c->rx_queues[i].region;
2009           md->rx_queues[i].qid = i;
2010           md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2011           md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2012           md->rx_queues[i].head = c->rx_queues[i].ring->head;
2013           md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2014           md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2015         }
2016       l0 += l1;
2017     }
2018   else
2019     err = MEMIF_ERR_NOBUF_DET;
2020
2021   md->tx_queues_num =
2022     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2023     run_args.num_s2m_rings;
2024
2025   l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2026   if (l0 + l1 <= buflen)
2027     {
2028       md->tx_queues = (memif_queue_details_t *) (buf + l0);
2029       for (i = 0; i < md->tx_queues_num; i++)
2030         {
2031           md->tx_queues[i].region = c->tx_queues[i].region;
2032           md->tx_queues[i].qid = i;
2033           md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2034           md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2035           md->tx_queues[i].head = c->tx_queues[i].ring->head;
2036           md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2037           md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2038         }
2039       l0 += l1;
2040     }
2041   else
2042     err = MEMIF_ERR_NOBUF_DET;
2043
2044   /* This is not completely true, clients should relay on
2045    * on_connect/on_disconnect callbacks */
2046   md->link_up_down = (c->control_channel != NULL) ? 1 : 0;
2047
2048   return err;                   /* 0 */
2049 }
2050
2051 int
2052 memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2053 {
2054   memif_connection_t *c = (memif_connection_t *) conn;
2055   uint8_t num;
2056
2057   *efd = -1;
2058   if (c == NULL)
2059     return MEMIF_ERR_NOCONN;
2060   if (c->control_channel == NULL)
2061     return MEMIF_ERR_DISCONNECTED;
2062
2063   num =
2064     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2065     run_args.num_m2s_rings;
2066   if (qid >= num)
2067     return MEMIF_ERR_QID;
2068
2069   *efd = c->rx_queues[qid].int_fd;
2070
2071   return MEMIF_ERR_SUCCESS;
2072 }