libmemif: fix insecure uses of strncpy
[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 libmemif_main_t libmemif_main;
69
70 static char memif_buf[MAX_ERRBUF_LEN];
71
72 const char *memif_errlist[ERRLIST_LEN] = {      /* MEMIF_ERR_SUCCESS */
73   "Success.",
74   /* MEMIF_ERR_SYSCALL */
75   "Unspecified syscall error (build with -DMEMIF_DBG or make debug).",
76   /* MEMIF_ERR_CONNREFUSED */
77   "Connection refused",
78   /* MEMIF_ERR_ACCES */
79   "Permission to resource denied.",
80   /* MEMIF_ERR_NO_FILE */
81   "Socket file does not exist",
82   /* MEMIF_ERR_FILE_LIMIT */
83   "System limit on total numer of open files reached.",
84   /* MEMIF_ERR_PROC_FILE_LIMIT */
85   "Per-process limit on total number of open files reached.",
86   /* MEMIF_ERR_ALREADY */
87   "Connection already requested.",
88   /* MEMIF_ERR_AGAIN */
89   "File descriptor refers to file other than socket, or operation would block.",
90   /* MEMIF_ERR_BAD_FD */
91   "Bad file descriptor.",
92   /* MEMIF_ERR_NOMEM */
93   "Out of memory.",
94   /* MEMIF_ERR_INVAL_ARG */
95   "Invalid argument.",
96   /* MEMIF_ERR_NOCONN */
97   "Memif connection handle does not point to existing connection",
98   /* MEMIF_ERR_CONN */
99   "Memif connection handle points to existing connection",
100   /* MEMIF_ERR_CB_FDUPDATE */
101   "Callback memif_control_fd_update_t returned error",
102   /* MEMIF_ERR_FILE_NOT_SOCK */
103   "File specified by socket filename exists and is not socket.",
104   /* MEMIF_ERR_NO_SHMFD */
105   "Missing shared memory file descriptor. (internal error)",
106   /* MEMIF_ERR_COOKIE */
107   "Invalid cookie on ring. (internal error)",
108   /* MEMIF_ERR_NOBUF_RING */
109   "Ring buffer full.",
110   /* MEMIF_ERR_NOBUF */
111   "Not enough memif buffers. There are unreceived data in shared memory.",
112   /* MEMIF_ERR_NOBUF_DET */
113   "Not enough space for memif details in supplied buffer. String data might be malformed.",
114   /* MEMIF_ERR_INT_WRITE */
115   "Send interrupt error.",
116   /* MEMIF_ERR_MFMSG */
117   "Malformed message received on control channel.",
118   /* MEMIF_ERR_QID */
119   "Invalid queue id",
120   /* MEMIF_ERR_PROTO */
121   "Incompatible memory interface protocol version.",
122   /* MEMIF_ERR_ID */
123   "Unmatched interface id.",
124   /* MEMIF_ERR_ACCSLAVE */
125   "Slave cannot accept connection request.",
126   /* MEMIF_ERR_ALRCONN */
127   "Interface is already connected.",
128   /* MEMIF_ERR_MODE */
129   "Mode mismatch.",
130   /* MEMIF_ERR_SECRET */
131   "Secret mismatch.",
132   /* MEMIF_ERR_NOSECRET */
133   "Secret required.",
134   /* MEMIF_ERR_MAXREG */
135   "Limit on total number of regions reached.",
136   /* MEMIF_ERR_MAXRING */
137   "Limit on total number of ring reached.",
138   /* MEMIF_ERR_NO_INTFD */
139   "Missing interrupt file descriptor. (internal error)",
140   /* MEMIF_ERR_DISCONNECT */
141   "Interface received disconnect request.",
142   /* MEMIF_ERR_DISCONNECTED */
143   "Interface is disconnected.",
144   /* MEMIF_ERR_UNKNOWN_MSG */
145   "Unknown message type received on control channel. (internal error)",
146   /* MEMIF_ERR_POLL_CANCEL */
147   "Memif event polling was canceled.",
148   /* MEMIF_ERR_MAX_RING */
149   "Maximum log2 ring size is 15",
150   /* MEMIF_ERR_PRIVHDR */
151   "Private headers not supported."
152 };
153
154 #define MEMIF_ERR_UNDEFINED "undefined error"
155
156 char *
157 memif_strerror (int err_code)
158 {
159   if (err_code >= ERRLIST_LEN)
160     {
161       strlcpy (memif_buf, MEMIF_ERR_UNDEFINED, sizeof (memif_buf));
162     }
163   else
164     {
165       strlcpy (memif_buf, memif_errlist[err_code], sizeof (memif_buf));
166     }
167   return memif_buf;
168 }
169
170 uint16_t
171 memif_get_version ()
172 {
173   return MEMIF_VERSION;
174 }
175
176 #define DBG_TX_BUF (0)
177 #define DBG_RX_BUF (1)
178
179 #ifdef MEMIF_DBG_SHM
180 static void
181 print_bytes (void *data, uint16_t len, uint8_t q)
182 {
183   if (q == DBG_TX_BUF)
184     printf ("\nTX:\n\t");
185   else
186     printf ("\nRX:\n\t");
187   int i;
188   for (i = 0; i < len; i++)
189     {
190       if (i % 8 == 0)
191         printf ("\n%d:\t", i);
192       printf ("%02X ", ((uint8_t *) (data))[i]);
193     }
194   printf ("\n\n");
195 }
196 #endif /* MEMIF_DBG_SHM */
197
198 int
199 memif_syscall_error_handler (int err_code)
200 {
201   DBG ("%s", strerror (err_code));
202
203   if (err_code == 0)
204     return MEMIF_ERR_SUCCESS;
205   if (err_code == EACCES)
206     return MEMIF_ERR_ACCES;
207   if (err_code == ENFILE)
208     return MEMIF_ERR_FILE_LIMIT;
209   if (err_code == EMFILE)
210     return MEMIF_ERR_PROC_FILE_LIMIT;
211   if (err_code == ENOMEM)
212     return MEMIF_ERR_NOMEM;
213 /* connection refused if master does not exist
214     this error would spam the user until master was created */
215 /*
216   if (err_code == ECONNREFUSED)
217     return MEMIF_ERR_SUCCESS;
218 */
219   if (err_code == ECONNREFUSED)
220     return MEMIF_ERR_CONNREFUSED;
221   if (err_code == EALREADY)
222     return MEMIF_ERR_ALREADY;
223   if (err_code == EAGAIN)
224     return MEMIF_ERR_AGAIN;
225   if (err_code == EBADF)
226     return MEMIF_ERR_BAD_FD;
227   if (err_code == ENOENT)
228     return MEMIF_ERR_NO_FILE;
229
230   /* other syscall errors */
231   return MEMIF_ERR_SYSCALL;
232 }
233
234 /* Always valid */
235 libmemif_main_t *
236 get_libmemif_main (memif_socket_t * ms)
237 {
238   if (ms != NULL && ms->lm != NULL)
239     return ms->lm;
240   return &libmemif_main;
241 }
242
243 static int
244 memif_add_epoll_fd (libmemif_main_t * lm, int fd, uint32_t events)
245 {
246   if (fd < 0)
247     {
248       DBG ("invalid fd %d", fd);
249       return -1;
250     }
251   struct epoll_event evt;
252   memset (&evt, 0, sizeof (evt));
253   evt.events = events;
254   evt.data.fd = fd;
255   if (epoll_ctl (lm->epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
256     {
257       DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
258       return -1;
259     }
260   DBG ("fd %d added to epoll", fd);
261   return 0;
262 }
263
264 static int
265 memif_mod_epoll_fd (libmemif_main_t * lm, int fd, uint32_t events)
266 {
267   if (fd < 0)
268     {
269       DBG ("invalid fd %d", fd);
270       return -1;
271     }
272   struct epoll_event evt;
273   memset (&evt, 0, sizeof (evt));
274   evt.events = events;
275   evt.data.fd = fd;
276   if (epoll_ctl (lm->epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
277     {
278       DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
279       return -1;
280     }
281   DBG ("fd %d modified on epoll", fd);
282   return 0;
283 }
284
285 static int
286 memif_del_epoll_fd (libmemif_main_t * lm, int fd)
287 {
288   if (fd < 0)
289     {
290       DBG ("invalid fd %d", fd);
291       return -1;
292     }
293   struct epoll_event evt;
294   memset (&evt, 0, sizeof (evt));
295   if (epoll_ctl (lm->epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
296     {
297       DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
298       return -1;
299     }
300   DBG ("fd %d removed from epoll", fd);
301   return 0;
302 }
303
304 int
305 memif_control_fd_update (int fd, uint8_t events, void *private_ctx)
306 {
307   libmemif_main_t *lm;
308
309   lm = (private_ctx == NULL) ? &libmemif_main : (libmemif_main_t *) private_ctx;
310
311   if (events & MEMIF_FD_EVENT_DEL)
312     return memif_del_epoll_fd (lm, fd);
313
314   uint32_t evt = 0;
315   if (events & MEMIF_FD_EVENT_READ)
316     evt |= EPOLLIN;
317   if (events & MEMIF_FD_EVENT_WRITE)
318     evt |= EPOLLOUT;
319
320   if (events & MEMIF_FD_EVENT_MOD)
321     return memif_mod_epoll_fd (lm, fd, evt);
322
323   return memif_add_epoll_fd (lm, fd, evt);
324 }
325
326 int
327 add_list_elt (libmemif_main_t * lm, memif_list_elt_t * e,
328               memif_list_elt_t ** list, uint16_t * len)
329 {
330   memif_list_elt_t *tmp;
331   int i;
332
333   for (i = 0; i < *len; i++)
334     {
335       if ((*list)[i].data_struct == NULL)
336         {
337           (*list)[i].key = e->key;
338           (*list)[i].data_struct = e->data_struct;
339           return i;
340         }
341     }
342
343   tmp = lm->realloc (*list, sizeof (memif_list_elt_t) * *len * 2);
344   if (tmp == NULL)
345     return -1;
346
347   for (i = *len; i < *len * 2; i++)
348     {
349       tmp[i].key = -1;
350       tmp[i].data_struct = NULL;
351     }
352
353   tmp[*len].key = e->key;
354   tmp[*len].data_struct = e->data_struct;
355   i = *len;
356   *len = *len * 2;
357   *list = tmp;
358
359   return i;
360 }
361
362 int
363 get_list_elt (memif_list_elt_t ** e, memif_list_elt_t * list, uint16_t len,
364               int key)
365 {
366   int i;
367   if (key == -1)
368     {
369       *e = NULL;
370       return -1;
371     }
372
373   for (i = 0; i < len; i++)
374     {
375       if (list[i].key == key)
376         {
377           *e = &list[i];
378           return 0;
379         }
380     }
381   *e = NULL;
382   return -1;
383 }
384
385 /* does not free memory, only marks element as free */
386 int
387 free_list_elt (memif_list_elt_t * list, uint16_t len, int key)
388 {
389   int i;
390   for (i = 0; i < len; i++)
391     {
392       if (list[i].key == key)
393         {
394           list[i].key = -1;
395           list[i].data_struct = NULL;
396           return 0;
397         }
398     }
399
400   return -1;
401 }
402
403 int
404 free_list_elt_ctx (memif_list_elt_t * list, uint16_t len,
405                    memif_connection_t * ctx)
406 {
407   int i;
408   for (i = 0; i < len; i++)
409     {
410       if (list[i].key == -1)
411         {
412           if (list[i].data_struct == ctx)
413             {
414               list[i].data_struct = NULL;
415               return 0;
416             }
417         }
418     }
419
420   return -1;
421 }
422
423 static void
424 memif_control_fd_update_register (libmemif_main_t * lm,
425                                   memif_control_fd_update_t * cb)
426 {
427   lm->control_fd_update = cb;
428 }
429
430 void
431 memif_register_external_region (memif_add_external_region_t * ar,
432                                 memif_get_external_region_addr_t * gr,
433                                 memif_del_external_region_t * dr,
434                                 memif_get_external_buffer_offset_t * go)
435 {
436   libmemif_main_t *lm = &libmemif_main;
437   lm->add_external_region = ar;
438   lm->get_external_region_addr = gr;
439   lm->del_external_region = dr;
440   lm->get_external_buffer_offset = go;
441 }
442
443 static void
444 memif_alloc_register (libmemif_main_t * lm, memif_alloc_t * ma)
445 {
446   lm->alloc = ma;
447 }
448
449 static void
450 memif_realloc_register (libmemif_main_t * lm, memif_realloc_t * mr)
451 {
452   lm->realloc = mr;
453 }
454
455 static void
456 memif_free_register (libmemif_main_t * lm, memif_free_t * mf)
457 {
458   lm->free = mf;
459 }
460
461 int
462 memif_set_connection_request_timer (struct itimerspec timer)
463 {
464   libmemif_main_t *lm = &libmemif_main;
465   int err = MEMIF_ERR_SUCCESS;
466
467   lm->arm = timer;
468
469   /* overwrite timer, if already armed */
470   if (lm->disconn_slaves != 0)
471     {
472       if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
473         {
474           err = memif_syscall_error_handler (errno);
475         }
476     }
477   return err;
478 }
479
480 int
481 memif_per_thread_set_connection_request_timer (memif_per_thread_main_handle_t
482                                                pt_main,
483                                                struct itimerspec timer)
484 {
485   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
486   int err = MEMIF_ERR_SUCCESS;
487
488   lm->arm = timer;
489
490   /* overwrite timer, if already armed */
491   if (lm->disconn_slaves != 0)
492     {
493       if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
494         {
495           err = memif_syscall_error_handler (errno);
496         }
497     }
498   return err;
499 }
500
501 int
502 memif_init (memif_control_fd_update_t * on_control_fd_update, char *app_name,
503             memif_alloc_t * memif_alloc, memif_realloc_t * memif_realloc,
504             memif_free_t * memif_free)
505 {
506   int err = MEMIF_ERR_SUCCESS;  /* 0 */
507   libmemif_main_t *lm = &libmemif_main;
508   memset (lm, 0, sizeof (libmemif_main_t));
509
510   /* register custom memory management */
511   if (memif_alloc != NULL)
512     {
513       memif_alloc_register (lm, memif_alloc);
514     }
515   else
516     memif_alloc_register (lm, malloc);
517
518   if (memif_realloc != NULL)
519     {
520       memif_realloc_register (lm, memif_realloc);
521     }
522   else
523     memif_realloc_register (lm, realloc);
524
525   if (memif_free != NULL)
526     memif_free_register (lm, memif_free);
527   else
528     memif_free_register (lm, free);
529
530   if (app_name != NULL)
531     {
532       strlcpy ((char *) lm->app_name, app_name, sizeof (lm->app_name));
533     }
534   else
535     {
536       strlcpy ((char *) lm->app_name, MEMIF_DEFAULT_APP_NAME,
537                sizeof (lm->app_name));
538     }
539
540   lm->poll_cancel_fd = -1;
541   /* register control fd update callback */
542   if (on_control_fd_update != NULL)
543     memif_control_fd_update_register (lm, on_control_fd_update);
544   else
545     {
546       lm->epfd = epoll_create (1);
547       memif_control_fd_update_register (lm, memif_control_fd_update);
548       if ((lm->poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
549         {
550           err = errno;
551           DBG ("eventfd: %s", strerror (err));
552           return memif_syscall_error_handler (err);
553         }
554       lm->control_fd_update (lm->poll_cancel_fd, MEMIF_FD_EVENT_READ, lm->private_ctx);
555       DBG ("libmemif event polling initialized");
556     }
557
558   lm->control_list_len = 2;
559   lm->interrupt_list_len = 2;
560   lm->socket_list_len = 1;
561   lm->pending_list_len = 1;
562
563   lm->control_list =
564     lm->alloc (sizeof (memif_list_elt_t) * lm->control_list_len);
565   if (lm->control_list == NULL)
566     {
567       err = MEMIF_ERR_NOMEM;
568       goto error;
569     }
570   lm->interrupt_list =
571     lm->alloc (sizeof (memif_list_elt_t) * lm->interrupt_list_len);
572   if (lm->interrupt_list == NULL)
573     {
574       err = MEMIF_ERR_NOMEM;
575       goto error;
576     }
577   lm->socket_list =
578     lm->alloc (sizeof (memif_list_elt_t) * lm->socket_list_len);
579   if (lm->socket_list == NULL)
580     {
581       err = MEMIF_ERR_NOMEM;
582       goto error;
583     }
584   lm->pending_list =
585     lm->alloc (sizeof (memif_list_elt_t) * lm->pending_list_len);
586   if (lm->pending_list == NULL)
587     {
588       err = MEMIF_ERR_NOMEM;
589       goto error;
590     }
591
592   int i;
593   for (i = 0; i < lm->control_list_len; i++)
594     {
595       lm->control_list[i].key = -1;
596       lm->control_list[i].data_struct = NULL;
597     }
598   for (i = 0; i < lm->interrupt_list_len; i++)
599     {
600       lm->interrupt_list[i].key = -1;
601       lm->interrupt_list[i].data_struct = NULL;
602     }
603   for (i = 0; i < lm->socket_list_len; i++)
604     {
605       lm->socket_list[i].key = -1;
606       lm->socket_list[i].data_struct = NULL;
607     }
608   for (i = 0; i < lm->pending_list_len; i++)
609     {
610       lm->pending_list[i].key = -1;
611       lm->pending_list[i].data_struct = NULL;
612     }
613
614   lm->disconn_slaves = 0;
615
616   lm->timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
617   if (lm->timerfd < 0)
618     {
619       err = memif_syscall_error_handler (errno);
620       goto error;
621     }
622
623   lm->arm.it_value.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
624   lm->arm.it_value.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
625   lm->arm.it_interval.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
626   lm->arm.it_interval.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
627
628   if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ, lm->private_ctx) < 0)
629     {
630       DBG ("callback type memif_control_fd_update_t error!");
631       err = MEMIF_ERR_CB_FDUPDATE;
632       goto error;
633     }
634
635   /* Create default socket */
636   err = memif_create_socket ((memif_socket_handle_t *) &
637                              lm->default_socket,
638                              MEMIF_DEFAULT_SOCKET_PATH, NULL);
639   if (err != MEMIF_ERR_SUCCESS)
640     goto error;
641
642   return err;
643
644 error:
645   memif_cleanup ();
646   return err;
647 }
648
649 int
650 memif_per_thread_init (memif_per_thread_main_handle_t * pt_main,
651                        void *private_ctx,
652                        memif_control_fd_update_t * on_control_fd_update,
653                        char *app_name, memif_alloc_t * memif_alloc,
654                        memif_realloc_t * memif_realloc,
655                        memif_free_t * memif_free)
656 {
657   memif_err_t err = MEMIF_ERR_SUCCESS;
658   int i;
659   libmemif_main_t *lm;
660
661   /* Allocate unique libmemif main */
662   if (memif_alloc != NULL)
663     lm = memif_alloc (sizeof (libmemif_main_t));
664   else
665     lm = malloc (sizeof (libmemif_main_t));
666
667   if (lm == NULL)
668     return MEMIF_ERR_NOMEM;
669
670   memset (lm, 0, sizeof (libmemif_main_t));
671
672   /* register custom memory management */
673   if (memif_alloc != NULL)
674     {
675       memif_alloc_register (lm, memif_alloc);
676     }
677   else
678     memif_alloc_register (lm, malloc);
679
680   if (memif_realloc != NULL)
681     {
682       memif_realloc_register (lm, memif_realloc);
683     }
684   else
685     memif_realloc_register (lm, realloc);
686
687   if (memif_free != NULL)
688     memif_free_register (lm, memif_free);
689   else
690     memif_free_register (lm, free);
691
692   lm->private_ctx = private_ctx;
693
694   /* set app name */
695   if (app_name != NULL)
696     {
697       strlcpy ((char *) lm->app_name, app_name, MEMIF_NAME_LEN);
698     }
699   else
700     {
701       strlcpy ((char *) lm->app_name, MEMIF_DEFAULT_APP_NAME,
702                sizeof (lm->app_name));
703     }
704
705   lm->poll_cancel_fd = -1;
706   /* register control fd update callback */
707   if (on_control_fd_update != NULL)
708     memif_control_fd_update_register (lm, on_control_fd_update);
709   else
710     {
711       /* private_ctx only used internally by memif_control_fd_update
712        * pointer to this libmemif main
713        */
714       lm->private_ctx = lm;
715       lm->epfd = epoll_create (1);
716       memif_control_fd_update_register (lm, memif_control_fd_update);
717       if ((lm->poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
718         {
719           err = errno;
720           DBG ("eventfd: %s", strerror (err));
721           return memif_syscall_error_handler (err);
722         }
723       lm->control_fd_update (lm->poll_cancel_fd, MEMIF_FD_EVENT_READ,
724                              lm->private_ctx);
725       DBG ("libmemif event polling initialized");
726     }
727
728   /* Initialize lists */
729   lm->control_list_len = 2;
730   lm->interrupt_list_len = 2;
731   lm->socket_list_len = 1;
732   lm->pending_list_len = 1;
733
734   lm->control_list =
735     lm->alloc (sizeof (memif_list_elt_t) * lm->control_list_len);
736   if (lm->control_list == NULL)
737     {
738       err = MEMIF_ERR_NOMEM;
739       goto error;
740     }
741   lm->interrupt_list =
742     lm->alloc (sizeof (memif_list_elt_t) * lm->interrupt_list_len);
743   if (lm->interrupt_list == NULL)
744     {
745       err = MEMIF_ERR_NOMEM;
746       goto error;
747     }
748   lm->socket_list =
749     lm->alloc (sizeof (memif_list_elt_t) * lm->socket_list_len);
750   if (lm->socket_list == NULL)
751     {
752       err = MEMIF_ERR_NOMEM;
753       goto error;
754     }
755   lm->pending_list =
756     lm->alloc (sizeof (memif_list_elt_t) * lm->pending_list_len);
757   if (lm->pending_list == NULL)
758     {
759       err = MEMIF_ERR_NOMEM;
760       goto error;
761     }
762
763   for (i = 0; i < lm->control_list_len; i++)
764     {
765       lm->control_list[i].key = -1;
766       lm->control_list[i].data_struct = NULL;
767     }
768   for (i = 0; i < lm->interrupt_list_len; i++)
769     {
770       lm->interrupt_list[i].key = -1;
771       lm->interrupt_list[i].data_struct = NULL;
772     }
773   for (i = 0; i < lm->socket_list_len; i++)
774     {
775       lm->socket_list[i].key = -1;
776       lm->socket_list[i].data_struct = NULL;
777     }
778   for (i = 0; i < lm->pending_list_len; i++)
779     {
780       lm->pending_list[i].key = -1;
781       lm->pending_list[i].data_struct = NULL;
782     }
783
784   /* Initialize autoconnect */
785   lm->disconn_slaves = 0;
786
787   lm->timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
788   if (lm->timerfd < 0)
789     {
790       err = memif_syscall_error_handler (errno);
791       goto error;
792     }
793
794   lm->arm.it_value.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
795   lm->arm.it_value.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
796   lm->arm.it_interval.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
797   lm->arm.it_interval.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
798
799   if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ,
800                              lm->private_ctx) < 0)
801     {
802       DBG ("callback type memif_control_fd_update_t error!");
803       err = MEMIF_ERR_CB_FDUPDATE;
804       goto error;
805     }
806
807   *pt_main = lm;
808
809   return err;
810
811 error:
812   *pt_main = lm;
813   memif_per_thread_cleanup (pt_main);
814   return err;
815 }
816
817 static inline memif_ring_t *
818 memif_get_ring (memif_connection_t * conn, memif_ring_type_t type,
819                 uint16_t ring_num)
820 {
821   if (&conn->regions[0] == NULL)
822     return NULL;
823   void *p = conn->regions[0].addr;
824   int ring_size =
825     sizeof (memif_ring_t) +
826     sizeof (memif_desc_t) * (1 << conn->run_args.log2_ring_size);
827   p += (ring_num + type * conn->run_args.num_s2m_rings) * ring_size;
828
829   return (memif_ring_t *) p;
830 }
831
832 int
833 memif_set_rx_mode (memif_conn_handle_t c, memif_rx_mode_t rx_mode,
834                    uint16_t qid)
835 {
836   memif_connection_t *conn = (memif_connection_t *) c;
837   if (conn == NULL)
838     return MEMIF_ERR_NOCONN;
839   uint8_t num =
840     (conn->args.is_master) ? conn->run_args.num_s2m_rings : conn->
841     run_args.num_m2s_rings;
842   if (qid >= num)
843     return MEMIF_ERR_QID;
844
845   conn->rx_queues[qid].ring->flags = rx_mode;
846   DBG ("rx_mode flag: %u", conn->rx_queues[qid].ring->flags);
847   return MEMIF_ERR_SUCCESS;
848 }
849
850 static int
851 memif_socket_start_listening (memif_socket_t * ms)
852 {
853   libmemif_main_t *lm = get_libmemif_main (ms);
854   memif_list_elt_t elt;
855   struct stat file_stat;
856   struct sockaddr_un un = { 0 };
857   int on = 1;
858   int err = MEMIF_ERR_SUCCESS;
859
860   if (ms->type == MEMIF_SOCKET_TYPE_CLIENT)
861     return MEMIF_ERR_INVAL_ARG;
862
863   /* check if file exists */
864   if (stat ((char *) ms->filename, &file_stat) == 0)
865     {
866       if (S_ISSOCK (file_stat.st_mode))
867         unlink ((char *) ms->filename);
868       else
869         return memif_syscall_error_handler (errno);
870     }
871
872   ms->fd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
873   if (ms->fd < 0)
874     {
875       err = memif_syscall_error_handler (errno);
876       goto error;
877     }
878
879   DBG ("socket %d created", ms->fd);
880   un.sun_family = AF_UNIX;
881   strlcpy ((char *) un.sun_path, (char *) ms->filename, sizeof (un.sun_path));
882   if (setsockopt (ms->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
883     {
884       err = memif_syscall_error_handler (errno);
885       goto error;
886     }
887   if (bind (ms->fd, (struct sockaddr *) &un, sizeof (un)) < 0)
888     {
889       err = memif_syscall_error_handler (errno);
890       goto error;
891     }
892   if (listen (ms->fd, 1) < 0)
893     {
894       err = memif_syscall_error_handler (errno);
895       goto error;
896     }
897   if (stat ((char *) ms->filename, &file_stat) < 0)
898     {
899       err = memif_syscall_error_handler (errno);
900       goto error;
901     }
902
903   /* add socket to libmemif main */
904   elt.key = ms->fd;
905   elt.data_struct = ms;
906   add_list_elt (lm, &elt, &lm->socket_list, &lm->socket_list_len);
907   /* if lm->private_ctx == lm event polling is done by libmemif */
908   lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_READ, lm->private_ctx);
909
910   ms->type = MEMIF_SOCKET_TYPE_LISTENER;
911
912   return err;
913
914 error:
915   if (ms->fd > 0)
916     {
917       close (ms->fd);
918       ms->fd = -1;
919     }
920   return err;
921 }
922
923 int
924 memif_create_socket (memif_socket_handle_t * sock, const char *filename,
925                      void *private_ctx)
926 {
927   libmemif_main_t *lm = &libmemif_main;
928   memif_socket_t *ms = (memif_socket_t *) * sock;
929   int i, err = MEMIF_ERR_SUCCESS;
930
931   for (i = 0; i < lm->socket_list_len; i++)
932     {
933       if ((ms = (memif_socket_t *) lm->socket_list[i].data_struct) != NULL)
934         {
935           if (strncmp ((char *) ms->filename, filename,
936                        strlen ((char *) ms->filename)) == 0)
937             return MEMIF_ERR_INVAL_ARG;
938         }
939     }
940
941   /* allocate memif_socket_t */
942   ms = NULL;
943   ms = lm->alloc (sizeof (memif_socket_t));
944   if (ms == NULL)
945     {
946       err = MEMIF_ERR_NOMEM;
947       goto error;
948     }
949   memset (ms, 0, sizeof (memif_socket_t));
950   /* set filename */
951   ms->filename = lm->alloc (strlen (filename) + sizeof (char));
952   if (ms->filename == NULL)
953     {
954       err = MEMIF_ERR_NOMEM;
955       goto error;
956     }
957   memset (ms->filename, 0, strlen (filename) + sizeof (char));
958   strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
959
960   ms->type = MEMIF_SOCKET_TYPE_NONE;
961
962   ms->interface_list_len = 1;
963   ms->interface_list =
964     lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
965   if (ms->interface_list == NULL)
966     {
967       err = MEMIF_ERR_NOMEM;
968       goto error;
969     }
970   ms->interface_list[0].key = -1;
971   ms->interface_list[0].data_struct = NULL;
972
973   *sock = ms;
974
975   return err;
976
977 error:
978   if (ms != NULL)
979     {
980       if (ms->filename != NULL)
981         {
982           lm->free (ms->filename);
983           ms->filename = NULL;
984         }
985       if (ms->fd > 0)
986         {
987           close (ms->fd);
988           ms->fd = -1;
989         }
990       if (ms->interface_list != NULL)
991         {
992           lm->free (ms->interface_list);
993           ms->interface_list = NULL;
994           ms->interface_list_len = 0;
995         }
996       lm->free (ms);
997       *sock = ms = NULL;
998     }
999   return err;
1000 }
1001
1002 int
1003 memif_per_thread_create_socket (memif_per_thread_main_handle_t pt_main,
1004                                 memif_socket_handle_t * sock,
1005                                 const char *filename, void *private_ctx)
1006 {
1007   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1008   memif_socket_t *ms = (memif_socket_t *) * sock;
1009   int i, err = MEMIF_ERR_SUCCESS;
1010
1011   if (lm == NULL)
1012     return MEMIF_ERR_INVAL_ARG;
1013
1014   for (i = 0; i < lm->socket_list_len; i++)
1015     {
1016       if ((ms = (memif_socket_t *) lm->socket_list[i].data_struct) != NULL)
1017         {
1018           if (strncmp ((char *) ms->filename, filename,
1019                        strlen ((char *) ms->filename)) == 0)
1020             return MEMIF_ERR_INVAL_ARG;
1021         }
1022     }
1023
1024   /* allocate memif_socket_t */
1025   ms = NULL;
1026   ms = lm->alloc (sizeof (memif_socket_t));
1027   if (ms == NULL)
1028     {
1029       err = MEMIF_ERR_NOMEM;
1030       goto error;
1031     }
1032   memset (ms, 0, sizeof (memif_socket_t));
1033   ms->lm = lm;
1034   /* set filename */
1035   ms->filename = lm->alloc (strlen (filename) + sizeof (char));
1036   if (ms->filename == NULL)
1037     {
1038       err = MEMIF_ERR_NOMEM;
1039       goto error;
1040     }
1041   memset (ms->filename, 0, strlen (filename) + sizeof (char));
1042   strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
1043
1044   ms->type = MEMIF_SOCKET_TYPE_NONE;
1045
1046   ms->interface_list_len = 1;
1047   ms->interface_list =
1048     lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
1049   if (ms->interface_list == NULL)
1050     {
1051       err = MEMIF_ERR_NOMEM;
1052       goto error;
1053     }
1054   ms->interface_list[0].key = -1;
1055   ms->interface_list[0].data_struct = NULL;
1056
1057   *sock = ms;
1058
1059   return err;
1060
1061 error:
1062   if (ms != NULL)
1063     {
1064       if (ms->filename != NULL)
1065         {
1066           lm->free (ms->filename);
1067           ms->filename = NULL;
1068         }
1069       if (ms->fd > 0)
1070         {
1071           close (ms->fd);
1072           ms->fd = -1;
1073         }
1074       if (ms->interface_list != NULL)
1075         {
1076           lm->free (ms->interface_list);
1077           ms->interface_list = NULL;
1078           ms->interface_list_len = 0;
1079         }
1080       lm->free (ms);
1081       *sock = ms = NULL;
1082     }
1083   return err;
1084 }
1085
1086 int
1087 memif_create (memif_conn_handle_t * c, memif_conn_args_t * args,
1088               memif_connection_update_t * on_connect,
1089               memif_connection_update_t * on_disconnect,
1090               memif_interrupt_t * on_interrupt, void *private_ctx)
1091 {
1092   libmemif_main_t *lm = get_libmemif_main (args->socket);
1093   int err, index = 0;
1094   memif_list_elt_t elt;
1095   memif_connection_t *conn = (memif_connection_t *) * c;
1096   memif_socket_t *ms;
1097
1098   if (conn != NULL)
1099     {
1100       DBG ("This handle already points to existing memif.");
1101       return MEMIF_ERR_CONN;
1102     }
1103
1104   conn = (memif_connection_t *) lm->alloc (sizeof (memif_connection_t));
1105   if (conn == NULL)
1106     {
1107       err = MEMIF_ERR_NOMEM;
1108       goto error;
1109     }
1110   memset (conn, 0, sizeof (memif_connection_t));
1111
1112   conn->args.interface_id = args->interface_id;
1113
1114   if (args->log2_ring_size == 0)
1115     args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
1116   else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
1117     {
1118       err = MEMIF_ERR_MAX_RING;
1119       goto error;
1120     }
1121   if (args->buffer_size == 0)
1122     args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
1123   if (args->num_s2m_rings == 0)
1124     args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
1125   if (args->num_m2s_rings == 0)
1126     args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
1127
1128   conn->args.num_s2m_rings = args->num_s2m_rings;
1129   conn->args.num_m2s_rings = args->num_m2s_rings;
1130   conn->args.buffer_size = args->buffer_size;
1131   conn->args.log2_ring_size = args->log2_ring_size;
1132   conn->args.is_master = args->is_master;
1133   conn->args.mode = args->mode;
1134   conn->msg_queue = NULL;
1135   conn->regions = NULL;
1136   conn->tx_queues = NULL;
1137   conn->rx_queues = NULL;
1138   conn->fd = -1;
1139   conn->on_connect = on_connect;
1140   conn->on_disconnect = on_disconnect;
1141   conn->on_interrupt = on_interrupt;
1142   conn->private_ctx = private_ctx;
1143   memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
1144
1145   strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
1146            sizeof (conn->args.interface_name));
1147
1148   if ((strlen ((char *) args->secret)) > 0)
1149     strlcpy ((char *) conn->args.secret, (char *) args->secret,
1150              sizeof (conn->args.secret));
1151
1152   if (args->socket != NULL)
1153     conn->args.socket = args->socket;
1154   else if (lm->default_socket != NULL)
1155     conn->args.socket = lm->default_socket;
1156   else
1157     {
1158       err = MEMIF_ERR_INVAL_ARG;
1159       goto error;
1160     }
1161
1162   ms = (memif_socket_t *) conn->args.socket;
1163
1164   if ((conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_CLIENT) ||
1165       (!conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_LISTENER))
1166     {
1167       err = MEMIF_ERR_INVAL_ARG;
1168       goto error;
1169     }
1170
1171   elt.key = conn->args.interface_id;
1172   elt.data_struct = conn;
1173   add_list_elt (lm, &elt, &ms->interface_list, &ms->interface_list_len);
1174   ms->use_count++;
1175
1176   if (conn->args.is_master)
1177     {
1178       if (ms->type == MEMIF_SOCKET_TYPE_NONE)
1179         {
1180           err = memif_socket_start_listening (ms);
1181           if (err != MEMIF_ERR_SUCCESS)
1182             goto error;
1183         }
1184     }
1185   else
1186     {
1187       elt.key = -1;
1188       elt.data_struct = conn;
1189       if ((index =
1190            add_list_elt (lm, &elt, &lm->control_list,
1191                          &lm->control_list_len)) < 0)
1192         {
1193           err = MEMIF_ERR_NOMEM;
1194           goto error;
1195         }
1196
1197       conn->index = index;
1198
1199       /* try connecting to master */
1200       err = memif_request_connection (conn);
1201       if ((err != MEMIF_ERR_SUCCESS) && (lm->disconn_slaves == 0))
1202         {
1203           /* connection failed, arm reconnect timer (if not armed) */
1204           if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1205             {
1206               err = memif_syscall_error_handler (errno);
1207               goto error;
1208             }
1209         }
1210       lm->disconn_slaves++;
1211     }
1212
1213   *c = conn;
1214
1215   return 0;
1216
1217 error:
1218   if (conn != NULL)
1219     lm->free (conn);
1220   *c = conn = NULL;
1221   return err;
1222 }
1223
1224 int
1225 memif_request_connection (memif_conn_handle_t c)
1226 {
1227   memif_connection_t *conn = (memif_connection_t *) c;
1228   libmemif_main_t *lm;
1229   memif_socket_t *ms;
1230   int err = MEMIF_ERR_SUCCESS;
1231   int sockfd = -1;
1232   struct sockaddr_un sun;
1233
1234   if (conn == NULL)
1235     return MEMIF_ERR_NOCONN;
1236
1237   ms = (memif_socket_t *) conn->args.socket;
1238   lm = get_libmemif_main (ms);
1239
1240
1241   if (conn->args.is_master || ms->type == MEMIF_SOCKET_TYPE_LISTENER)
1242     return MEMIF_ERR_INVAL_ARG;
1243   if (conn->fd > 0)
1244     return MEMIF_ERR_ALRCONN;
1245
1246   sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
1247   if (sockfd < 0)
1248     {
1249       err = memif_syscall_error_handler (errno);
1250       goto error;
1251     }
1252
1253   sun.sun_family = AF_UNIX;
1254
1255   strlcpy (sun.sun_path, (char *) ms->filename, sizeof (sun.sun_path));
1256
1257   if (connect (sockfd, (struct sockaddr *) &sun,
1258                sizeof (struct sockaddr_un)) == 0)
1259     {
1260       conn->fd = sockfd;
1261       conn->read_fn = memif_conn_fd_read_ready;
1262       conn->write_fn = memif_conn_fd_write_ready;
1263       conn->error_fn = memif_conn_fd_error;
1264
1265       lm->control_list[conn->index].key = conn->fd;
1266       lm->control_fd_update (sockfd,
1267                              MEMIF_FD_EVENT_READ |
1268                              MEMIF_FD_EVENT_WRITE, lm->private_ctx);
1269
1270       lm->disconn_slaves--;
1271       if (lm->disconn_slaves == 0)
1272         {
1273           if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1274             {
1275               err = memif_syscall_error_handler (errno);
1276               return err;
1277             }
1278         }
1279     }
1280   else
1281     {
1282       err = memif_syscall_error_handler (errno);
1283       strcpy ((char *) conn->remote_disconnect_string, memif_strerror (err));
1284       goto error;
1285     }
1286
1287   ms->type = MEMIF_SOCKET_TYPE_CLIENT;
1288
1289   return err;
1290
1291 error:
1292   if (sockfd > 0)
1293     close (sockfd);
1294   sockfd = -1;
1295   return err;
1296 }
1297
1298 int
1299 memif_control_fd_handler (int fd, uint8_t events)
1300 {
1301   int i, err = MEMIF_ERR_SUCCESS;       /* 0 */
1302   uint16_t num;
1303   memif_list_elt_t *e = NULL;
1304   memif_connection_t *conn;
1305   libmemif_main_t *lm = &libmemif_main;
1306   if (fd == lm->timerfd)
1307     {
1308       uint64_t b;
1309       ssize_t size;
1310       size = read (fd, &b, sizeof (b));
1311
1312       if (size == -1)
1313         goto error;
1314
1315       for (i = 0; i < lm->control_list_len; i++)
1316         {
1317           if ((lm->control_list[i].key < 0)
1318               && (lm->control_list[i].data_struct != NULL))
1319             {
1320               conn = lm->control_list[i].data_struct;
1321               if (conn->args.is_master)
1322                 continue;
1323               err = memif_request_connection (conn);
1324               if (err != MEMIF_ERR_SUCCESS)
1325                 DBG ("memif_request_connection: %s", memif_strerror (err));
1326             }
1327         }
1328     }
1329   else
1330     {
1331       get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1332       if (e != NULL)
1333         {
1334           if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1335             {
1336               num =
1337                 (((memif_connection_t *) e->data_struct)->
1338                  args.is_master) ? ((memif_connection_t *) e->
1339                                     data_struct)->run_args.
1340                 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1341                 run_args.num_m2s_rings;
1342               for (i = 0; i < num; i++)
1343                 {
1344                   if (((memif_connection_t *) e->data_struct)->
1345                       rx_queues[i].int_fd == fd)
1346                     {
1347                       ((memif_connection_t *) e->data_struct)->
1348                         on_interrupt ((void *) e->data_struct,
1349                                       ((memif_connection_t *) e->
1350                                        data_struct)->private_ctx, i);
1351                       return MEMIF_ERR_SUCCESS;
1352                     }
1353                 }
1354             }
1355           return MEMIF_ERR_SUCCESS;
1356         }
1357       get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1358       if (e != NULL
1359           && ((memif_socket_t *) e->data_struct)->type ==
1360           MEMIF_SOCKET_TYPE_LISTENER)
1361         {
1362           err =
1363             memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
1364           return err;
1365         }
1366
1367       get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1368       if (e != NULL)
1369         {
1370           err = memif_read_ready (lm, fd);
1371           return err;
1372         }
1373
1374       get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1375       if (e != NULL)
1376         {
1377           if (events & MEMIF_FD_EVENT_READ)
1378             {
1379               err =
1380                 ((memif_connection_t *) e->data_struct)->
1381                 read_fn (e->data_struct);
1382               if (err != MEMIF_ERR_SUCCESS)
1383                 return err;
1384             }
1385           if (events & MEMIF_FD_EVENT_WRITE)
1386             {
1387               err =
1388                 ((memif_connection_t *) e->data_struct)->
1389                 write_fn (e->data_struct);
1390               if (err != MEMIF_ERR_SUCCESS)
1391                 return err;
1392             }
1393           if (events & MEMIF_FD_EVENT_ERROR)
1394             {
1395               err =
1396                 ((memif_connection_t *) e->data_struct)->
1397                 error_fn (e->data_struct);
1398               if (err != MEMIF_ERR_SUCCESS)
1399                 return err;
1400             }
1401         }
1402     }
1403
1404   return MEMIF_ERR_SUCCESS;     /* 0 */
1405
1406 error:
1407   return err;
1408 }
1409
1410 int
1411 memif_per_thread_control_fd_handler (memif_per_thread_main_handle_t pt_main,
1412                                      int fd, uint8_t events)
1413 {
1414   int i, err = MEMIF_ERR_SUCCESS;       /* 0 */
1415   uint16_t num;
1416   memif_list_elt_t *e = NULL;
1417   memif_connection_t *conn;
1418   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1419
1420   if (fd == lm->timerfd)
1421     {
1422       uint64_t b;
1423       ssize_t size;
1424       size = read (fd, &b, sizeof (b));
1425
1426       if (size == -1)
1427         goto error;
1428
1429       for (i = 0; i < lm->control_list_len; i++)
1430         {
1431           if ((lm->control_list[i].key < 0)
1432               && (lm->control_list[i].data_struct != NULL))
1433             {
1434               conn = lm->control_list[i].data_struct;
1435               if (conn->args.is_master)
1436                 continue;
1437               err = memif_request_connection (conn);
1438               if (err != MEMIF_ERR_SUCCESS)
1439                 DBG ("memif_request_connection: %s", memif_strerror (err));
1440             }
1441         }
1442     }
1443   else
1444     {
1445       get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1446       if (e != NULL)
1447         {
1448           if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1449             {
1450               num =
1451                 (((memif_connection_t *) e->data_struct)->
1452                  args.is_master) ? ((memif_connection_t *) e->
1453                                     data_struct)->run_args.
1454                 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1455                 run_args.num_m2s_rings;
1456               for (i = 0; i < num; i++)
1457                 {
1458                   if (((memif_connection_t *) e->data_struct)->
1459                       rx_queues[i].int_fd == fd)
1460                     {
1461                       ((memif_connection_t *) e->data_struct)->
1462                         on_interrupt ((void *) e->data_struct,
1463                                       ((memif_connection_t *) e->
1464                                        data_struct)->private_ctx, i);
1465                       return MEMIF_ERR_SUCCESS;
1466                     }
1467                 }
1468             }
1469           return MEMIF_ERR_SUCCESS;
1470         }
1471       get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1472       if (e != NULL
1473           && ((memif_socket_t *) e->data_struct)->type ==
1474           MEMIF_SOCKET_TYPE_LISTENER)
1475         {
1476           err =
1477             memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
1478           return err;
1479         }
1480
1481       get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1482       if (e != NULL)
1483         {
1484           err = memif_read_ready (lm, fd);
1485           return err;
1486         }
1487
1488       get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1489       if (e != NULL)
1490         {
1491           if (events & MEMIF_FD_EVENT_READ)
1492             {
1493               err =
1494                 ((memif_connection_t *) e->data_struct)->
1495                 read_fn (e->data_struct);
1496               if (err != MEMIF_ERR_SUCCESS)
1497                 return err;
1498             }
1499           if (events & MEMIF_FD_EVENT_WRITE)
1500             {
1501               err =
1502                 ((memif_connection_t *) e->data_struct)->
1503                 write_fn (e->data_struct);
1504               if (err != MEMIF_ERR_SUCCESS)
1505                 return err;
1506             }
1507           if (events & MEMIF_FD_EVENT_ERROR)
1508             {
1509               err =
1510                 ((memif_connection_t *) e->data_struct)->
1511                 error_fn (e->data_struct);
1512               if (err != MEMIF_ERR_SUCCESS)
1513                 return err;
1514             }
1515         }
1516     }
1517
1518   return MEMIF_ERR_SUCCESS;     /* 0 */
1519
1520 error:
1521   return err;
1522 }
1523
1524 int
1525 memif_poll_event (int timeout)
1526 {
1527   libmemif_main_t *lm = &libmemif_main;
1528   struct epoll_event evt;
1529   int en = 0, err = MEMIF_ERR_SUCCESS;  /* 0 */
1530   uint32_t events = 0;
1531   uint64_t counter = 0;
1532   ssize_t r = 0;
1533   memset (&evt, 0, sizeof (evt));
1534   evt.events = EPOLLIN | EPOLLOUT;
1535   sigset_t sigset;
1536   sigemptyset (&sigset);
1537   en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
1538   if (en < 0)
1539     {
1540       err = errno;
1541       DBG ("epoll_pwait: %s", strerror (err));
1542       return memif_syscall_error_handler (err);
1543     }
1544   if (en > 0)
1545     {
1546       if (evt.data.fd == lm->poll_cancel_fd)
1547         {
1548           r = read (evt.data.fd, &counter, sizeof (counter));
1549           if (r == -1)
1550             return MEMIF_ERR_DISCONNECTED;
1551
1552           return MEMIF_ERR_POLL_CANCEL;
1553         }
1554       if (evt.events & EPOLLIN)
1555         events |= MEMIF_FD_EVENT_READ;
1556       if (evt.events & EPOLLOUT)
1557         events |= MEMIF_FD_EVENT_WRITE;
1558       if (evt.events & EPOLLERR)
1559         events |= MEMIF_FD_EVENT_ERROR;
1560       err = memif_control_fd_handler (evt.data.fd, events);
1561       return err;
1562     }
1563   return 0;
1564 }
1565
1566 int
1567 memif_per_thread_poll_event (memif_per_thread_main_handle_t pt_main,
1568                              int timeout)
1569 {
1570   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1571   struct epoll_event evt;
1572   int en = 0, err = MEMIF_ERR_SUCCESS;  /* 0 */
1573   uint32_t events = 0;
1574   uint64_t counter = 0;
1575   ssize_t r = 0;
1576   memset (&evt, 0, sizeof (evt));
1577   evt.events = EPOLLIN | EPOLLOUT;
1578   sigset_t sigset;
1579   sigemptyset (&sigset);
1580   en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
1581   if (en < 0)
1582     {
1583       err = errno;
1584       DBG ("epoll_pwait: %s", strerror (err));
1585       return memif_syscall_error_handler (err);
1586     }
1587   if (en > 0)
1588     {
1589       if (evt.data.fd == lm->poll_cancel_fd)
1590         {
1591           r = read (evt.data.fd, &counter, sizeof (counter));
1592           if (r == -1)
1593             return MEMIF_ERR_DISCONNECTED;
1594
1595           return MEMIF_ERR_POLL_CANCEL;
1596         }
1597       if (evt.events & EPOLLIN)
1598         events |= MEMIF_FD_EVENT_READ;
1599       if (evt.events & EPOLLOUT)
1600         events |= MEMIF_FD_EVENT_WRITE;
1601       if (evt.events & EPOLLERR)
1602         events |= MEMIF_FD_EVENT_ERROR;
1603       err = memif_control_fd_handler (evt.data.fd, events);
1604       return err;
1605     }
1606   return 0;
1607 }
1608
1609 int
1610 memif_cancel_poll_event ()
1611 {
1612   libmemif_main_t *lm = &libmemif_main;
1613   uint64_t counter = 1;
1614   ssize_t w = 0;
1615
1616   if (lm->poll_cancel_fd == -1)
1617     return 0;
1618   w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
1619   if (w < sizeof (counter))
1620     return MEMIF_ERR_INT_WRITE;
1621
1622   return 0;
1623 }
1624
1625 int
1626 memif_per_thread_cancel_poll_event (memif_per_thread_main_handle_t pt_main)
1627 {
1628   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1629   uint64_t counter = 1;
1630   ssize_t w = 0;
1631
1632   if (lm == NULL)
1633     return MEMIF_ERR_INVAL_ARG;
1634
1635   if (lm->poll_cancel_fd == -1)
1636     return 0;
1637   w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
1638   if (w < sizeof (counter))
1639     return MEMIF_ERR_INT_WRITE;
1640
1641   return 0;
1642 }
1643
1644 static void
1645 memif_msg_queue_free (libmemif_main_t * lm, memif_msg_queue_elt_t ** e)
1646 {
1647   if (*e == NULL)
1648     return;
1649   memif_msg_queue_free (lm, &(*e)->next);
1650   lm->free (*e);
1651   *e = NULL;
1652   return;
1653 }
1654
1655 /* send disconnect msg and close interface */
1656 int
1657 memif_disconnect_internal (memif_connection_t * c)
1658 {
1659   int err = MEMIF_ERR_SUCCESS, i;       /* 0 */
1660   memif_queue_t *mq;
1661   libmemif_main_t *lm;
1662   memif_list_elt_t *e;
1663
1664   if (c == NULL)
1665     {
1666       DBG ("no connection");
1667       return MEMIF_ERR_NOCONN;
1668     }
1669
1670   lm = get_libmemif_main (c->args.socket);
1671
1672   c->on_disconnect ((void *) c, c->private_ctx);
1673
1674   if (c->fd > 0)
1675     {
1676       memif_msg_send_disconnect (c->fd, (uint8_t *) "interface deleted", 0);
1677       lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
1678       close (c->fd);
1679     }
1680   get_list_elt (&e, lm->control_list, lm->control_list_len, c->fd);
1681   if (e != NULL)
1682     {
1683       if (c->args.is_master)
1684         free_list_elt (lm->control_list, lm->control_list_len, c->fd);
1685       e->key = c->fd = -1;
1686     }
1687
1688   if (c->tx_queues != NULL)
1689     {
1690       for (i = 0; i < c->tx_queues_num; i++)
1691         {
1692           mq = &c->tx_queues[i];
1693           if (mq != NULL)
1694             {
1695               if (mq->int_fd > 0)
1696                 close (mq->int_fd);
1697               free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1698                              mq->int_fd);
1699               mq->int_fd = -1;
1700             }
1701         }
1702       lm->free (c->tx_queues);
1703       c->tx_queues = NULL;
1704     }
1705   c->tx_queues_num = 0;
1706
1707   if (c->rx_queues != NULL)
1708     {
1709       for (i = 0; i < c->rx_queues_num; i++)
1710         {
1711           mq = &c->rx_queues[i];
1712           if (mq != NULL)
1713             {
1714               if (mq->int_fd > 0)
1715                 {
1716                   if (c->on_interrupt != NULL)
1717                     lm->control_fd_update (mq->int_fd, MEMIF_FD_EVENT_DEL,
1718                                            lm->private_ctx);
1719                   close (mq->int_fd);
1720                 }
1721               free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1722                              mq->int_fd);
1723               mq->int_fd = -1;
1724             }
1725         }
1726       lm->free (c->rx_queues);
1727       c->rx_queues = NULL;
1728     }
1729   c->rx_queues_num = 0;
1730
1731   for (i = 0; i < c->regions_num; i++)
1732     {
1733       if (&c->regions[i] == NULL)
1734         continue;
1735       if (c->regions[i].is_external != 0)
1736         {
1737           lm->del_external_region (c->regions[i].addr,
1738                                    c->regions[i].region_size,
1739                                    c->regions[i].fd, c->private_ctx);
1740         }
1741       else
1742         {
1743           if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1744             return memif_syscall_error_handler (errno);
1745           if (c->regions[i].fd > 0)
1746             close (c->regions[i].fd);
1747           c->regions[i].fd = -1;
1748         }
1749     }
1750   lm->free (c->regions);
1751   c->regions = NULL;
1752   c->regions_num = 0;
1753
1754   memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1755
1756   memif_msg_queue_free (lm, &c->msg_queue);
1757
1758   if (!(c->args.is_master))
1759     {
1760       if (lm->disconn_slaves == 0)
1761         {
1762           if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1763             {
1764               err = memif_syscall_error_handler (errno);
1765               DBG ("timerfd_settime: arm");
1766             }
1767         }
1768       lm->disconn_slaves++;
1769     }
1770
1771   return err;
1772 }
1773
1774 const char *
1775 memif_get_socket_filename (memif_socket_handle_t sock)
1776 {
1777   memif_socket_t *ms = (memif_socket_t *) sock;
1778
1779   if (ms == NULL)
1780     return NULL;
1781
1782   return (char *) ms->filename;
1783 }
1784
1785 int
1786 memif_delete_socket (memif_socket_handle_t * sock)
1787 {
1788   memif_socket_t *ms = (memif_socket_t *) * sock;
1789   libmemif_main_t *lm;
1790
1791   /* check if socket is in use */
1792   if (ms == NULL || ms->use_count > 0)
1793     return MEMIF_ERR_INVAL_ARG;
1794
1795   lm = get_libmemif_main (ms);
1796
1797   lm->free (ms->interface_list);
1798   ms->interface_list = NULL;
1799   lm->free (ms->filename);
1800   ms->filename = NULL;
1801   lm->free (ms);
1802   *sock = ms = NULL;
1803
1804   return MEMIF_ERR_SUCCESS;
1805 }
1806
1807 int
1808 memif_delete (memif_conn_handle_t * conn)
1809 {
1810   memif_connection_t *c = (memif_connection_t *) * conn;
1811   libmemif_main_t *lm;
1812   memif_socket_t *ms = NULL;
1813   int err = MEMIF_ERR_SUCCESS;
1814
1815   if (c == NULL)
1816     {
1817       DBG ("no connection");
1818       return MEMIF_ERR_NOCONN;
1819     }
1820
1821   if (c->fd > 0)
1822     {
1823       DBG ("DISCONNECTING");
1824       err = memif_disconnect_internal (c);
1825       if (err == MEMIF_ERR_NOCONN)
1826         return err;
1827     }
1828
1829   lm = get_libmemif_main (c->args.socket);
1830
1831   free_list_elt_ctx (lm->control_list, lm->control_list_len, c);
1832
1833   ms = (memif_socket_t *) c->args.socket;
1834   ms->use_count--;
1835   free_list_elt (ms->interface_list, ms->interface_list_len,
1836                  c->args.interface_id);
1837   if (ms->use_count <= 0)
1838     {
1839       /* stop listening on this socket */
1840       if (ms->type == MEMIF_SOCKET_TYPE_LISTENER)
1841         {
1842           lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
1843           free_list_elt (lm->socket_list, lm->socket_list_len, ms->fd);
1844           close (ms->fd);
1845           ms->fd = -1;
1846         }
1847       /* socket not in use */
1848       ms->type = MEMIF_SOCKET_TYPE_NONE;
1849     }
1850
1851   if (!c->args.is_master)
1852     {
1853       lm->disconn_slaves--;
1854       if (lm->disconn_slaves <= 0)
1855         {
1856           if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1857             {
1858               err = memif_syscall_error_handler (errno);
1859               DBG ("timerfd_settime: disarm");
1860             }
1861         }
1862     }
1863
1864   lm->free (c);
1865   c = NULL;
1866
1867   *conn = c;
1868   return err;
1869 }
1870
1871 int
1872 memif_connect1 (memif_connection_t * c)
1873 {
1874   libmemif_main_t *lm;
1875   memif_region_t *mr;
1876   memif_queue_t *mq;
1877   int i;
1878
1879   if (c == NULL)
1880     return MEMIF_ERR_INVAL_ARG;
1881
1882   lm = get_libmemif_main (c->args.socket);
1883
1884   for (i = 0; i < c->regions_num; i++)
1885     {
1886       mr = &c->regions[i];
1887       if (mr != NULL)
1888         {
1889           if (!mr->addr)
1890             {
1891               if (mr->is_external)
1892                 {
1893                   if (lm->get_external_region_addr == NULL)
1894                     return MEMIF_ERR_INVAL_ARG;
1895                   mr->addr =
1896                     lm->get_external_region_addr (mr->region_size, mr->fd,
1897                                                   c->private_ctx);
1898                 }
1899               else
1900                 {
1901                   if (mr->fd < 0)
1902                     return MEMIF_ERR_NO_SHMFD;
1903
1904                   if ((mr->addr =
1905                        mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1906                              MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
1907                     {
1908                       return memif_syscall_error_handler (errno);
1909                     }
1910                 }
1911             }
1912         }
1913     }
1914
1915   for (i = 0; i < c->rx_queues_num; i++)
1916     {
1917       mq = &c->rx_queues[i];
1918       if (mq != NULL)
1919         {
1920           mq->ring = c->regions[mq->region].addr + mq->offset;
1921           if (mq->ring->cookie != MEMIF_COOKIE)
1922             {
1923               DBG ("wrong cookie on rx ring %u", i);
1924               return MEMIF_ERR_COOKIE;
1925             }
1926           mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
1927         }
1928     }
1929
1930   for (i = 0; i < c->tx_queues_num; i++)
1931     {
1932       mq = &c->tx_queues[i];
1933       if (mq != NULL)
1934         {
1935           mq->ring = c->regions[mq->region].addr + mq->offset;
1936           if (mq->ring->cookie != MEMIF_COOKIE)
1937             {
1938               DBG ("wrong cookie on tx ring %u", i);
1939               return MEMIF_ERR_COOKIE;
1940             }
1941           mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
1942         }
1943     }
1944
1945   lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD,
1946                          lm->private_ctx);
1947
1948   return 0;
1949 }
1950
1951 static inline int
1952 memif_add_region (libmemif_main_t * lm, memif_connection_t * conn,
1953                   uint8_t has_buffers)
1954 {
1955   memif_region_t *r;
1956
1957   r =
1958     lm->realloc (conn->regions,
1959                  sizeof (memif_region_t) * ++conn->regions_num);
1960   if (r == NULL)
1961     return MEMIF_ERR_NOMEM;
1962
1963   conn->regions = r;
1964   r = &conn->regions[conn->regions_num - 1];
1965   memset (r, 0, sizeof (memif_region_t));
1966
1967   if (has_buffers != 0)
1968     {
1969       r->buffer_offset = 0;
1970     }
1971   else
1972     {
1973       r->buffer_offset =
1974         (conn->run_args.num_s2m_rings +
1975          conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1976                                           sizeof (memif_desc_t) *
1977                                           (1 << conn->
1978                                            run_args.log2_ring_size));
1979     }
1980
1981   r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
1982     conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1983     (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1984
1985   if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
1986     return memif_syscall_error_handler (errno);
1987
1988   if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1989     return memif_syscall_error_handler (errno);
1990
1991   if ((ftruncate (r->fd, r->region_size)) == -1)
1992     return memif_syscall_error_handler (errno);
1993
1994   if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1995                        MAP_SHARED, r->fd, 0)) == MAP_FAILED)
1996     return memif_syscall_error_handler (errno);
1997
1998   return MEMIF_ERR_SUCCESS;
1999 }
2000
2001 static inline int
2002 memif_init_queues (libmemif_main_t * lm, memif_connection_t * conn)
2003 {
2004   int i, j;
2005   memif_ring_t *ring;
2006
2007   for (i = 0; i < conn->run_args.num_s2m_rings; i++)
2008     {
2009       ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
2010       DBG ("RING: %p I: %d", ring, i);
2011       ring->head = ring->tail = 0;
2012       ring->cookie = MEMIF_COOKIE;
2013       ring->flags = 0;
2014       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
2015         {
2016           uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
2017           ring->desc[j].region = 1;
2018           ring->desc[j].offset =
2019             conn->regions[1].buffer_offset +
2020             (uint32_t) (slot * conn->run_args.buffer_size);
2021           ring->desc[j].length = conn->run_args.buffer_size;
2022         }
2023     }
2024   for (i = 0; i < conn->run_args.num_m2s_rings; i++)
2025     {
2026       ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
2027       DBG ("RING: %p I: %d", ring, i);
2028       ring->head = ring->tail = 0;
2029       ring->cookie = MEMIF_COOKIE;
2030       ring->flags = 0;
2031       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
2032         {
2033           uint16_t slot = (i + conn->run_args.num_s2m_rings) *
2034             (1 << conn->run_args.log2_ring_size) + j;
2035           ring->desc[j].region = 1;
2036           ring->desc[j].offset =
2037             conn->regions[1].buffer_offset +
2038             (uint32_t) (slot * conn->run_args.buffer_size);
2039           ring->desc[j].length = conn->run_args.buffer_size;
2040         }
2041     }
2042   memif_queue_t *mq;
2043   DBG ("alloc: %p", lm->alloc);
2044   DBG ("size: %lu", sizeof (memif_queue_t) * conn->run_args.num_s2m_rings);
2045   mq =
2046     (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2047                                  conn->run_args.num_s2m_rings);
2048   if (mq == NULL)
2049     return MEMIF_ERR_NOMEM;
2050
2051   int x;
2052   memif_list_elt_t e;
2053   for (x = 0; x < conn->run_args.num_s2m_rings; x++)
2054     {
2055       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2056         return memif_syscall_error_handler (errno);
2057       e.key = mq[x].int_fd;
2058       e.data_struct = conn;
2059       add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
2060
2061       mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
2062       DBG ("RING: %p I: %d", mq[x].ring, x);
2063       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2064       mq[x].region = 0;
2065       mq[x].offset =
2066         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2067       mq[x].last_head = mq[x].last_tail = 0;
2068       mq[x].next_buf = 0;
2069     }
2070   conn->tx_queues = mq;
2071   conn->tx_queues_num = conn->run_args.num_s2m_rings;
2072
2073   mq =
2074     (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2075                                  conn->run_args.num_m2s_rings);
2076   if (mq == NULL)
2077     return MEMIF_ERR_NOMEM;
2078
2079   for (x = 0; x < conn->run_args.num_m2s_rings; x++)
2080     {
2081       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2082         return memif_syscall_error_handler (errno);
2083       e.key = mq[x].int_fd;
2084       e.data_struct = conn;
2085       add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
2086
2087       mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
2088       DBG ("RING: %p I: %d", mq[x].ring, x);
2089       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2090       mq[x].region = 0;
2091       mq[x].offset =
2092         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2093       mq[x].last_head = mq[x].last_tail = 0;
2094       mq[x].next_buf = 0;
2095     }
2096   conn->rx_queues = mq;
2097   conn->rx_queues_num = conn->run_args.num_m2s_rings;
2098
2099   return MEMIF_ERR_SUCCESS;
2100 }
2101
2102 int
2103 memif_init_regions_and_queues (memif_connection_t * conn)
2104 {
2105   memif_region_t *r;
2106   libmemif_main_t *lm;
2107
2108   if (conn == NULL)
2109     return MEMIF_ERR_INVAL_ARG;
2110
2111   lm = get_libmemif_main (conn->args.socket);
2112
2113   /* region 0. rings */
2114   memif_add_region (lm, conn, /* has_buffers */ 0);
2115
2116   /* region 1. buffers */
2117   if (lm->add_external_region)
2118     {
2119       r =
2120         (memif_region_t *) lm->realloc (conn->regions,
2121                                         sizeof (memif_region_t) *
2122                                         ++conn->regions_num);
2123       if (r == NULL)
2124         return MEMIF_ERR_NOMEM;
2125       conn->regions = r;
2126
2127       conn->regions[1].region_size =
2128         conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
2129         (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
2130       conn->regions[1].buffer_offset = 0;
2131       lm->add_external_region (&conn->regions[1].addr,
2132                                conn->regions[1].region_size,
2133                                &conn->regions[1].fd, conn->private_ctx);
2134       conn->regions[1].is_external = 1;
2135     }
2136   else
2137     {
2138       memif_add_region (lm, conn, 1);
2139     }
2140
2141   memif_init_queues (lm, conn);
2142
2143   return 0;
2144 }
2145
2146 int
2147 memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
2148                             memif_buffer_t *buf)
2149 {
2150   memif_connection_t *c = (memif_connection_t *) conn;
2151   if (EXPECT_FALSE (c == NULL))
2152     return MEMIF_ERR_NOCONN;
2153   if (EXPECT_FALSE (qid >= c->tx_queues_num))
2154     return MEMIF_ERR_QID;
2155   if (EXPECT_FALSE (buf == NULL))
2156     return MEMIF_ERR_INVAL_ARG;
2157
2158   uint16_t ring_size, ns;
2159   memif_queue_t *mq = &c->tx_queues[qid];
2160   memif_ring_t *ring = mq->ring;
2161
2162   ring_size = (1 << mq->log2_ring_size);
2163   if (c->args.is_master)
2164     ns = ring->head - mq->next_buf;
2165   else
2166     ns = ring_size - mq->next_buf + ring->tail;
2167
2168   if ((mq->next_buf - buf->desc_index) > ns)
2169     return MEMIF_ERR_INVAL_ARG;
2170
2171   mq->next_buf = buf->desc_index;
2172
2173   return MEMIF_ERR_SUCCESS;
2174 }
2175
2176 static void
2177 memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
2178                                   memif_buffer_t *buf, uint16_t slot)
2179 {
2180   uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
2181   uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
2182   memif_desc_t *from_d, *to_d, tmp_d;
2183
2184   /* Get the descriptors */
2185   from_d = &from_q->ring->desc[buf->desc_index & from_mask];
2186   to_d = &to_q->ring->desc[slot & to_mask];
2187
2188   /* Swap descriptors */
2189   tmp_d = *from_d;
2190   *from_d = *to_d;
2191   *to_d = tmp_d;
2192
2193   /* Update descriptor index and queue for clients buffer */
2194   buf->desc_index = slot;
2195   buf->queue = to_q;
2196 }
2197
2198 int
2199 memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
2200                       memif_buffer_t *buf_b)
2201 {
2202   memif_connection_t *c = (memif_connection_t *) conn;
2203   if (EXPECT_FALSE (c == NULL))
2204     return MEMIF_ERR_NOCONN;
2205   if (EXPECT_FALSE (c->args.is_master))
2206     return MEMIF_ERR_INVAL_ARG;
2207   if ((buf_a == NULL) || (buf_b == NULL))
2208     return MEMIF_ERR_INVAL_ARG;
2209
2210   int err;
2211   /* store buf_a information */
2212   uint16_t index_a = buf_a->desc_index;
2213   memif_queue_t *mq_a = buf_a->queue;
2214
2215   /* swap buffers, buf_a was updated with new desc_index and queue */
2216   memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
2217                                     (memif_queue_t *) buf_b->queue, buf_a,
2218                                     buf_b->desc_index);
2219
2220   /* update buf_b desc_index and queue */
2221   buf_b->desc_index = index_a;
2222   buf_b->queue = mq_a;
2223
2224   return MEMIF_ERR_SUCCESS;
2225 }
2226
2227 int
2228 memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
2229                      memif_buffer_t * bufs, uint16_t count,
2230                      uint16_t * count_out)
2231 {
2232   memif_connection_t *c = (memif_connection_t *) conn;
2233   if (EXPECT_FALSE (c == NULL))
2234     return MEMIF_ERR_NOCONN;
2235   if (EXPECT_FALSE (c->fd < 0))
2236     return MEMIF_ERR_DISCONNECTED;
2237   if (EXPECT_FALSE (qid >= c->tx_queues_num))
2238     return MEMIF_ERR_QID;
2239   if (EXPECT_FALSE (!count_out))
2240     return MEMIF_ERR_INVAL_ARG;
2241   if (EXPECT_FALSE (c->args.is_master))
2242     return MEMIF_ERR_INVAL_ARG;
2243
2244   memif_queue_t *mq = &c->tx_queues[qid];
2245   memif_ring_t *ring = mq->ring;
2246   memif_buffer_t *b0;
2247   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2248   uint16_t ring_size;
2249   uint16_t ns;
2250   memif_queue_t *bmq;
2251   int err = MEMIF_ERR_SUCCESS;  /* 0 */
2252   *count_out = 0;
2253
2254   ring_size = (1 << mq->log2_ring_size);
2255
2256   /* can only be called by slave */
2257   ns = ring_size - mq->next_buf + ring->tail;
2258
2259   b0 = bufs;
2260
2261   while (count && ns)
2262     {
2263       /* Swaps the descriptors, updates next_buf pointer and updates client
2264        * memif buffer */
2265
2266       memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
2267                                         mq->next_buf);
2268
2269       mq->next_buf++; /* mark the buffer as allocated */
2270       count--;
2271       ns--;
2272       b0++;
2273       *count_out += 1;
2274     }
2275
2276   DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2277        mq->next_buf);
2278
2279   if (count)
2280     {
2281       DBG ("ring buffer full! qid: %u", qid);
2282       err = MEMIF_ERR_NOBUF_RING;
2283     }
2284
2285   return err;
2286 }
2287
2288 int
2289 memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
2290                     memif_buffer_t * bufs, uint16_t count,
2291                     uint16_t * count_out, uint16_t size)
2292 {
2293   memif_connection_t *c = (memif_connection_t *) conn;
2294   if (EXPECT_FALSE (c == NULL))
2295     return MEMIF_ERR_NOCONN;
2296   if (EXPECT_FALSE (c->fd < 0))
2297     return MEMIF_ERR_DISCONNECTED;
2298   uint8_t num =
2299     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2300     run_args.num_s2m_rings;
2301   if (EXPECT_FALSE (qid >= num))
2302     return MEMIF_ERR_QID;
2303   if (EXPECT_FALSE (!count_out))
2304     return MEMIF_ERR_INVAL_ARG;
2305
2306   libmemif_main_t *lm = get_libmemif_main (c->args.socket);
2307   memif_queue_t *mq = &c->tx_queues[qid];
2308   memif_ring_t *ring = mq->ring;
2309   memif_buffer_t *b0;
2310   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2311   uint32_t offset_mask = c->run_args.buffer_size - 1;
2312   uint16_t ring_size;
2313   uint16_t ns;
2314   int err = MEMIF_ERR_SUCCESS;  /* 0 */
2315   uint16_t dst_left, src_left;
2316   uint16_t saved_count;
2317   uint16_t saved_next_buf;
2318   memif_buffer_t *saved_b;
2319   *count_out = 0;
2320
2321   ring_size = (1 << mq->log2_ring_size);
2322
2323   if (c->args.is_master)
2324     ns = ring->head - mq->next_buf;
2325   else
2326     ns = ring_size - mq->next_buf + ring->tail;
2327
2328   while (count && ns)
2329     {
2330       b0 = (bufs + *count_out);
2331
2332       saved_b = b0;
2333       saved_count = count;
2334       saved_next_buf = mq->next_buf;
2335
2336       b0->desc_index = mq->next_buf;
2337       ring->desc[mq->next_buf & mask].flags = 0;
2338
2339       /* slave can produce buffer with original length */
2340       dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
2341                                        c->run_args.buffer_size;
2342       src_left = size;
2343
2344       while (src_left)
2345         {
2346           if (EXPECT_FALSE (dst_left == 0))
2347             {
2348               if (count && ns)
2349                 {
2350                   *count_out += 1;
2351                   mq->next_buf++;
2352                   ns--;
2353
2354                   ring->desc[b0->desc_index & mask].flags |=
2355                     MEMIF_DESC_FLAG_NEXT;
2356                   b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
2357
2358                   b0 = (bufs + *count_out);
2359                   b0->desc_index = mq->next_buf;
2360                   dst_left = (c->args.is_master) ?
2361                                ring->desc[mq->next_buf & mask].length :
2362                                c->run_args.buffer_size;
2363                   ring->desc[mq->next_buf & mask].flags = 0;
2364                 }
2365               else
2366                 {
2367                   /* rollback allocated chain buffers */
2368                   memset (saved_b, 0, sizeof (memif_buffer_t)
2369                           * (saved_count - count + 1));
2370                   *count_out -= saved_count - count;
2371                   mq->next_buf = saved_next_buf;
2372                   goto no_ns;
2373                 }
2374             }
2375           b0->len = memif_min (dst_left, src_left);
2376
2377           /* slave resets buffer offset */
2378           if (c->args.is_master == 0)
2379             {
2380               memif_desc_t *d = &ring->desc[mq->next_buf & mask];
2381               if (lm->get_external_buffer_offset)
2382                 d->offset = lm->get_external_buffer_offset (c->private_ctx);
2383               else
2384                 d->offset = d->offset - (d->offset & offset_mask);
2385             }
2386           b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
2387
2388           src_left -= b0->len;
2389           dst_left -= b0->len;
2390         }
2391
2392       *count_out += 1;
2393       mq->next_buf++;
2394       ns--;
2395       count--;
2396     }
2397
2398 no_ns:
2399
2400   DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2401        mq->next_buf);
2402
2403   if (count)
2404     {
2405       DBG ("ring buffer full! qid: %u", qid);
2406       err = MEMIF_ERR_NOBUF_RING;
2407     }
2408
2409   return err;
2410 }
2411
2412 int
2413 memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
2414                     uint16_t headroom)
2415 {
2416   memif_connection_t *c = (memif_connection_t *) conn;
2417   if (EXPECT_FALSE (c == NULL))
2418     return MEMIF_ERR_NOCONN;
2419   if (EXPECT_FALSE (c->fd < 0))
2420     return MEMIF_ERR_DISCONNECTED;
2421   uint8_t num =
2422     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2423     run_args.num_m2s_rings;
2424   if (EXPECT_FALSE (qid >= num))
2425     return MEMIF_ERR_QID;
2426   libmemif_main_t *lm = get_libmemif_main (c->args.socket);
2427   memif_queue_t *mq = &c->rx_queues[qid];
2428   memif_ring_t *ring = mq->ring;
2429   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2430   uint32_t offset_mask = c->run_args.buffer_size - 1;
2431   uint16_t slot, counter = 0;
2432
2433   if (c->args.is_master)
2434     {
2435       MEMIF_MEMORY_BARRIER ();
2436       ring->tail =
2437         (ring->tail + count <=
2438          mq->last_head) ? ring->tail + count : mq->last_head;
2439       return MEMIF_ERR_SUCCESS;
2440     }
2441
2442   uint16_t head = ring->head;
2443   slot = head;
2444   uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
2445   count = (count < ns) ? count : ns;
2446
2447   memif_desc_t *d;
2448   while (counter < count)
2449     {
2450       d = &ring->desc[slot & mask];
2451       d->region = 1;
2452       d->length = c->run_args.buffer_size - headroom;
2453       if (lm->get_external_buffer_offset)
2454         d->offset = lm->get_external_buffer_offset (c->private_ctx);
2455       else
2456         d->offset = d->offset - (d->offset & offset_mask) + headroom;
2457       slot++;
2458       counter++;
2459     }
2460
2461   MEMIF_MEMORY_BARRIER ();
2462   ring->head = slot;
2463
2464   return MEMIF_ERR_SUCCESS;     /* 0 */
2465 }
2466
2467 int
2468 memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
2469                 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
2470 {
2471   memif_connection_t *c = (memif_connection_t *) conn;
2472   if (EXPECT_FALSE (c == NULL))
2473     return MEMIF_ERR_NOCONN;
2474   if (EXPECT_FALSE (c->fd < 0))
2475     return MEMIF_ERR_DISCONNECTED;
2476   uint8_t num =
2477     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2478     run_args.num_s2m_rings;
2479   if (EXPECT_FALSE (qid >= num))
2480     return MEMIF_ERR_QID;
2481   if (EXPECT_FALSE (!tx))
2482     return MEMIF_ERR_INVAL_ARG;
2483
2484   memif_queue_t *mq = &c->tx_queues[qid];
2485   memif_ring_t *ring = mq->ring;
2486   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2487   uint32_t offset_mask = c->run_args.buffer_size - 1;
2488   memif_buffer_t *b0;
2489   memif_desc_t *d;
2490   int64_t data_offset;
2491   *tx = 0;
2492   int err = MEMIF_ERR_SUCCESS;
2493
2494   if (EXPECT_FALSE (count == 0))
2495     return MEMIF_ERR_SUCCESS;
2496
2497   uint16_t index;
2498   if (c->args.is_master)
2499     index = ring->tail;
2500   else
2501     index = ring->head;
2502
2503   while (count)
2504     {
2505       b0 = (bufs + *tx);
2506       /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
2507        */
2508       if ((b0->desc_index & mask) != (index & mask))
2509         {
2510           err = MEMIF_ERR_INVAL_ARG;
2511           goto done;
2512         }
2513       d = &ring->desc[b0->desc_index & mask];
2514       d->length = b0->len;
2515       if (!c->args.is_master)
2516         {
2517           // reset headroom
2518           d->offset = d->offset - (d->offset & offset_mask);
2519           // calculate offset from user data
2520           data_offset = b0->data - (d->offset + c->regions[d->region].addr);
2521           if (data_offset != 0)
2522             {
2523               /* verify data offset */
2524               if ((data_offset < 0) ||
2525                   (data_offset > (d->offset + offset_mask)))
2526                 {
2527                   printf ("%ld\n", data_offset);
2528                   err = MEMIF_ERR_INVAL_ARG;
2529                   goto done;
2530                 }
2531               d->offset += data_offset;
2532             }
2533         }
2534
2535 #ifdef MEMIF_DBG_SHM
2536       printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
2537       printf ("data: %p\n",
2538               memif_get_buffer (c, ring, b0->desc_index & mask));
2539       printf ("index: %u\n", b0->desc_index);
2540       print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
2541                    ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
2542 #endif /* MEMIF_DBG_SHM */
2543
2544       *tx += 1;
2545       count--;
2546       index++;
2547     }
2548
2549 done:
2550   MEMIF_MEMORY_BARRIER ();
2551   if (c->args.is_master)
2552     ring->tail = b0->desc_index + 1;
2553   else
2554     ring->head = b0->desc_index + 1;
2555
2556   if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
2557     {
2558       uint64_t a = 1;
2559       int r = write (mq->int_fd, &a, sizeof (a));
2560       if (r < 0)
2561         return MEMIF_ERR_INT_WRITE;
2562     }
2563
2564   return err;
2565 }
2566
2567 int
2568 memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
2569                 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
2570 {
2571   memif_connection_t *c = (memif_connection_t *) conn;
2572   if (EXPECT_FALSE (c == NULL))
2573     return MEMIF_ERR_NOCONN;
2574   if (EXPECT_FALSE (c->fd < 0))
2575     return MEMIF_ERR_DISCONNECTED;
2576   uint8_t num =
2577     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2578     run_args.num_m2s_rings;
2579   if (EXPECT_FALSE (qid >= num))
2580     return MEMIF_ERR_QID;
2581   if (EXPECT_FALSE (!rx))
2582     return MEMIF_ERR_INVAL_ARG;
2583
2584   memif_queue_t *mq = &c->rx_queues[qid];
2585   memif_ring_t *ring = mq->ring;
2586   uint16_t cur_slot, last_slot;
2587   uint16_t ns;
2588   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2589   memif_buffer_t *b0;
2590   *rx = 0;
2591
2592   uint64_t b;
2593   ssize_t r;
2594
2595   cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
2596   last_slot = (c->args.is_master) ? ring->head : ring->tail;
2597   if (cur_slot == last_slot)
2598     {
2599       r = read (mq->int_fd, &b, sizeof (b));
2600       if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2601                         return memif_syscall_error_handler (errno);
2602
2603       return MEMIF_ERR_SUCCESS;
2604     }
2605
2606   ns = last_slot - cur_slot;
2607
2608   while (ns && count)
2609     {
2610       b0 = (bufs + *rx);
2611
2612       b0->desc_index = cur_slot;
2613       b0->data = memif_get_buffer (c, ring, cur_slot & mask);
2614       b0->len = ring->desc[cur_slot & mask].length;
2615       /* slave resets buffer length */
2616       if (c->args.is_master == 0)
2617         {
2618           ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
2619         }
2620
2621       if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
2622         {
2623           b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
2624           ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
2625         }
2626
2627       b0->queue = mq;
2628 #ifdef MEMIF_DBG_SHM
2629       printf ("data: %p\n", b0->data);
2630       printf ("index: %u\n", b0->desc_index);
2631       printf ("queue: %p\n", b0->queue);
2632       print_bytes (b0->data, b0->len, DBG_RX_BUF);
2633 #endif /* MEMIF_DBG_SHM */
2634       ns--;
2635       *rx += 1;
2636
2637       count--;
2638       cur_slot++;
2639     }
2640
2641   if (c->args.is_master)
2642     mq->last_head = cur_slot;
2643   else
2644     mq->last_tail = cur_slot;
2645
2646   if (ns)
2647     {
2648       DBG ("not enough buffers!");
2649       return MEMIF_ERR_NOBUF;
2650     }
2651
2652   r = read (mq->int_fd, &b, sizeof (b));
2653   if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2654     return memif_syscall_error_handler (errno);
2655
2656   return MEMIF_ERR_SUCCESS;     /* 0 */
2657 }
2658
2659 int
2660 memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
2661                    char *buf, ssize_t buflen)
2662 {
2663   memif_connection_t *c = (memif_connection_t *) conn;
2664   libmemif_main_t *lm;
2665   memif_socket_t *ms;
2666   int err = MEMIF_ERR_SUCCESS, i;
2667   ssize_t l0 = 0, l1;
2668
2669   if (c == NULL)
2670     return MEMIF_ERR_NOCONN;
2671
2672   ms = (memif_socket_t *) c->args.socket;
2673   lm = get_libmemif_main (ms);
2674
2675   l1 = strlen ((char *) c->args.interface_name);
2676   if (l0 + l1 < buflen)
2677     {
2678       md->if_name =
2679         (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
2680       l0 += l1 + 1;
2681     }
2682   else
2683     err = MEMIF_ERR_NOBUF_DET;
2684
2685   l1 = strlen ((char *) lm->app_name);
2686   if (l0 + l1 < buflen)
2687     {
2688       md->inst_name = (uint8_t *) strcpy (buf + l0, (char *) lm->app_name);
2689       l0 += l1 + 1;
2690     }
2691   else
2692     err = MEMIF_ERR_NOBUF_DET;
2693
2694   l1 = strlen ((char *) c->remote_if_name);
2695   if (l0 + l1 < buflen)
2696     {
2697       md->remote_if_name =
2698         (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
2699       l0 += l1 + 1;
2700     }
2701   else
2702     err = MEMIF_ERR_NOBUF_DET;
2703
2704   l1 = strlen ((char *) c->remote_name);
2705   if (l0 + l1 < buflen)
2706     {
2707       md->remote_inst_name =
2708         (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
2709       l0 += l1 + 1;
2710     }
2711   else
2712     err = MEMIF_ERR_NOBUF_DET;
2713
2714   md->id = c->args.interface_id;
2715
2716   if (strlen ((char *) c->args.secret) > 0)
2717     {
2718       l1 = strlen ((char *) c->args.secret);
2719       if (l0 + l1 < buflen)
2720         {
2721           md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
2722           l0 += l1 + 1;
2723         }
2724       else
2725         err = MEMIF_ERR_NOBUF_DET;
2726     }
2727
2728   md->role = (c->args.is_master) ? 0 : 1;
2729   md->mode = c->args.mode;
2730
2731   l1 = strlen ((char *) ms->filename);
2732   if (l0 + l1 < buflen)
2733     {
2734       md->socket_filename =
2735         (uint8_t *) strcpy (buf + l0, (char *) ms->filename);
2736       l0 += l1 + 1;
2737     }
2738   else
2739     err = MEMIF_ERR_NOBUF_DET;
2740
2741   l1 = strlen ((char *) c->remote_disconnect_string);
2742   if (l0 + l1 < buflen)
2743     {
2744       md->error =
2745         (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
2746       l0 += l1 + 1;
2747     }
2748   else
2749     err = MEMIF_ERR_NOBUF_DET;
2750
2751   md->regions_num = c->regions_num;
2752   l1 = sizeof (memif_region_details_t) * md->regions_num;
2753   if (l0 + l1 <= buflen)
2754     {
2755       md->regions = (memif_region_details_t *) (buf + l0);
2756       for (i = 0; i < md->regions_num; i++)
2757         {
2758           md->regions[i].index = i;
2759           md->regions[i].addr = c->regions[i].addr;
2760           md->regions[i].size = c->regions[i].region_size;
2761           md->regions[i].fd = c->regions[i].fd;
2762           md->regions[i].is_external = c->regions[i].is_external;
2763         }
2764       l0 += l1;
2765     }
2766   else
2767     err = MEMIF_ERR_NOBUF_DET;
2768
2769   md->rx_queues_num =
2770     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2771     run_args.num_m2s_rings;
2772
2773   l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2774   if (l0 + l1 <= buflen)
2775     {
2776       md->rx_queues = (memif_queue_details_t *) (buf + l0);
2777       for (i = 0; i < md->rx_queues_num; i++)
2778         {
2779           md->rx_queues[i].region = c->rx_queues[i].region;
2780           md->rx_queues[i].qid = i;
2781           md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2782           md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2783           md->rx_queues[i].head = c->rx_queues[i].ring->head;
2784           md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2785           md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2786         }
2787       l0 += l1;
2788     }
2789   else
2790     err = MEMIF_ERR_NOBUF_DET;
2791
2792   md->tx_queues_num =
2793     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2794     run_args.num_s2m_rings;
2795
2796   l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2797   if (l0 + l1 <= buflen)
2798     {
2799       md->tx_queues = (memif_queue_details_t *) (buf + l0);
2800       for (i = 0; i < md->tx_queues_num; i++)
2801         {
2802           md->tx_queues[i].region = c->tx_queues[i].region;
2803           md->tx_queues[i].qid = i;
2804           md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2805           md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2806           md->tx_queues[i].head = c->tx_queues[i].ring->head;
2807           md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2808           md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2809         }
2810       l0 += l1;
2811     }
2812   else
2813     err = MEMIF_ERR_NOBUF_DET;
2814
2815   md->link_up_down = (c->fd > 0) ? 1 : 0;
2816
2817   return err;                   /* 0 */
2818 }
2819
2820 int
2821 memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2822 {
2823   memif_connection_t *c = (memif_connection_t *) conn;
2824   uint8_t num;
2825
2826   *efd = -1;
2827   if (c == NULL)
2828     return MEMIF_ERR_NOCONN;
2829   if (c->fd < 0)
2830     return MEMIF_ERR_DISCONNECTED;
2831
2832   num =
2833     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2834     run_args.num_m2s_rings;
2835   if (qid >= num)
2836     return MEMIF_ERR_QID;
2837
2838   *efd = c->rx_queues[qid].int_fd;
2839
2840   return MEMIF_ERR_SUCCESS;
2841 }
2842
2843 int
2844 memif_cleanup ()
2845 {
2846   libmemif_main_t *lm = &libmemif_main;
2847   int err;
2848
2849   err = memif_delete_socket ((memif_socket_handle_t *) & lm->default_socket);
2850   if (err != MEMIF_ERR_SUCCESS)
2851     return err;
2852
2853   if (lm->control_list)
2854     lm->free (lm->control_list);
2855   lm->control_list = NULL;
2856   if (lm->interrupt_list)
2857     lm->free (lm->interrupt_list);
2858   lm->interrupt_list = NULL;
2859   if (lm->socket_list)
2860     lm->free (lm->socket_list);
2861   lm->socket_list = NULL;
2862   if (lm->pending_list)
2863     lm->free (lm->pending_list);
2864   lm->pending_list = NULL;
2865   if (lm->poll_cancel_fd != -1)
2866     close (lm->poll_cancel_fd);
2867
2868   return MEMIF_ERR_SUCCESS;     /* 0 */
2869 }
2870
2871 int
2872 memif_per_thread_cleanup (memif_per_thread_main_handle_t * pt_main)
2873 {
2874   libmemif_main_t *lm = (libmemif_main_t *) * pt_main;
2875
2876   if (lm == NULL)
2877     return MEMIF_ERR_INVAL_ARG;
2878
2879   /* No default socket in case of per thread */
2880
2881   if (lm->control_list)
2882     lm->free (lm->control_list);
2883   lm->control_list = NULL;
2884   if (lm->interrupt_list)
2885     lm->free (lm->interrupt_list);
2886   lm->interrupt_list = NULL;
2887   if (lm->socket_list)
2888     lm->free (lm->socket_list);
2889   lm->socket_list = NULL;
2890   if (lm->pending_list)
2891     lm->free (lm->pending_list);
2892   lm->pending_list = NULL;
2893   if (lm->poll_cancel_fd != -1)
2894     close (lm->poll_cancel_fd);
2895
2896   lm->free (lm);
2897
2898   *pt_main = NULL;
2899
2900   return MEMIF_ERR_SUCCESS;     /* 0 */
2901 }