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