e70334ae40f8f61361fd2bf25d8f34dce0396a51
[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   memset (ms->filename, 0, sizeof (ms->filename));
952   strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
953
954   ms->type = MEMIF_SOCKET_TYPE_NONE;
955
956   ms->interface_list_len = 1;
957   ms->interface_list =
958     lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
959   if (ms->interface_list == NULL)
960     {
961       err = MEMIF_ERR_NOMEM;
962       goto error;
963     }
964   ms->interface_list[0].key = -1;
965   ms->interface_list[0].data_struct = NULL;
966
967   *sock = ms;
968
969   return err;
970
971 error:
972   if (ms != NULL)
973     {
974       if (ms->fd > 0)
975         {
976           close (ms->fd);
977           ms->fd = -1;
978         }
979       if (ms->interface_list != NULL)
980         {
981           lm->free (ms->interface_list);
982           ms->interface_list = NULL;
983           ms->interface_list_len = 0;
984         }
985       lm->free (ms);
986       *sock = ms = NULL;
987     }
988   return err;
989 }
990
991 int
992 memif_per_thread_create_socket (memif_per_thread_main_handle_t pt_main,
993                                 memif_socket_handle_t * sock,
994                                 const char *filename, void *private_ctx)
995 {
996   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
997   memif_socket_t *ms = (memif_socket_t *) * sock;
998   int i, err = MEMIF_ERR_SUCCESS;
999
1000   if (lm == NULL)
1001     return MEMIF_ERR_INVAL_ARG;
1002
1003   for (i = 0; i < lm->socket_list_len; i++)
1004     {
1005       if ((ms = (memif_socket_t *) lm->socket_list[i].data_struct) != NULL)
1006         {
1007           if (strncmp ((char *) ms->filename, filename,
1008                        strlen ((char *) ms->filename)) == 0)
1009             return MEMIF_ERR_INVAL_ARG;
1010         }
1011     }
1012
1013   /* allocate memif_socket_t */
1014   ms = NULL;
1015   ms = lm->alloc (sizeof (memif_socket_t));
1016   if (ms == NULL)
1017     {
1018       err = MEMIF_ERR_NOMEM;
1019       goto error;
1020     }
1021   memset (ms, 0, sizeof (memif_socket_t));
1022   ms->lm = lm;
1023   /* set filename */
1024   memset (ms->filename, 0, sizeof (ms->filename));
1025   strlcpy ((char *) ms->filename, filename, sizeof (ms->filename));
1026
1027   ms->type = MEMIF_SOCKET_TYPE_NONE;
1028
1029   ms->interface_list_len = 1;
1030   ms->interface_list =
1031     lm->alloc (sizeof (memif_list_elt_t) * ms->interface_list_len);
1032   if (ms->interface_list == NULL)
1033     {
1034       err = MEMIF_ERR_NOMEM;
1035       goto error;
1036     }
1037   ms->interface_list[0].key = -1;
1038   ms->interface_list[0].data_struct = NULL;
1039
1040   *sock = ms;
1041
1042   return err;
1043
1044 error:
1045   if (ms != NULL)
1046     {
1047       if (ms->fd > 0)
1048         {
1049           close (ms->fd);
1050           ms->fd = -1;
1051         }
1052       if (ms->interface_list != NULL)
1053         {
1054           lm->free (ms->interface_list);
1055           ms->interface_list = NULL;
1056           ms->interface_list_len = 0;
1057         }
1058       lm->free (ms);
1059       *sock = ms = NULL;
1060     }
1061   return err;
1062 }
1063
1064 int
1065 memif_create (memif_conn_handle_t * c, memif_conn_args_t * args,
1066               memif_connection_update_t * on_connect,
1067               memif_connection_update_t * on_disconnect,
1068               memif_interrupt_t * on_interrupt, void *private_ctx)
1069 {
1070   libmemif_main_t *lm = get_libmemif_main (args->socket);
1071   int err, index = 0;
1072   memif_list_elt_t elt;
1073   memif_connection_t *conn = (memif_connection_t *) * c;
1074   memif_socket_t *ms;
1075
1076   if (conn != NULL)
1077     {
1078       DBG ("This handle already points to existing memif.");
1079       return MEMIF_ERR_CONN;
1080     }
1081
1082   conn = (memif_connection_t *) lm->alloc (sizeof (memif_connection_t));
1083   if (conn == NULL)
1084     {
1085       err = MEMIF_ERR_NOMEM;
1086       goto error;
1087     }
1088   memset (conn, 0, sizeof (memif_connection_t));
1089
1090   conn->args.interface_id = args->interface_id;
1091
1092   if (args->log2_ring_size == 0)
1093     args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
1094   else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
1095     {
1096       err = MEMIF_ERR_MAX_RING;
1097       goto error;
1098     }
1099   if (args->buffer_size == 0)
1100     args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
1101   if (args->num_s2m_rings == 0)
1102     args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
1103   if (args->num_m2s_rings == 0)
1104     args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
1105
1106   conn->args.num_s2m_rings = args->num_s2m_rings;
1107   conn->args.num_m2s_rings = args->num_m2s_rings;
1108   conn->args.buffer_size = args->buffer_size;
1109   conn->args.log2_ring_size = args->log2_ring_size;
1110   conn->args.is_master = args->is_master;
1111   conn->args.mode = args->mode;
1112   conn->msg_queue = NULL;
1113   conn->regions = NULL;
1114   conn->tx_queues = NULL;
1115   conn->rx_queues = NULL;
1116   conn->fd = -1;
1117   conn->on_connect = on_connect;
1118   conn->on_disconnect = on_disconnect;
1119   conn->on_interrupt = on_interrupt;
1120   conn->private_ctx = private_ctx;
1121   memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
1122
1123   strlcpy ((char *) conn->args.interface_name, (char *) args->interface_name,
1124            sizeof (conn->args.interface_name));
1125
1126   if ((strlen ((char *) args->secret)) > 0)
1127     strlcpy ((char *) conn->args.secret, (char *) args->secret,
1128              sizeof (conn->args.secret));
1129
1130   if (args->socket != NULL)
1131     conn->args.socket = args->socket;
1132   else if (lm->default_socket != NULL)
1133     conn->args.socket = lm->default_socket;
1134   else
1135     {
1136       err = MEMIF_ERR_INVAL_ARG;
1137       goto error;
1138     }
1139
1140   ms = (memif_socket_t *) conn->args.socket;
1141
1142   if ((conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_CLIENT) ||
1143       (!conn->args.is_master && ms->type == MEMIF_SOCKET_TYPE_LISTENER))
1144     {
1145       err = MEMIF_ERR_INVAL_ARG;
1146       goto error;
1147     }
1148
1149   elt.key = conn->args.interface_id;
1150   elt.data_struct = conn;
1151   add_list_elt (lm, &elt, &ms->interface_list, &ms->interface_list_len);
1152   ms->use_count++;
1153
1154   if (conn->args.is_master)
1155     {
1156       if (ms->type == MEMIF_SOCKET_TYPE_NONE)
1157         {
1158           err = memif_socket_start_listening (ms);
1159           if (err != MEMIF_ERR_SUCCESS)
1160             goto error;
1161         }
1162     }
1163   else
1164     {
1165       elt.key = -1;
1166       elt.data_struct = conn;
1167       if ((index =
1168            add_list_elt (lm, &elt, &lm->control_list,
1169                          &lm->control_list_len)) < 0)
1170         {
1171           err = MEMIF_ERR_NOMEM;
1172           goto error;
1173         }
1174
1175       conn->index = index;
1176
1177       /* try connecting to master */
1178       err = memif_request_connection (conn);
1179       if ((err != MEMIF_ERR_SUCCESS) && (lm->disconn_slaves == 0))
1180         {
1181           /* connection failed, arm reconnect timer (if not armed) */
1182           if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1183             {
1184               err = memif_syscall_error_handler (errno);
1185               goto error;
1186             }
1187         }
1188       lm->disconn_slaves++;
1189     }
1190
1191   *c = conn;
1192
1193   return 0;
1194
1195 error:
1196   if (conn != NULL)
1197     lm->free (conn);
1198   *c = conn = NULL;
1199   return err;
1200 }
1201
1202 int
1203 memif_request_connection (memif_conn_handle_t c)
1204 {
1205   memif_connection_t *conn = (memif_connection_t *) c;
1206   libmemif_main_t *lm;
1207   memif_socket_t *ms;
1208   int err = MEMIF_ERR_SUCCESS;
1209   int sockfd = -1;
1210   struct sockaddr_un sun;
1211
1212   if (conn == NULL)
1213     return MEMIF_ERR_NOCONN;
1214
1215   ms = (memif_socket_t *) conn->args.socket;
1216   lm = get_libmemif_main (ms);
1217
1218
1219   if (conn->args.is_master || ms->type == MEMIF_SOCKET_TYPE_LISTENER)
1220     return MEMIF_ERR_INVAL_ARG;
1221   if (conn->fd > 0)
1222     return MEMIF_ERR_ALRCONN;
1223
1224   sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
1225   if (sockfd < 0)
1226     {
1227       err = memif_syscall_error_handler (errno);
1228       goto error;
1229     }
1230
1231   sun.sun_family = AF_UNIX;
1232
1233   strlcpy (sun.sun_path, (char *) ms->filename, sizeof (sun.sun_path));
1234
1235   if (connect (sockfd, (struct sockaddr *) &sun,
1236                sizeof (struct sockaddr_un)) == 0)
1237     {
1238       conn->fd = sockfd;
1239       conn->read_fn = memif_conn_fd_read_ready;
1240       conn->write_fn = memif_conn_fd_write_ready;
1241       conn->error_fn = memif_conn_fd_error;
1242
1243       lm->control_list[conn->index].key = conn->fd;
1244       lm->control_fd_update (sockfd,
1245                              MEMIF_FD_EVENT_READ |
1246                              MEMIF_FD_EVENT_WRITE, lm->private_ctx);
1247
1248       lm->disconn_slaves--;
1249       if (lm->disconn_slaves == 0)
1250         {
1251           if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1252             {
1253               err = memif_syscall_error_handler (errno);
1254               return err;
1255             }
1256         }
1257     }
1258   else
1259     {
1260       err = memif_syscall_error_handler (errno);
1261       strcpy ((char *) conn->remote_disconnect_string, memif_strerror (err));
1262       goto error;
1263     }
1264
1265   ms->type = MEMIF_SOCKET_TYPE_CLIENT;
1266
1267   return err;
1268
1269 error:
1270   if (sockfd > 0)
1271     close (sockfd);
1272   sockfd = -1;
1273   return err;
1274 }
1275
1276 int
1277 memif_control_fd_handler (int fd, uint8_t events)
1278 {
1279   int i, err = MEMIF_ERR_SUCCESS;       /* 0 */
1280   uint16_t num;
1281   memif_list_elt_t *e = NULL;
1282   memif_connection_t *conn;
1283   libmemif_main_t *lm = &libmemif_main;
1284   if (fd == lm->timerfd)
1285     {
1286       uint64_t b;
1287       ssize_t size;
1288       size = read (fd, &b, sizeof (b));
1289
1290       if (size == -1)
1291         goto error;
1292
1293       for (i = 0; i < lm->control_list_len; i++)
1294         {
1295           if ((lm->control_list[i].key < 0)
1296               && (lm->control_list[i].data_struct != NULL))
1297             {
1298               conn = lm->control_list[i].data_struct;
1299               if (conn->args.is_master)
1300                 continue;
1301               err = memif_request_connection (conn);
1302               if (err != MEMIF_ERR_SUCCESS)
1303                 DBG ("memif_request_connection: %s", memif_strerror (err));
1304             }
1305         }
1306     }
1307   else
1308     {
1309       get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1310       if (e != NULL)
1311         {
1312           if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1313             {
1314               num =
1315                 (((memif_connection_t *) e->data_struct)->
1316                  args.is_master) ? ((memif_connection_t *) e->
1317                                     data_struct)->run_args.
1318                 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1319                 run_args.num_m2s_rings;
1320               for (i = 0; i < num; i++)
1321                 {
1322                   if (((memif_connection_t *) e->data_struct)->
1323                       rx_queues[i].int_fd == fd)
1324                     {
1325                       ((memif_connection_t *) e->data_struct)->
1326                         on_interrupt ((void *) e->data_struct,
1327                                       ((memif_connection_t *) e->
1328                                        data_struct)->private_ctx, i);
1329                       return MEMIF_ERR_SUCCESS;
1330                     }
1331                 }
1332             }
1333           return MEMIF_ERR_SUCCESS;
1334         }
1335       get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1336       if (e != NULL
1337           && ((memif_socket_t *) e->data_struct)->type ==
1338           MEMIF_SOCKET_TYPE_LISTENER)
1339         {
1340           err =
1341             memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
1342           return err;
1343         }
1344
1345       get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1346       if (e != NULL)
1347         {
1348           err = memif_read_ready (lm, fd);
1349           return err;
1350         }
1351
1352       get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1353       if (e != NULL)
1354         {
1355           if (events & MEMIF_FD_EVENT_READ)
1356             {
1357               err =
1358                 ((memif_connection_t *) e->data_struct)->
1359                 read_fn (e->data_struct);
1360               if (err != MEMIF_ERR_SUCCESS)
1361                 return err;
1362             }
1363           if (events & MEMIF_FD_EVENT_WRITE)
1364             {
1365               err =
1366                 ((memif_connection_t *) e->data_struct)->
1367                 write_fn (e->data_struct);
1368               if (err != MEMIF_ERR_SUCCESS)
1369                 return err;
1370             }
1371           if (events & MEMIF_FD_EVENT_ERROR)
1372             {
1373               err =
1374                 ((memif_connection_t *) e->data_struct)->
1375                 error_fn (e->data_struct);
1376               if (err != MEMIF_ERR_SUCCESS)
1377                 return err;
1378             }
1379         }
1380     }
1381
1382   return MEMIF_ERR_SUCCESS;     /* 0 */
1383
1384 error:
1385   return err;
1386 }
1387
1388 int
1389 memif_per_thread_control_fd_handler (memif_per_thread_main_handle_t pt_main,
1390                                      int fd, uint8_t events)
1391 {
1392   int i, err = MEMIF_ERR_SUCCESS;       /* 0 */
1393   uint16_t num;
1394   memif_list_elt_t *e = NULL;
1395   memif_connection_t *conn;
1396   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1397
1398   if (fd == lm->timerfd)
1399     {
1400       uint64_t b;
1401       ssize_t size;
1402       size = read (fd, &b, sizeof (b));
1403
1404       if (size == -1)
1405         goto error;
1406
1407       for (i = 0; i < lm->control_list_len; i++)
1408         {
1409           if ((lm->control_list[i].key < 0)
1410               && (lm->control_list[i].data_struct != NULL))
1411             {
1412               conn = lm->control_list[i].data_struct;
1413               if (conn->args.is_master)
1414                 continue;
1415               err = memif_request_connection (conn);
1416               if (err != MEMIF_ERR_SUCCESS)
1417                 DBG ("memif_request_connection: %s", memif_strerror (err));
1418             }
1419         }
1420     }
1421   else
1422     {
1423       get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1424       if (e != NULL)
1425         {
1426           if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1427             {
1428               num =
1429                 (((memif_connection_t *) e->data_struct)->
1430                  args.is_master) ? ((memif_connection_t *) e->
1431                                     data_struct)->run_args.
1432                 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1433                 run_args.num_m2s_rings;
1434               for (i = 0; i < num; i++)
1435                 {
1436                   if (((memif_connection_t *) e->data_struct)->
1437                       rx_queues[i].int_fd == fd)
1438                     {
1439                       ((memif_connection_t *) e->data_struct)->
1440                         on_interrupt ((void *) e->data_struct,
1441                                       ((memif_connection_t *) e->
1442                                        data_struct)->private_ctx, i);
1443                       return MEMIF_ERR_SUCCESS;
1444                     }
1445                 }
1446             }
1447           return MEMIF_ERR_SUCCESS;
1448         }
1449       get_list_elt (&e, lm->socket_list, lm->socket_list_len, fd);
1450       if (e != NULL
1451           && ((memif_socket_t *) e->data_struct)->type ==
1452           MEMIF_SOCKET_TYPE_LISTENER)
1453         {
1454           err =
1455             memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
1456           return err;
1457         }
1458
1459       get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1460       if (e != NULL)
1461         {
1462           err = memif_read_ready (lm, fd);
1463           return err;
1464         }
1465
1466       get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1467       if (e != NULL)
1468         {
1469           if (events & MEMIF_FD_EVENT_READ)
1470             {
1471               err =
1472                 ((memif_connection_t *) e->data_struct)->
1473                 read_fn (e->data_struct);
1474               if (err != MEMIF_ERR_SUCCESS)
1475                 return err;
1476             }
1477           if (events & MEMIF_FD_EVENT_WRITE)
1478             {
1479               err =
1480                 ((memif_connection_t *) e->data_struct)->
1481                 write_fn (e->data_struct);
1482               if (err != MEMIF_ERR_SUCCESS)
1483                 return err;
1484             }
1485           if (events & MEMIF_FD_EVENT_ERROR)
1486             {
1487               err =
1488                 ((memif_connection_t *) e->data_struct)->
1489                 error_fn (e->data_struct);
1490               if (err != MEMIF_ERR_SUCCESS)
1491                 return err;
1492             }
1493         }
1494     }
1495
1496   return MEMIF_ERR_SUCCESS;     /* 0 */
1497
1498 error:
1499   return err;
1500 }
1501
1502 int
1503 memif_poll_event (int timeout)
1504 {
1505   libmemif_main_t *lm = &libmemif_main;
1506   struct epoll_event evt;
1507   int en = 0, err = MEMIF_ERR_SUCCESS;  /* 0 */
1508   uint32_t events = 0;
1509   uint64_t counter = 0;
1510   ssize_t r = 0;
1511   memset (&evt, 0, sizeof (evt));
1512   evt.events = EPOLLIN | EPOLLOUT;
1513   sigset_t sigset;
1514   sigemptyset (&sigset);
1515   en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
1516   if (en < 0)
1517     {
1518       err = errno;
1519       DBG ("epoll_pwait: %s", strerror (err));
1520       return memif_syscall_error_handler (err);
1521     }
1522   if (en > 0)
1523     {
1524       if (evt.data.fd == lm->poll_cancel_fd)
1525         {
1526           r = read (evt.data.fd, &counter, sizeof (counter));
1527           if (r == -1)
1528             return MEMIF_ERR_DISCONNECTED;
1529
1530           return MEMIF_ERR_POLL_CANCEL;
1531         }
1532       if (evt.events & EPOLLIN)
1533         events |= MEMIF_FD_EVENT_READ;
1534       if (evt.events & EPOLLOUT)
1535         events |= MEMIF_FD_EVENT_WRITE;
1536       if (evt.events & EPOLLERR)
1537         events |= MEMIF_FD_EVENT_ERROR;
1538       err = memif_control_fd_handler (evt.data.fd, events);
1539       return err;
1540     }
1541   return 0;
1542 }
1543
1544 int
1545 memif_per_thread_poll_event (memif_per_thread_main_handle_t pt_main,
1546                              int timeout)
1547 {
1548   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1549   struct epoll_event evt;
1550   int en = 0, err = MEMIF_ERR_SUCCESS;  /* 0 */
1551   uint32_t events = 0;
1552   uint64_t counter = 0;
1553   ssize_t r = 0;
1554   memset (&evt, 0, sizeof (evt));
1555   evt.events = EPOLLIN | EPOLLOUT;
1556   sigset_t sigset;
1557   sigemptyset (&sigset);
1558   en = epoll_pwait (lm->epfd, &evt, 1, timeout, &sigset);
1559   if (en < 0)
1560     {
1561       err = errno;
1562       DBG ("epoll_pwait: %s", strerror (err));
1563       return memif_syscall_error_handler (err);
1564     }
1565   if (en > 0)
1566     {
1567       if (evt.data.fd == lm->poll_cancel_fd)
1568         {
1569           r = read (evt.data.fd, &counter, sizeof (counter));
1570           if (r == -1)
1571             return MEMIF_ERR_DISCONNECTED;
1572
1573           return MEMIF_ERR_POLL_CANCEL;
1574         }
1575       if (evt.events & EPOLLIN)
1576         events |= MEMIF_FD_EVENT_READ;
1577       if (evt.events & EPOLLOUT)
1578         events |= MEMIF_FD_EVENT_WRITE;
1579       if (evt.events & EPOLLERR)
1580         events |= MEMIF_FD_EVENT_ERROR;
1581       err = memif_control_fd_handler (evt.data.fd, events);
1582       return err;
1583     }
1584   return 0;
1585 }
1586
1587 int
1588 memif_cancel_poll_event ()
1589 {
1590   libmemif_main_t *lm = &libmemif_main;
1591   uint64_t counter = 1;
1592   ssize_t w = 0;
1593
1594   if (lm->poll_cancel_fd == -1)
1595     return 0;
1596   w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
1597   if (w < sizeof (counter))
1598     return MEMIF_ERR_INT_WRITE;
1599
1600   return 0;
1601 }
1602
1603 int
1604 memif_per_thread_cancel_poll_event (memif_per_thread_main_handle_t pt_main)
1605 {
1606   libmemif_main_t *lm = (libmemif_main_t *) pt_main;
1607   uint64_t counter = 1;
1608   ssize_t w = 0;
1609
1610   if (lm == NULL)
1611     return MEMIF_ERR_INVAL_ARG;
1612
1613   if (lm->poll_cancel_fd == -1)
1614     return 0;
1615   w = write (lm->poll_cancel_fd, &counter, sizeof (counter));
1616   if (w < sizeof (counter))
1617     return MEMIF_ERR_INT_WRITE;
1618
1619   return 0;
1620 }
1621
1622 static void
1623 memif_msg_queue_free (libmemif_main_t * lm, memif_msg_queue_elt_t ** e)
1624 {
1625   if (*e == NULL)
1626     return;
1627   memif_msg_queue_free (lm, &(*e)->next);
1628   lm->free (*e);
1629   *e = NULL;
1630   return;
1631 }
1632
1633 /* send disconnect msg and close interface */
1634 int
1635 memif_disconnect_internal (memif_connection_t * c)
1636 {
1637   int err = MEMIF_ERR_SUCCESS, i;       /* 0 */
1638   memif_queue_t *mq;
1639   libmemif_main_t *lm;
1640   memif_list_elt_t *e;
1641
1642   if (c == NULL)
1643     {
1644       DBG ("no connection");
1645       return MEMIF_ERR_NOCONN;
1646     }
1647
1648   lm = get_libmemif_main (c->args.socket);
1649
1650   c->on_disconnect ((void *) c, c->private_ctx);
1651
1652   if (c->fd > 0)
1653     {
1654       memif_msg_send_disconnect (c->fd, (uint8_t *) "interface deleted", 0);
1655       lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
1656       close (c->fd);
1657     }
1658   get_list_elt (&e, lm->control_list, lm->control_list_len, c->fd);
1659   if (e != NULL)
1660     {
1661       if (c->args.is_master)
1662         free_list_elt (lm->control_list, lm->control_list_len, c->fd);
1663       e->key = c->fd = -1;
1664     }
1665
1666   if (c->tx_queues != NULL)
1667     {
1668       for (i = 0; i < c->tx_queues_num; i++)
1669         {
1670           mq = &c->tx_queues[i];
1671           if (mq != NULL)
1672             {
1673               if (mq->int_fd > 0)
1674                 close (mq->int_fd);
1675               free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1676                              mq->int_fd);
1677               mq->int_fd = -1;
1678             }
1679         }
1680       lm->free (c->tx_queues);
1681       c->tx_queues = NULL;
1682     }
1683   c->tx_queues_num = 0;
1684
1685   if (c->rx_queues != NULL)
1686     {
1687       for (i = 0; i < c->rx_queues_num; i++)
1688         {
1689           mq = &c->rx_queues[i];
1690           if (mq != NULL)
1691             {
1692               if (mq->int_fd > 0)
1693                 {
1694                   if (c->on_interrupt != NULL)
1695                     lm->control_fd_update (mq->int_fd, MEMIF_FD_EVENT_DEL,
1696                                            lm->private_ctx);
1697                   close (mq->int_fd);
1698                 }
1699               free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1700                              mq->int_fd);
1701               mq->int_fd = -1;
1702             }
1703         }
1704       lm->free (c->rx_queues);
1705       c->rx_queues = NULL;
1706     }
1707   c->rx_queues_num = 0;
1708
1709   for (i = 0; i < c->regions_num; i++)
1710     {
1711       if (&c->regions[i] == NULL)
1712         continue;
1713       if (c->regions[i].is_external != 0)
1714         {
1715           lm->del_external_region (c->regions[i].addr,
1716                                    c->regions[i].region_size,
1717                                    c->regions[i].fd, c->private_ctx);
1718         }
1719       else
1720         {
1721           if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1722             return memif_syscall_error_handler (errno);
1723           if (c->regions[i].fd > 0)
1724             close (c->regions[i].fd);
1725           c->regions[i].fd = -1;
1726         }
1727     }
1728   lm->free (c->regions);
1729   c->regions = NULL;
1730   c->regions_num = 0;
1731
1732   memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1733
1734   memif_msg_queue_free (lm, &c->msg_queue);
1735
1736   if (!(c->args.is_master))
1737     {
1738       if (lm->disconn_slaves == 0)
1739         {
1740           if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1741             {
1742               err = memif_syscall_error_handler (errno);
1743               DBG ("timerfd_settime: arm");
1744             }
1745         }
1746       lm->disconn_slaves++;
1747     }
1748
1749   return err;
1750 }
1751
1752 const char *
1753 memif_get_socket_filename (memif_socket_handle_t sock)
1754 {
1755   memif_socket_t *ms = (memif_socket_t *) sock;
1756
1757   if (ms == NULL)
1758     return NULL;
1759
1760   return (char *) ms->filename;
1761 }
1762
1763 int
1764 memif_delete_socket (memif_socket_handle_t * sock)
1765 {
1766   memif_socket_t *ms = (memif_socket_t *) * sock;
1767   libmemif_main_t *lm;
1768
1769   /* check if socket is in use */
1770   if (ms == NULL || ms->use_count > 0)
1771     return MEMIF_ERR_INVAL_ARG;
1772
1773   lm = get_libmemif_main (ms);
1774
1775   lm->free (ms->interface_list);
1776   ms->interface_list = NULL;
1777   lm->free (ms);
1778   *sock = ms = NULL;
1779
1780   return MEMIF_ERR_SUCCESS;
1781 }
1782
1783 int
1784 memif_delete (memif_conn_handle_t * conn)
1785 {
1786   memif_connection_t *c = (memif_connection_t *) * conn;
1787   libmemif_main_t *lm;
1788   memif_socket_t *ms = NULL;
1789   int err = MEMIF_ERR_SUCCESS;
1790
1791   if (c == NULL)
1792     {
1793       DBG ("no connection");
1794       return MEMIF_ERR_NOCONN;
1795     }
1796
1797   if (c->fd > 0)
1798     {
1799       DBG ("DISCONNECTING");
1800       err = memif_disconnect_internal (c);
1801       if (err == MEMIF_ERR_NOCONN)
1802         return err;
1803     }
1804
1805   lm = get_libmemif_main (c->args.socket);
1806
1807   free_list_elt_ctx (lm->control_list, lm->control_list_len, c);
1808
1809   ms = (memif_socket_t *) c->args.socket;
1810   ms->use_count--;
1811   free_list_elt (ms->interface_list, ms->interface_list_len,
1812                  c->args.interface_id);
1813   if (ms->use_count <= 0)
1814     {
1815       /* stop listening on this socket */
1816       if (ms->type == MEMIF_SOCKET_TYPE_LISTENER)
1817         {
1818           lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_DEL, lm->private_ctx);
1819           free_list_elt (lm->socket_list, lm->socket_list_len, ms->fd);
1820           close (ms->fd);
1821           ms->fd = -1;
1822         }
1823       /* socket not in use */
1824       ms->type = MEMIF_SOCKET_TYPE_NONE;
1825     }
1826
1827   if (!c->args.is_master)
1828     {
1829       lm->disconn_slaves--;
1830       if (lm->disconn_slaves <= 0)
1831         {
1832           if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1833             {
1834               err = memif_syscall_error_handler (errno);
1835               DBG ("timerfd_settime: disarm");
1836             }
1837         }
1838     }
1839
1840   lm->free (c);
1841   c = NULL;
1842
1843   *conn = c;
1844   return err;
1845 }
1846
1847 int
1848 memif_connect1 (memif_connection_t * c)
1849 {
1850   libmemif_main_t *lm;
1851   memif_region_t *mr;
1852   memif_queue_t *mq;
1853   int i;
1854
1855   if (c == NULL)
1856     return MEMIF_ERR_INVAL_ARG;
1857
1858   lm = get_libmemif_main (c->args.socket);
1859
1860   for (i = 0; i < c->regions_num; i++)
1861     {
1862       mr = &c->regions[i];
1863       if (mr != NULL)
1864         {
1865           if (!mr->addr)
1866             {
1867               if (mr->is_external)
1868                 {
1869                   if (lm->get_external_region_addr == NULL)
1870                     return MEMIF_ERR_INVAL_ARG;
1871                   mr->addr =
1872                     lm->get_external_region_addr (mr->region_size, mr->fd,
1873                                                   c->private_ctx);
1874                 }
1875               else
1876                 {
1877                   if (mr->fd < 0)
1878                     return MEMIF_ERR_NO_SHMFD;
1879
1880                   if ((mr->addr =
1881                        mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1882                              MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
1883                     {
1884                       return memif_syscall_error_handler (errno);
1885                     }
1886                 }
1887             }
1888         }
1889     }
1890
1891   for (i = 0; i < c->rx_queues_num; i++)
1892     {
1893       mq = &c->rx_queues[i];
1894       if (mq != NULL)
1895         {
1896           mq->ring = c->regions[mq->region].addr + mq->offset;
1897           if (mq->ring->cookie != MEMIF_COOKIE)
1898             {
1899               DBG ("wrong cookie on rx ring %u", i);
1900               return MEMIF_ERR_COOKIE;
1901             }
1902           mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
1903         }
1904     }
1905
1906   for (i = 0; i < c->tx_queues_num; i++)
1907     {
1908       mq = &c->tx_queues[i];
1909       if (mq != NULL)
1910         {
1911           mq->ring = c->regions[mq->region].addr + mq->offset;
1912           if (mq->ring->cookie != MEMIF_COOKIE)
1913             {
1914               DBG ("wrong cookie on tx ring %u", i);
1915               return MEMIF_ERR_COOKIE;
1916             }
1917           mq->ring->head = mq->ring->tail = mq->last_head = mq->next_buf = 0;
1918         }
1919     }
1920
1921   lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD,
1922                          lm->private_ctx);
1923
1924   return 0;
1925 }
1926
1927 static inline int
1928 memif_add_region (libmemif_main_t * lm, memif_connection_t * conn,
1929                   uint8_t has_buffers)
1930 {
1931   memif_region_t *r;
1932
1933   r =
1934     lm->realloc (conn->regions,
1935                  sizeof (memif_region_t) * ++conn->regions_num);
1936   if (r == NULL)
1937     return MEMIF_ERR_NOMEM;
1938
1939   conn->regions = r;
1940   r = &conn->regions[conn->regions_num - 1];
1941   memset (r, 0, sizeof (memif_region_t));
1942
1943   if (has_buffers != 0)
1944     {
1945       r->buffer_offset = 0;
1946     }
1947   else
1948     {
1949       r->buffer_offset =
1950         (conn->run_args.num_s2m_rings +
1951          conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1952                                           sizeof (memif_desc_t) *
1953                                           (1 << conn->
1954                                            run_args.log2_ring_size));
1955     }
1956
1957   r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
1958     conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1959     (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1960
1961   if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
1962     return memif_syscall_error_handler (errno);
1963
1964   if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1965     return memif_syscall_error_handler (errno);
1966
1967   if ((ftruncate (r->fd, r->region_size)) == -1)
1968     return memif_syscall_error_handler (errno);
1969
1970   if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1971                        MAP_SHARED, r->fd, 0)) == MAP_FAILED)
1972     return memif_syscall_error_handler (errno);
1973
1974   return MEMIF_ERR_SUCCESS;
1975 }
1976
1977 static inline int
1978 memif_init_queues (libmemif_main_t * lm, memif_connection_t * conn)
1979 {
1980   int i, j;
1981   memif_ring_t *ring;
1982
1983   for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1984     {
1985       ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1986       DBG ("RING: %p I: %d", ring, i);
1987       ring->head = ring->tail = 0;
1988       ring->cookie = MEMIF_COOKIE;
1989       ring->flags = 0;
1990       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1991         {
1992           uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
1993           ring->desc[j].region = 1;
1994           ring->desc[j].offset =
1995             conn->regions[1].buffer_offset +
1996             (uint32_t) (slot * conn->run_args.buffer_size);
1997           ring->desc[j].length = conn->run_args.buffer_size;
1998         }
1999     }
2000   for (i = 0; i < conn->run_args.num_m2s_rings; i++)
2001     {
2002       ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
2003       DBG ("RING: %p I: %d", ring, i);
2004       ring->head = ring->tail = 0;
2005       ring->cookie = MEMIF_COOKIE;
2006       ring->flags = 0;
2007       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
2008         {
2009           uint16_t slot = (i + conn->run_args.num_s2m_rings) *
2010             (1 << conn->run_args.log2_ring_size) + j;
2011           ring->desc[j].region = 1;
2012           ring->desc[j].offset =
2013             conn->regions[1].buffer_offset +
2014             (uint32_t) (slot * conn->run_args.buffer_size);
2015           ring->desc[j].length = conn->run_args.buffer_size;
2016         }
2017     }
2018   memif_queue_t *mq;
2019   DBG ("alloc: %p", lm->alloc);
2020   DBG ("size: %lu", sizeof (memif_queue_t) * conn->run_args.num_s2m_rings);
2021   mq =
2022     (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2023                                  conn->run_args.num_s2m_rings);
2024   if (mq == NULL)
2025     return MEMIF_ERR_NOMEM;
2026
2027   int x;
2028   memif_list_elt_t e;
2029   for (x = 0; x < conn->run_args.num_s2m_rings; x++)
2030     {
2031       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2032         return memif_syscall_error_handler (errno);
2033       e.key = mq[x].int_fd;
2034       e.data_struct = conn;
2035       add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
2036
2037       mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
2038       DBG ("RING: %p I: %d", mq[x].ring, x);
2039       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2040       mq[x].region = 0;
2041       mq[x].offset =
2042         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2043       mq[x].last_head = mq[x].last_tail = 0;
2044       mq[x].next_buf = 0;
2045     }
2046   conn->tx_queues = mq;
2047   conn->tx_queues_num = conn->run_args.num_s2m_rings;
2048
2049   mq =
2050     (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
2051                                  conn->run_args.num_m2s_rings);
2052   if (mq == NULL)
2053     return MEMIF_ERR_NOMEM;
2054
2055   for (x = 0; x < conn->run_args.num_m2s_rings; x++)
2056     {
2057       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
2058         return memif_syscall_error_handler (errno);
2059       e.key = mq[x].int_fd;
2060       e.data_struct = conn;
2061       add_list_elt (lm, &e, &lm->interrupt_list, &lm->interrupt_list_len);
2062
2063       mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
2064       DBG ("RING: %p I: %d", mq[x].ring, x);
2065       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
2066       mq[x].region = 0;
2067       mq[x].offset =
2068         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
2069       mq[x].last_head = mq[x].last_tail = 0;
2070       mq[x].next_buf = 0;
2071     }
2072   conn->rx_queues = mq;
2073   conn->rx_queues_num = conn->run_args.num_m2s_rings;
2074
2075   return MEMIF_ERR_SUCCESS;
2076 }
2077
2078 int
2079 memif_init_regions_and_queues (memif_connection_t * conn)
2080 {
2081   memif_region_t *r;
2082   libmemif_main_t *lm;
2083
2084   if (conn == NULL)
2085     return MEMIF_ERR_INVAL_ARG;
2086
2087   lm = get_libmemif_main (conn->args.socket);
2088
2089   /* region 0. rings */
2090   memif_add_region (lm, conn, /* has_buffers */ 0);
2091
2092   /* region 1. buffers */
2093   if (lm->add_external_region)
2094     {
2095       r =
2096         (memif_region_t *) lm->realloc (conn->regions,
2097                                         sizeof (memif_region_t) *
2098                                         ++conn->regions_num);
2099       if (r == NULL)
2100         return MEMIF_ERR_NOMEM;
2101       conn->regions = r;
2102
2103       conn->regions[1].region_size =
2104         conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
2105         (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
2106       conn->regions[1].buffer_offset = 0;
2107       lm->add_external_region (&conn->regions[1].addr,
2108                                conn->regions[1].region_size,
2109                                &conn->regions[1].fd, conn->private_ctx);
2110       conn->regions[1].is_external = 1;
2111     }
2112   else
2113     {
2114       memif_add_region (lm, conn, 1);
2115     }
2116
2117   memif_init_queues (lm, conn);
2118
2119   return 0;
2120 }
2121
2122 int
2123 memif_set_next_free_buffer (memif_conn_handle_t conn, uint16_t qid,
2124                             memif_buffer_t *buf)
2125 {
2126   memif_connection_t *c = (memif_connection_t *) conn;
2127   if (EXPECT_FALSE (c == NULL))
2128     return MEMIF_ERR_NOCONN;
2129   if (EXPECT_FALSE (qid >= c->tx_queues_num))
2130     return MEMIF_ERR_QID;
2131   if (EXPECT_FALSE (buf == NULL))
2132     return MEMIF_ERR_INVAL_ARG;
2133
2134   uint16_t ring_size, ns;
2135   memif_queue_t *mq = &c->tx_queues[qid];
2136   memif_ring_t *ring = mq->ring;
2137
2138   ring_size = (1 << mq->log2_ring_size);
2139   if (c->args.is_master)
2140     ns = ring->head - mq->next_buf;
2141   else
2142     ns = ring_size - mq->next_buf + ring->tail;
2143
2144   if ((mq->next_buf - buf->desc_index) > ns)
2145     return MEMIF_ERR_INVAL_ARG;
2146
2147   mq->next_buf = buf->desc_index;
2148
2149   return MEMIF_ERR_SUCCESS;
2150 }
2151
2152 static void
2153 memif_buffer_enq_at_idx_internal (memif_queue_t *from_q, memif_queue_t *to_q,
2154                                   memif_buffer_t *buf, uint16_t slot)
2155 {
2156   uint16_t from_mask = (1 << from_q->log2_ring_size) - 1;
2157   uint16_t to_mask = (1 << to_q->log2_ring_size) - 1;
2158   memif_desc_t *from_d, *to_d, tmp_d;
2159
2160   /* Get the descriptors */
2161   from_d = &from_q->ring->desc[buf->desc_index & from_mask];
2162   to_d = &to_q->ring->desc[slot & to_mask];
2163
2164   /* Swap descriptors */
2165   tmp_d = *from_d;
2166   *from_d = *to_d;
2167   *to_d = tmp_d;
2168
2169   /* Update descriptor index and queue for clients buffer */
2170   buf->desc_index = slot;
2171   buf->queue = to_q;
2172 }
2173
2174 int
2175 memif_buffer_requeue (memif_conn_handle_t conn, memif_buffer_t *buf_a,
2176                       memif_buffer_t *buf_b)
2177 {
2178   memif_connection_t *c = (memif_connection_t *) conn;
2179   if (EXPECT_FALSE (c == NULL))
2180     return MEMIF_ERR_NOCONN;
2181   if (EXPECT_FALSE (c->args.is_master))
2182     return MEMIF_ERR_INVAL_ARG;
2183   if ((buf_a == NULL) || (buf_b == NULL))
2184     return MEMIF_ERR_INVAL_ARG;
2185
2186   int err;
2187   /* store buf_a information */
2188   uint16_t index_a = buf_a->desc_index;
2189   memif_queue_t *mq_a = buf_a->queue;
2190
2191   /* swap buffers, buf_a was updated with new desc_index and queue */
2192   memif_buffer_enq_at_idx_internal ((memif_queue_t *) buf_a->queue,
2193                                     (memif_queue_t *) buf_b->queue, buf_a,
2194                                     buf_b->desc_index);
2195
2196   /* update buf_b desc_index and queue */
2197   buf_b->desc_index = index_a;
2198   buf_b->queue = mq_a;
2199
2200   return MEMIF_ERR_SUCCESS;
2201 }
2202
2203 int
2204 memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
2205                      memif_buffer_t * bufs, uint16_t count,
2206                      uint16_t * count_out)
2207 {
2208   memif_connection_t *c = (memif_connection_t *) conn;
2209   if (EXPECT_FALSE (c == NULL))
2210     return MEMIF_ERR_NOCONN;
2211   if (EXPECT_FALSE (c->fd < 0))
2212     return MEMIF_ERR_DISCONNECTED;
2213   if (EXPECT_FALSE (qid >= c->tx_queues_num))
2214     return MEMIF_ERR_QID;
2215   if (EXPECT_FALSE (!count_out))
2216     return MEMIF_ERR_INVAL_ARG;
2217   if (EXPECT_FALSE (c->args.is_master))
2218     return MEMIF_ERR_INVAL_ARG;
2219
2220   memif_queue_t *mq = &c->tx_queues[qid];
2221   memif_ring_t *ring = mq->ring;
2222   memif_buffer_t *b0;
2223   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2224   uint16_t ring_size;
2225   uint16_t ns;
2226   memif_queue_t *bmq;
2227   int err = MEMIF_ERR_SUCCESS;  /* 0 */
2228   *count_out = 0;
2229
2230   ring_size = (1 << mq->log2_ring_size);
2231
2232   /* can only be called by slave */
2233   ns = ring_size - mq->next_buf + ring->tail;
2234
2235   b0 = bufs;
2236
2237   while (count && ns)
2238     {
2239       /* Swaps the descriptors, updates next_buf pointer and updates client
2240        * memif buffer */
2241
2242       memif_buffer_enq_at_idx_internal ((memif_queue_t *) b0->queue, mq, b0,
2243                                         mq->next_buf);
2244
2245       mq->next_buf++; /* mark the buffer as allocated */
2246       count--;
2247       ns--;
2248       b0++;
2249       *count_out += 1;
2250     }
2251
2252   DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2253        mq->next_buf);
2254
2255   if (count)
2256     {
2257       DBG ("ring buffer full! qid: %u", qid);
2258       err = MEMIF_ERR_NOBUF_RING;
2259     }
2260
2261   return err;
2262 }
2263
2264 int
2265 memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
2266                     memif_buffer_t * bufs, uint16_t count,
2267                     uint16_t * count_out, uint16_t size)
2268 {
2269   memif_connection_t *c = (memif_connection_t *) conn;
2270   if (EXPECT_FALSE (c == NULL))
2271     return MEMIF_ERR_NOCONN;
2272   if (EXPECT_FALSE (c->fd < 0))
2273     return MEMIF_ERR_DISCONNECTED;
2274   uint8_t num =
2275     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2276     run_args.num_s2m_rings;
2277   if (EXPECT_FALSE (qid >= num))
2278     return MEMIF_ERR_QID;
2279   if (EXPECT_FALSE (!count_out))
2280     return MEMIF_ERR_INVAL_ARG;
2281
2282   libmemif_main_t *lm = get_libmemif_main (c->args.socket);
2283   memif_queue_t *mq = &c->tx_queues[qid];
2284   memif_ring_t *ring = mq->ring;
2285   memif_buffer_t *b0;
2286   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2287   uint32_t offset_mask = c->run_args.buffer_size - 1;
2288   uint16_t ring_size;
2289   uint16_t ns;
2290   int err = MEMIF_ERR_SUCCESS;  /* 0 */
2291   uint16_t dst_left, src_left;
2292   uint16_t saved_count;
2293   uint16_t saved_next_buf;
2294   memif_buffer_t *saved_b;
2295   *count_out = 0;
2296
2297   ring_size = (1 << mq->log2_ring_size);
2298
2299   if (c->args.is_master)
2300     ns = ring->head - mq->next_buf;
2301   else
2302     ns = ring_size - mq->next_buf + ring->tail;
2303
2304   while (count && ns)
2305     {
2306       b0 = (bufs + *count_out);
2307
2308       saved_b = b0;
2309       saved_count = count;
2310       saved_next_buf = mq->next_buf;
2311
2312       b0->desc_index = mq->next_buf;
2313       ring->desc[mq->next_buf & mask].flags = 0;
2314
2315       /* slave can produce buffer with original length */
2316       dst_left = (c->args.is_master) ? ring->desc[mq->next_buf & mask].length :
2317                                        c->run_args.buffer_size;
2318       src_left = size;
2319
2320       while (src_left)
2321         {
2322           if (EXPECT_FALSE (dst_left == 0))
2323             {
2324               if (count && ns)
2325                 {
2326                   *count_out += 1;
2327                   mq->next_buf++;
2328                   ns--;
2329
2330                   ring->desc[b0->desc_index & mask].flags |=
2331                     MEMIF_DESC_FLAG_NEXT;
2332                   b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
2333
2334                   b0 = (bufs + *count_out);
2335                   b0->desc_index = mq->next_buf;
2336                   dst_left = (c->args.is_master) ?
2337                                ring->desc[mq->next_buf & mask].length :
2338                                c->run_args.buffer_size;
2339                   ring->desc[mq->next_buf & mask].flags = 0;
2340                 }
2341               else
2342                 {
2343                   /* rollback allocated chain buffers */
2344                   memset (saved_b, 0, sizeof (memif_buffer_t)
2345                           * (saved_count - count + 1));
2346                   *count_out -= saved_count - count;
2347                   mq->next_buf = saved_next_buf;
2348                   goto no_ns;
2349                 }
2350             }
2351           b0->len = memif_min (dst_left, src_left);
2352
2353           /* slave resets buffer offset */
2354           if (c->args.is_master == 0)
2355             {
2356               memif_desc_t *d = &ring->desc[mq->next_buf & mask];
2357               if (lm->get_external_buffer_offset)
2358                 d->offset = lm->get_external_buffer_offset (c->private_ctx);
2359               else
2360                 d->offset = d->offset - (d->offset & offset_mask);
2361             }
2362           b0->data = memif_get_buffer (c, ring, mq->next_buf & mask);
2363
2364           src_left -= b0->len;
2365           dst_left -= b0->len;
2366         }
2367
2368       *count_out += 1;
2369       mq->next_buf++;
2370       ns--;
2371       count--;
2372     }
2373
2374 no_ns:
2375
2376   DBG ("allocated: %u/%u bufs. Next buffer pointer %d", *count_out, count,
2377        mq->next_buf);
2378
2379   if (count)
2380     {
2381       DBG ("ring buffer full! qid: %u", qid);
2382       err = MEMIF_ERR_NOBUF_RING;
2383     }
2384
2385   return err;
2386 }
2387
2388 int
2389 memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
2390                     uint16_t headroom)
2391 {
2392   memif_connection_t *c = (memif_connection_t *) conn;
2393   if (EXPECT_FALSE (c == NULL))
2394     return MEMIF_ERR_NOCONN;
2395   if (EXPECT_FALSE (c->fd < 0))
2396     return MEMIF_ERR_DISCONNECTED;
2397   uint8_t num =
2398     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2399     run_args.num_m2s_rings;
2400   if (EXPECT_FALSE (qid >= num))
2401     return MEMIF_ERR_QID;
2402   libmemif_main_t *lm = get_libmemif_main (c->args.socket);
2403   memif_queue_t *mq = &c->rx_queues[qid];
2404   memif_ring_t *ring = mq->ring;
2405   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2406   uint32_t offset_mask = c->run_args.buffer_size - 1;
2407   uint16_t slot, counter = 0;
2408
2409   if (c->args.is_master)
2410     {
2411       MEMIF_MEMORY_BARRIER ();
2412       ring->tail =
2413         (ring->tail + count <=
2414          mq->last_head) ? ring->tail + count : mq->last_head;
2415       return MEMIF_ERR_SUCCESS;
2416     }
2417
2418   uint16_t head = ring->head;
2419   slot = head;
2420   uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
2421   count = (count < ns) ? count : ns;
2422
2423   memif_desc_t *d;
2424   while (counter < count)
2425     {
2426       d = &ring->desc[slot & mask];
2427       d->region = 1;
2428       d->length = c->run_args.buffer_size - headroom;
2429       if (lm->get_external_buffer_offset)
2430         d->offset = lm->get_external_buffer_offset (c->private_ctx);
2431       else
2432         d->offset = d->offset - (d->offset & offset_mask) + headroom;
2433       slot++;
2434       counter++;
2435     }
2436
2437   MEMIF_MEMORY_BARRIER ();
2438   ring->head = slot;
2439
2440   return MEMIF_ERR_SUCCESS;     /* 0 */
2441 }
2442
2443 int
2444 memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
2445                 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
2446 {
2447   memif_connection_t *c = (memif_connection_t *) conn;
2448   if (EXPECT_FALSE (c == NULL))
2449     return MEMIF_ERR_NOCONN;
2450   if (EXPECT_FALSE (c->fd < 0))
2451     return MEMIF_ERR_DISCONNECTED;
2452   uint8_t num =
2453     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2454     run_args.num_s2m_rings;
2455   if (EXPECT_FALSE (qid >= num))
2456     return MEMIF_ERR_QID;
2457   if (EXPECT_FALSE (!tx))
2458     return MEMIF_ERR_INVAL_ARG;
2459
2460   memif_queue_t *mq = &c->tx_queues[qid];
2461   memif_ring_t *ring = mq->ring;
2462   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2463   uint32_t offset_mask = c->run_args.buffer_size - 1;
2464   memif_buffer_t *b0;
2465   memif_desc_t *d;
2466   int64_t data_offset;
2467   *tx = 0;
2468   int err = MEMIF_ERR_SUCCESS;
2469
2470   if (EXPECT_FALSE (count == 0))
2471     return MEMIF_ERR_SUCCESS;
2472
2473   uint16_t index;
2474   if (c->args.is_master)
2475     index = ring->tail;
2476   else
2477     index = ring->head;
2478
2479   while (count)
2480     {
2481       b0 = (bufs + *tx);
2482       /* set error to MEMIF_ERR_INVAL_ARG and finish the sending process
2483        */
2484       if ((b0->desc_index & mask) != (index & mask))
2485         {
2486           err = MEMIF_ERR_INVAL_ARG;
2487           goto done;
2488         }
2489       d = &ring->desc[b0->desc_index & mask];
2490       d->length = b0->len;
2491       if (!c->args.is_master)
2492         {
2493           // reset headroom
2494           d->offset = d->offset - (d->offset & offset_mask);
2495           // calculate offset from user data
2496           data_offset = b0->data - (d->offset + c->regions[d->region].addr);
2497           if (data_offset != 0)
2498             {
2499               /* verify data offset and buffer length */
2500               if ((data_offset < 0) ||
2501                   ((data_offset + b0->len) > c->run_args.buffer_size))
2502                 {
2503                   DBG ("slot: %d, data_offset: %d, length: %d",
2504                        b0->desc_index & mask, data_offset, b0->len);
2505                   err = MEMIF_ERR_INVAL_ARG;
2506                   goto done;
2507                 }
2508               d->offset += data_offset;
2509             }
2510         }
2511
2512 #ifdef MEMIF_DBG_SHM
2513       printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
2514       printf ("data: %p\n",
2515               memif_get_buffer (c, ring, b0->desc_index & mask));
2516       printf ("index: %u\n", b0->desc_index);
2517       print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
2518                    ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
2519 #endif /* MEMIF_DBG_SHM */
2520
2521       *tx += 1;
2522       count--;
2523       index++;
2524     }
2525
2526 done:
2527   MEMIF_MEMORY_BARRIER ();
2528   if (c->args.is_master)
2529     ring->tail = b0->desc_index + 1;
2530   else
2531     ring->head = b0->desc_index + 1;
2532
2533   if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
2534     {
2535       uint64_t a = 1;
2536       int r = write (mq->int_fd, &a, sizeof (a));
2537       if (r < 0)
2538         return MEMIF_ERR_INT_WRITE;
2539     }
2540
2541   return err;
2542 }
2543
2544 int
2545 memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
2546                 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
2547 {
2548   memif_connection_t *c = (memif_connection_t *) conn;
2549   if (EXPECT_FALSE (c == NULL))
2550     return MEMIF_ERR_NOCONN;
2551   if (EXPECT_FALSE (c->fd < 0))
2552     return MEMIF_ERR_DISCONNECTED;
2553   uint8_t num =
2554     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2555     run_args.num_m2s_rings;
2556   if (EXPECT_FALSE (qid >= num))
2557     return MEMIF_ERR_QID;
2558   if (EXPECT_FALSE (!rx))
2559     return MEMIF_ERR_INVAL_ARG;
2560
2561   memif_queue_t *mq = &c->rx_queues[qid];
2562   memif_ring_t *ring = mq->ring;
2563   uint16_t cur_slot, last_slot;
2564   uint16_t ns;
2565   uint16_t mask = (1 << mq->log2_ring_size) - 1;
2566   memif_buffer_t *b0;
2567   *rx = 0;
2568
2569   uint64_t b;
2570   ssize_t r;
2571
2572   cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
2573   last_slot = (c->args.is_master) ? ring->head : ring->tail;
2574   if (cur_slot == last_slot)
2575     {
2576       r = read (mq->int_fd, &b, sizeof (b));
2577       if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2578                         return memif_syscall_error_handler (errno);
2579
2580       return MEMIF_ERR_SUCCESS;
2581     }
2582
2583   ns = last_slot - cur_slot;
2584
2585   while (ns && count)
2586     {
2587       b0 = (bufs + *rx);
2588
2589       b0->desc_index = cur_slot;
2590       b0->data = memif_get_buffer (c, ring, cur_slot & mask);
2591       b0->len = ring->desc[cur_slot & mask].length;
2592       /* slave resets buffer length */
2593       if (c->args.is_master == 0)
2594         {
2595           ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
2596         }
2597
2598       if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
2599         {
2600           b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
2601           ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
2602         }
2603
2604       b0->queue = mq;
2605 #ifdef MEMIF_DBG_SHM
2606       printf ("data: %p\n", b0->data);
2607       printf ("index: %u\n", b0->desc_index);
2608       printf ("queue: %p\n", b0->queue);
2609       print_bytes (b0->data, b0->len, DBG_RX_BUF);
2610 #endif /* MEMIF_DBG_SHM */
2611       ns--;
2612       *rx += 1;
2613
2614       count--;
2615       cur_slot++;
2616     }
2617
2618   if (c->args.is_master)
2619     mq->last_head = cur_slot;
2620   else
2621     mq->last_tail = cur_slot;
2622
2623   if (ns)
2624     {
2625       DBG ("not enough buffers!");
2626       return MEMIF_ERR_NOBUF;
2627     }
2628
2629   r = read (mq->int_fd, &b, sizeof (b));
2630   if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
2631     return memif_syscall_error_handler (errno);
2632
2633   return MEMIF_ERR_SUCCESS;     /* 0 */
2634 }
2635
2636 int
2637 memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
2638                    char *buf, ssize_t buflen)
2639 {
2640   memif_connection_t *c = (memif_connection_t *) conn;
2641   libmemif_main_t *lm;
2642   memif_socket_t *ms;
2643   int err = MEMIF_ERR_SUCCESS, i;
2644   ssize_t l0 = 0, l1;
2645
2646   if (c == NULL)
2647     return MEMIF_ERR_NOCONN;
2648
2649   ms = (memif_socket_t *) c->args.socket;
2650   lm = get_libmemif_main (ms);
2651
2652   l1 = strlen ((char *) c->args.interface_name);
2653   if (l0 + l1 < buflen)
2654     {
2655       md->if_name =
2656         (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
2657       l0 += l1 + 1;
2658     }
2659   else
2660     err = MEMIF_ERR_NOBUF_DET;
2661
2662   l1 = strlen ((char *) lm->app_name);
2663   if (l0 + l1 < buflen)
2664     {
2665       md->inst_name = (uint8_t *) strcpy (buf + l0, (char *) lm->app_name);
2666       l0 += l1 + 1;
2667     }
2668   else
2669     err = MEMIF_ERR_NOBUF_DET;
2670
2671   l1 = strlen ((char *) c->remote_if_name);
2672   if (l0 + l1 < buflen)
2673     {
2674       md->remote_if_name =
2675         (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
2676       l0 += l1 + 1;
2677     }
2678   else
2679     err = MEMIF_ERR_NOBUF_DET;
2680
2681   l1 = strlen ((char *) c->remote_name);
2682   if (l0 + l1 < buflen)
2683     {
2684       md->remote_inst_name =
2685         (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
2686       l0 += l1 + 1;
2687     }
2688   else
2689     err = MEMIF_ERR_NOBUF_DET;
2690
2691   md->id = c->args.interface_id;
2692
2693   if (strlen ((char *) c->args.secret) > 0)
2694     {
2695       l1 = strlen ((char *) c->args.secret);
2696       if (l0 + l1 < buflen)
2697         {
2698           md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
2699           l0 += l1 + 1;
2700         }
2701       else
2702         err = MEMIF_ERR_NOBUF_DET;
2703     }
2704
2705   md->role = (c->args.is_master) ? 0 : 1;
2706   md->mode = c->args.mode;
2707
2708   l1 = strlen ((char *) ms->filename);
2709   if (l0 + l1 < buflen)
2710     {
2711       md->socket_filename =
2712         (uint8_t *) strcpy (buf + l0, (char *) ms->filename);
2713       l0 += l1 + 1;
2714     }
2715   else
2716     err = MEMIF_ERR_NOBUF_DET;
2717
2718   l1 = strlen ((char *) c->remote_disconnect_string);
2719   if (l0 + l1 < buflen)
2720     {
2721       md->error =
2722         (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
2723       l0 += l1 + 1;
2724     }
2725   else
2726     err = MEMIF_ERR_NOBUF_DET;
2727
2728   md->regions_num = c->regions_num;
2729   l1 = sizeof (memif_region_details_t) * md->regions_num;
2730   if (l0 + l1 <= buflen)
2731     {
2732       md->regions = (memif_region_details_t *) (buf + l0);
2733       for (i = 0; i < md->regions_num; i++)
2734         {
2735           md->regions[i].index = i;
2736           md->regions[i].addr = c->regions[i].addr;
2737           md->regions[i].size = c->regions[i].region_size;
2738           md->regions[i].fd = c->regions[i].fd;
2739           md->regions[i].is_external = c->regions[i].is_external;
2740         }
2741       l0 += l1;
2742     }
2743   else
2744     err = MEMIF_ERR_NOBUF_DET;
2745
2746   md->rx_queues_num =
2747     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2748     run_args.num_m2s_rings;
2749
2750   l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2751   if (l0 + l1 <= buflen)
2752     {
2753       md->rx_queues = (memif_queue_details_t *) (buf + l0);
2754       for (i = 0; i < md->rx_queues_num; i++)
2755         {
2756           md->rx_queues[i].region = c->rx_queues[i].region;
2757           md->rx_queues[i].qid = i;
2758           md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2759           md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2760           md->rx_queues[i].head = c->rx_queues[i].ring->head;
2761           md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2762           md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2763         }
2764       l0 += l1;
2765     }
2766   else
2767     err = MEMIF_ERR_NOBUF_DET;
2768
2769   md->tx_queues_num =
2770     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2771     run_args.num_s2m_rings;
2772
2773   l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2774   if (l0 + l1 <= buflen)
2775     {
2776       md->tx_queues = (memif_queue_details_t *) (buf + l0);
2777       for (i = 0; i < md->tx_queues_num; i++)
2778         {
2779           md->tx_queues[i].region = c->tx_queues[i].region;
2780           md->tx_queues[i].qid = i;
2781           md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2782           md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2783           md->tx_queues[i].head = c->tx_queues[i].ring->head;
2784           md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2785           md->tx_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->link_up_down = (c->fd > 0) ? 1 : 0;
2793
2794   return err;                   /* 0 */
2795 }
2796
2797 int
2798 memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2799 {
2800   memif_connection_t *c = (memif_connection_t *) conn;
2801   uint8_t num;
2802
2803   *efd = -1;
2804   if (c == NULL)
2805     return MEMIF_ERR_NOCONN;
2806   if (c->fd < 0)
2807     return MEMIF_ERR_DISCONNECTED;
2808
2809   num =
2810     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2811     run_args.num_m2s_rings;
2812   if (qid >= num)
2813     return MEMIF_ERR_QID;
2814
2815   *efd = c->rx_queues[qid].int_fd;
2816
2817   return MEMIF_ERR_SUCCESS;
2818 }
2819
2820 int
2821 memif_cleanup ()
2822 {
2823   libmemif_main_t *lm = &libmemif_main;
2824   int err;
2825
2826   err = memif_delete_socket ((memif_socket_handle_t *) & lm->default_socket);
2827   if (err != MEMIF_ERR_SUCCESS)
2828     return err;
2829
2830   if (lm->control_list)
2831     lm->free (lm->control_list);
2832   lm->control_list = NULL;
2833   if (lm->interrupt_list)
2834     lm->free (lm->interrupt_list);
2835   lm->interrupt_list = NULL;
2836   if (lm->socket_list)
2837     lm->free (lm->socket_list);
2838   lm->socket_list = NULL;
2839   if (lm->pending_list)
2840     lm->free (lm->pending_list);
2841   lm->pending_list = NULL;
2842   if (lm->poll_cancel_fd != -1)
2843     close (lm->poll_cancel_fd);
2844
2845   return MEMIF_ERR_SUCCESS;     /* 0 */
2846 }
2847
2848 int
2849 memif_per_thread_cleanup (memif_per_thread_main_handle_t * pt_main)
2850 {
2851   libmemif_main_t *lm = (libmemif_main_t *) * pt_main;
2852
2853   if (lm == NULL)
2854     return MEMIF_ERR_INVAL_ARG;
2855
2856   /* No default socket in case of per thread */
2857
2858   if (lm->control_list)
2859     lm->free (lm->control_list);
2860   lm->control_list = NULL;
2861   if (lm->interrupt_list)
2862     lm->free (lm->interrupt_list);
2863   lm->interrupt_list = NULL;
2864   if (lm->socket_list)
2865     lm->free (lm->socket_list);
2866   lm->socket_list = NULL;
2867   if (lm->pending_list)
2868     lm->free (lm->pending_list);
2869   lm->pending_list = NULL;
2870   if (lm->poll_cancel_fd != -1)
2871     close (lm->poll_cancel_fd);
2872
2873   lm->free (lm);
2874
2875   *pt_main = NULL;
2876
2877   return MEMIF_ERR_SUCCESS;     /* 0 */
2878 }