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