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