libmemif: Connection request APIs
[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 int memif_epfd;
70 int poll_cancel_fd = -1;
71
72 static char memif_buf[MAX_ERRBUF_LEN];
73
74 const char *memif_errlist[ERRLIST_LEN] = {      /* MEMIF_ERR_SUCCESS */
75   "Success.",
76   /* MEMIF_ERR_SYSCALL */
77   "Unspecified syscall error (build with -DMEMIF_DBG or make debug).",
78   /* MEMIF_ERR_CONNREFUSED */
79   "Connection refused",
80   /* MEMIF_ERR_ACCES */
81   "Permission to resoure denied.",
82   /* MEMIF_ERR_NO_FILE */
83   "Socket file does not exist",
84   /* MEMIF_ERR_FILE_LIMIT */
85   "System limit on total numer of open files reached.",
86   /* MEMIF_ERR_PROC_FILE_LIMIT */
87   "Per-process limit on total number of open files reached.",
88   /* MEMIF_ERR_ALREADY */
89   "Connection already requested.",
90   /* MEMIF_ERR_AGAIN */
91   "File descriptor refers to file other than socket, or operation would block.",
92   /* MEMIF_ERR_BAD_FD */
93   "Bad file descriptor.",
94   /* MEMIF_ERR_NOMEM */
95   "Out of memory.",
96   /* MEMIF_ERR_INVAL_ARG */
97   "Invalid argument.",
98   /* MEMIF_ERR_NOCONN */
99   "Memif connection handle does not point to existing conenction",
100   /* MEMIF_ERR_CONN */
101   "Memif connection handle points to existing connection",
102   /* MEMIF_ERR_CB_FDUPDATE */
103   "Callback memif_control_fd_update_t returned error",
104   /* MEMIF_ERR_FILE_NOT_SOCK */
105   "File specified by socket filename exists and is not socket.",
106   /* MEMIF_ERR_NO_SHMFD */
107   "Missing shared memory file descriptor. (internal error)",
108   /* MEMIF_ERR_COOKIE */
109   "Invalid cookie on ring. (internal error)",
110   /* MEMIF_ERR_NOBUF_RING */
111   "Ring buffer full.",
112   /* MEMIF_ERR_NOBUF */
113   "Not enough memif buffers. There are unreceived data in shared memory.",
114   /* MEMIF_ERR_NOBUF_DET */
115   "Not enough space for memif details in suplied buffer. String data might be malformed.",
116   /* MEMIF_ERR_INT_WRITE */
117   "Send interrupt error.",
118   /* MEMIF_ERR_MFMSG */
119   "Malformed message received on control channel.",
120   /* MEMIF_ERR_QID */
121   "Invalid queue id",
122   /* MEMIF_ERR_PROTO */
123   "Incompatible memory interface protocol version.",
124   /* MEMIF_ERR_ID */
125   "Unmatched interface id.",
126   /* MEMIF_ERR_ACCSLAVE */
127   "Slave cannot accept connection reqest.",
128   /* MEMIF_ERR_ALRCONN */
129   "Interface is already connected.",
130   /* MEMIF_ERR_MODE */
131   "Mode mismatch.",
132   /* MEMIF_ERR_SECRET */
133   "Secret mismatch.",
134   /* MEMIF_ERR_NOSECRET */
135   "Secret required.",
136   /* MEMIF_ERR_MAXREG */
137   "Limit on total number of regions reached.",
138   /* MEMIF_ERR_MAXRING */
139   "Limit on total number of ring reached.",
140   /* MEMIF_ERR_NO_INTFD */
141   "Missing interrupt file descriptor. (internal error)",
142   /* MEMIF_ERR_DISCONNECT */
143   "Interface received disconnect request.",
144   /* MEMIF_ERR_DISCONNECTED */
145   "Interface is disconnected.",
146   /* MEMIF_ERR_UNKNOWN_MSG */
147   "Unknown message type received on control channel. (internal error)",
148   /* MEMIF_ERR_POLL_CANCEL */
149   "Memif event polling was canceled.",
150   /* MEMIF_ERR_MAX_RING */
151   "Maximum log2 ring size is 15",
152   /* MEMIF_ERR_PRIVHDR */
153   "Private headers not supported."
154 };
155
156 #define MEMIF_ERR_UNDEFINED "undefined error"
157
158 char *
159 memif_strerror (int err_code)
160 {
161   if (err_code >= ERRLIST_LEN)
162     {
163       strncpy (memif_buf, MEMIF_ERR_UNDEFINED, strlen (MEMIF_ERR_UNDEFINED));
164       memif_buf[strlen (MEMIF_ERR_UNDEFINED)] = '\0';
165     }
166   else
167     {
168       strncpy (memif_buf, memif_errlist[err_code],
169                strlen (memif_errlist[err_code]));
170       memif_buf[strlen (memif_errlist[err_code])] = '\0';
171     }
172   return memif_buf;
173 }
174
175 uint16_t
176 memif_get_version ()
177 {
178   return MEMIF_VERSION;
179 }
180
181 #define DBG_TX_BUF (0)
182 #define DBG_RX_BUF (1)
183
184 #ifdef MEMIF_DBG_SHM
185 static void
186 print_bytes (void *data, uint16_t len, uint8_t q)
187 {
188   if (q == DBG_TX_BUF)
189     printf ("\nTX:\n\t");
190   else
191     printf ("\nRX:\n\t");
192   int i;
193   for (i = 0; i < len; i++)
194     {
195       if (i % 8 == 0)
196         printf ("\n%d:\t", i);
197       printf ("%02X ", ((uint8_t *) (data))[i]);
198     }
199   printf ("\n\n");
200 }
201 #endif /* MEMIF_DBG_SHM */
202
203 int
204 memif_syscall_error_handler (int err_code)
205 {
206   DBG ("%s", strerror (err_code));
207
208   if (err_code == 0)
209     return MEMIF_ERR_SUCCESS;
210   if (err_code == EACCES)
211     return MEMIF_ERR_ACCES;
212   if (err_code == ENFILE)
213     return MEMIF_ERR_FILE_LIMIT;
214   if (err_code == EMFILE)
215     return MEMIF_ERR_PROC_FILE_LIMIT;
216   if (err_code == ENOMEM)
217     return MEMIF_ERR_NOMEM;
218 /* connection refused if master does not exist
219     this error would spam the user until master was created */
220 /*
221   if (err_code == ECONNREFUSED)
222     return MEMIF_ERR_SUCCESS;
223 */
224   if (err_code == ECONNREFUSED)
225     return MEMIF_ERR_CONNREFUSED;
226   if (err_code == EALREADY)
227     return MEMIF_ERR_ALREADY;
228   if (err_code == EAGAIN)
229     return MEMIF_ERR_AGAIN;
230   if (err_code == EBADF)
231     return MEMIF_ERR_BAD_FD;
232   if (err_code == ENOENT)
233     return MEMIF_ERR_NO_FILE;
234
235   /* other syscall errors */
236   return MEMIF_ERR_SYSCALL;
237 }
238
239 static int
240 memif_add_epoll_fd (int fd, uint32_t events)
241 {
242   if (fd < 0)
243     {
244       DBG ("invalid fd %d", fd);
245       return -1;
246     }
247   struct epoll_event evt;
248   memset (&evt, 0, sizeof (evt));
249   evt.events = events;
250   evt.data.fd = fd;
251   if (epoll_ctl (memif_epfd, EPOLL_CTL_ADD, fd, &evt) < 0)
252     {
253       DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
254       return -1;
255     }
256   DBG ("fd %d added to epoll", fd);
257   return 0;
258 }
259
260 static int
261 memif_mod_epoll_fd (int fd, uint32_t events)
262 {
263   if (fd < 0)
264     {
265       DBG ("invalid fd %d", fd);
266       return -1;
267     }
268   struct epoll_event evt;
269   memset (&evt, 0, sizeof (evt));
270   evt.events = events;
271   evt.data.fd = fd;
272   if (epoll_ctl (memif_epfd, EPOLL_CTL_MOD, fd, &evt) < 0)
273     {
274       DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
275       return -1;
276     }
277   DBG ("fd %d moddified on epoll", fd);
278   return 0;
279 }
280
281 static int
282 memif_del_epoll_fd (int fd)
283 {
284   if (fd < 0)
285     {
286       DBG ("invalid fd %d", fd);
287       return -1;
288     }
289   struct epoll_event evt;
290   memset (&evt, 0, sizeof (evt));
291   if (epoll_ctl (memif_epfd, EPOLL_CTL_DEL, fd, &evt) < 0)
292     {
293       DBG ("epoll_ctl: %s fd %d", strerror (errno), fd);
294       return -1;
295     }
296   DBG ("fd %d removed from epoll", fd);
297   return 0;
298 }
299
300 int
301 memif_control_fd_update (int fd, uint8_t events)
302 {
303   if (events & MEMIF_FD_EVENT_DEL)
304     return memif_del_epoll_fd (fd);
305
306   uint32_t evt = 0;
307   if (events & MEMIF_FD_EVENT_READ)
308     evt |= EPOLLIN;
309   if (events & MEMIF_FD_EVENT_WRITE)
310     evt |= EPOLLOUT;
311
312   if (events & MEMIF_FD_EVENT_MOD)
313     return memif_mod_epoll_fd (fd, evt);
314
315   return memif_add_epoll_fd (fd, evt);
316 }
317
318 int
319 add_list_elt (memif_list_elt_t * e, memif_list_elt_t ** list, uint16_t * len)
320 {
321   libmemif_main_t *lm = &libmemif_main;
322
323   int i;
324   for (i = 0; i < *len; i++)
325     {
326       if ((*list)[i].data_struct == NULL)
327         {
328           (*list)[i].key = e->key;
329           (*list)[i].data_struct = e->data_struct;
330           return i;
331         }
332     }
333   memif_list_elt_t *tmp;
334   tmp = lm->realloc (*list, sizeof (memif_list_elt_t) * *len * 2);
335   if (tmp == NULL)
336     return -1;
337
338   for (i = *len; i < *len * 2; i++)
339     {
340       tmp[i].key = -1;
341       tmp[i].data_struct = NULL;
342     }
343
344   tmp[*len].key = e->key;
345   tmp[*len].data_struct = e->data_struct;
346   i = *len;
347   *len = *len * 2;
348   *list = tmp;
349
350   return i;
351 }
352
353 int
354 get_list_elt (memif_list_elt_t ** e, memif_list_elt_t * list, uint16_t len,
355               int key)
356 {
357   if (key == -1)
358     {
359       *e = NULL;
360       return -1;
361     }
362   int i;
363   for (i = 0; i < len; i++)
364     {
365       if (list[i].key == key)
366         {
367           *e = &list[i];
368           return 0;
369         }
370     }
371   *e = NULL;
372   return -1;
373 }
374
375 /* does not free memory, only marks element as free */
376 int
377 free_list_elt (memif_list_elt_t * list, uint16_t len, int key)
378 {
379   int i;
380   for (i = 0; i < len; i++)
381     {
382       if (list[i].key == key)
383         {
384           list[i].key = -1;
385           list[i].data_struct = NULL;
386           return 0;
387         }
388     }
389
390   return -1;
391 }
392
393 int
394 free_list_elt_ctx (memif_list_elt_t * list, uint16_t len,
395                    memif_connection_t * ctx)
396 {
397   int i;
398   for (i = 0; i < len; i++)
399     {
400       if (list[i].key == -1)
401         {
402           if (list[i].data_struct == ctx)
403             {
404               list[i].data_struct = NULL;
405               return 0;
406             }
407         }
408     }
409
410   return -1;
411 }
412
413 static void
414 memif_control_fd_update_register (memif_control_fd_update_t * cb)
415 {
416   libmemif_main_t *lm = &libmemif_main;
417   lm->control_fd_update = cb;
418 }
419
420 void
421 memif_register_external_region (memif_add_external_region_t * ar,
422                                 memif_get_external_region_addr_t * gr,
423                                 memif_del_external_region_t * dr,
424                                 memif_get_external_buffer_offset_t * go)
425 {
426   libmemif_main_t *lm = &libmemif_main;
427   lm->add_external_region = ar;
428   lm->get_external_region_addr = gr;
429   lm->del_external_region = dr;
430   lm->get_external_buffer_offset = go;
431 }
432
433 static void
434 memif_alloc_register (memif_alloc_t * ma)
435 {
436   libmemif_main_t *lm = &libmemif_main;
437   lm->alloc = ma;
438 }
439
440 static void
441 memif_realloc_register (memif_realloc_t * mr)
442 {
443   libmemif_main_t *lm = &libmemif_main;
444   lm->realloc = mr;
445 }
446
447 static void
448 memif_free_register (memif_free_t * mf)
449 {
450   libmemif_main_t *lm = &libmemif_main;
451   lm->free = mf;
452 }
453
454 int
455 memif_set_connection_request_timer(struct itimerspec timer)
456 {
457   libmemif_main_t *lm = &libmemif_main;
458   int err = MEMIF_ERR_SUCCESS;
459
460   lm->arm = timer;
461
462   /* overwrite timer, if already armed */
463   if (lm->disconn_slaves != 0)
464     {
465       if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
466         {
467           err = memif_syscall_error_handler (errno);
468         }
469     }
470   return err;
471 }
472
473 int
474 memif_init (memif_control_fd_update_t * on_control_fd_update, char *app_name,
475             memif_alloc_t * memif_alloc, memif_realloc_t * memif_realloc,
476             memif_free_t * memif_free)
477 {
478   int err = MEMIF_ERR_SUCCESS;  /* 0 */
479   libmemif_main_t *lm = &libmemif_main;
480   memset (lm, 0, sizeof (libmemif_main_t));
481
482   if (memif_alloc != NULL)
483     {
484       memif_alloc_register (memif_alloc);
485     }
486   else
487     memif_alloc_register (malloc);
488
489   if (memif_realloc != NULL)
490     {
491       memif_realloc_register (memif_realloc);
492     }
493   else
494     memif_realloc_register (realloc);
495
496   if (memif_free != NULL)
497     memif_free_register (memif_free);
498   else
499     memif_free_register (free);
500
501   if (app_name != NULL)
502     {
503       uint8_t len = (strlen (app_name) > MEMIF_NAME_LEN)
504         ? strlen (app_name) : MEMIF_NAME_LEN;
505       strncpy ((char *) lm->app_name, app_name, len);
506     }
507   else
508     {
509       strncpy ((char *) lm->app_name, MEMIF_DEFAULT_APP_NAME,
510                strlen (MEMIF_DEFAULT_APP_NAME));
511     }
512
513   /* register control fd update callback */
514   if (on_control_fd_update != NULL)
515     memif_control_fd_update_register (on_control_fd_update);
516   else
517     {
518       memif_epfd = epoll_create (1);
519       memif_control_fd_update_register (memif_control_fd_update);
520       if ((poll_cancel_fd = eventfd (0, EFD_NONBLOCK)) < 0)
521         {
522           err = errno;
523           DBG ("eventfd: %s", strerror (err));
524           return memif_syscall_error_handler (err);
525         }
526       lm->control_fd_update (poll_cancel_fd, MEMIF_FD_EVENT_READ);
527       DBG ("libmemif event polling initialized");
528     }
529
530   lm->control_list_len = 2;
531   lm->interrupt_list_len = 2;
532   lm->listener_list_len = 1;
533   lm->pending_list_len = 1;
534
535   lm->control_list =
536     lm->alloc (sizeof (memif_list_elt_t) * lm->control_list_len);
537   if (lm->control_list == NULL)
538     {
539       err = MEMIF_ERR_NOMEM;
540       goto error;
541     }
542   lm->interrupt_list =
543     lm->alloc (sizeof (memif_list_elt_t) * lm->interrupt_list_len);
544   if (lm->interrupt_list == NULL)
545     {
546       err = MEMIF_ERR_NOMEM;
547       goto error;
548     }
549   lm->listener_list =
550     lm->alloc (sizeof (memif_list_elt_t) * lm->listener_list_len);
551   if (lm->listener_list == NULL)
552     {
553       err = MEMIF_ERR_NOMEM;
554       goto error;
555     }
556   lm->pending_list =
557     lm->alloc (sizeof (memif_list_elt_t) * lm->pending_list_len);
558   if (lm->pending_list == NULL)
559     {
560       err = MEMIF_ERR_NOMEM;
561       goto error;
562     }
563
564   int i;
565   for (i = 0; i < lm->control_list_len; i++)
566     {
567       lm->control_list[i].key = -1;
568       lm->control_list[i].data_struct = NULL;
569     }
570   for (i = 0; i < lm->interrupt_list_len; i++)
571     {
572       lm->interrupt_list[i].key = -1;
573       lm->interrupt_list[i].data_struct = NULL;
574     }
575   for (i = 0; i < lm->listener_list_len; i++)
576     {
577       lm->listener_list[i].key = -1;
578       lm->listener_list[i].data_struct = NULL;
579     }
580   for (i = 0; i < lm->pending_list_len; i++)
581     {
582       lm->pending_list[i].key = -1;
583       lm->pending_list[i].data_struct = NULL;
584     }
585
586   lm->disconn_slaves = 0;
587
588   lm->timerfd = timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK);
589   if (lm->timerfd < 0)
590     {
591       err = memif_syscall_error_handler (errno);
592       goto error;
593     }
594
595   lm->arm.it_value.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
596   lm->arm.it_value.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
597   lm->arm.it_interval.tv_sec = MEMIF_DEFAULT_RECONNECT_PERIOD_SEC;
598   lm->arm.it_interval.tv_nsec = MEMIF_DEFAULT_RECONNECT_PERIOD_NSEC;
599
600   if (lm->control_fd_update (lm->timerfd, MEMIF_FD_EVENT_READ) < 0)
601     {
602       DBG ("callback type memif_control_fd_update_t error!");
603       err = MEMIF_ERR_CB_FDUPDATE;
604       goto error;
605     }
606
607   return err;
608
609 error:
610   memif_cleanup ();
611   return err;
612 }
613
614 static inline memif_ring_t *
615 memif_get_ring (memif_connection_t * conn, memif_ring_type_t type,
616                 uint16_t ring_num)
617 {
618   if (&conn->regions[0] == NULL)
619     return NULL;
620   void *p = conn->regions[0].addr;
621   int ring_size =
622     sizeof (memif_ring_t) +
623     sizeof (memif_desc_t) * (1 << conn->run_args.log2_ring_size);
624   p += (ring_num + type * conn->run_args.num_s2m_rings) * ring_size;
625
626   return (memif_ring_t *) p;
627 }
628
629 int
630 memif_set_rx_mode (memif_conn_handle_t c, memif_rx_mode_t rx_mode,
631                    uint16_t qid)
632 {
633   memif_connection_t *conn = (memif_connection_t *) c;
634   if (conn == NULL)
635     return MEMIF_ERR_NOCONN;
636   uint8_t num =
637     (conn->args.is_master) ? conn->run_args.num_s2m_rings : conn->
638     run_args.num_m2s_rings;
639   if (qid >= num)
640     return MEMIF_ERR_QID;
641
642   conn->rx_queues[qid].ring->flags = rx_mode;
643   DBG ("rx_mode flag: %u", conn->rx_queues[qid].ring->flags);
644   return MEMIF_ERR_SUCCESS;
645 }
646
647 int
648 memif_create (memif_conn_handle_t * c, memif_conn_args_t * args,
649               memif_connection_update_t * on_connect,
650               memif_connection_update_t * on_disconnect,
651               memif_interrupt_t * on_interrupt, void *private_ctx)
652 {
653   libmemif_main_t *lm = &libmemif_main;
654   int err, i, index = 0, sockfd = -1;
655   memif_list_elt_t list_elt;
656   memif_connection_t *conn = (memif_connection_t *) * c;
657   if (conn != NULL)
658     {
659       DBG ("This handle already points to existing memif.");
660       return MEMIF_ERR_CONN;
661     }
662   conn = (memif_connection_t *) lm->alloc (sizeof (memif_connection_t));
663   if (conn == NULL)
664     {
665       err = MEMIF_ERR_NOMEM;
666       goto error;
667     }
668   memset (conn, 0, sizeof (memif_connection_t));
669
670   conn->args.interface_id = args->interface_id;
671
672   if (args->log2_ring_size == 0)
673     args->log2_ring_size = MEMIF_DEFAULT_LOG2_RING_SIZE;
674   else if (args->log2_ring_size > MEMIF_MAX_LOG2_RING_SIZE)
675     {
676       err = MEMIF_ERR_MAX_RING;
677       goto error;
678     }
679   if (args->buffer_size == 0)
680     args->buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
681   if (args->num_s2m_rings == 0)
682     args->num_s2m_rings = MEMIF_DEFAULT_TX_QUEUES;
683   if (args->num_m2s_rings == 0)
684     args->num_m2s_rings = MEMIF_DEFAULT_RX_QUEUES;
685
686   conn->args.num_s2m_rings = args->num_s2m_rings;
687   conn->args.num_m2s_rings = args->num_m2s_rings;
688   conn->args.buffer_size = args->buffer_size;
689   conn->args.log2_ring_size = args->log2_ring_size;
690   conn->args.is_master = args->is_master;
691   conn->args.mode = args->mode;
692   conn->msg_queue = NULL;
693   conn->regions = NULL;
694   conn->tx_queues = NULL;
695   conn->rx_queues = NULL;
696   conn->fd = -1;
697   conn->on_connect = on_connect;
698   conn->on_disconnect = on_disconnect;
699   conn->on_interrupt = on_interrupt;
700   conn->private_ctx = private_ctx;
701   memset (&conn->run_args, 0, sizeof (memif_conn_run_args_t));
702
703   uint8_t l = strlen ((char *) args->interface_name);
704   strncpy ((char *) conn->args.interface_name, (char *) args->interface_name,
705            l);
706
707   /* allocate and initialize socket_filename so it can be copyed to sun_path
708      without memory leaks */
709   conn->args.socket_filename = lm->alloc (sizeof (char *) * 108);
710   if (conn->args.socket_filename == NULL)
711     {
712       err = MEMIF_ERR_NOMEM;
713       goto error;
714     }
715   memset (conn->args.socket_filename, 0, 108 * sizeof (char *));
716
717   if (args->socket_filename)
718     {
719       if (conn->args.socket_filename == NULL)
720         {
721           err = memif_syscall_error_handler (errno);
722           goto error;
723         }
724       strncpy ((char *) conn->args.socket_filename,
725                (char *) args->socket_filename,
726                strlen ((char *) args->socket_filename));
727     }
728   else
729     {
730       uint16_t sdl = strlen (MEMIF_DEFAULT_SOCKET_DIR);
731       uint16_t sfl = strlen (MEMIF_DEFAULT_SOCKET_FILENAME);
732       if (conn->args.socket_filename == NULL)
733         {
734           err = memif_syscall_error_handler (errno);
735           goto error;
736         }
737       strncpy ((char *) conn->args.socket_filename,
738                MEMIF_DEFAULT_SOCKET_DIR, sdl);
739       conn->args.socket_filename[sdl] = '/';
740       strncpy ((char *) (conn->args.socket_filename + 1 + sdl),
741                MEMIF_DEFAULT_SOCKET_FILENAME, sfl);
742     }
743
744   if ((l = strlen ((char *) args->secret)) > 0)
745     {
746       strncpy ((char *) conn->args.secret, (char *) args->secret, l);
747     }
748
749   if (conn->args.is_master)
750     {
751       conn->run_args.buffer_size = conn->args.buffer_size;
752       memif_socket_t *ms;
753       memif_list_elt_t elt;
754       for (i = 0; i < lm->listener_list_len; i++)
755         {
756           if ((ms =
757                (memif_socket_t *) lm->listener_list[i].data_struct) != NULL)
758             {
759               if (strncmp
760                   ((char *) ms->filename, (char *) conn->args.socket_filename,
761                    strlen ((char *) ms->filename)) == 0)
762                 {
763                   /* add interface to listener socket */
764                   elt.key = conn->args.interface_id;
765                   *c = elt.data_struct = conn;
766                   add_list_elt (&elt, &ms->interface_list,
767                                 &ms->interface_list_len);
768                   ms->use_count++;
769                   conn->listener_fd = ms->fd;
770                   break;
771                 }
772             }
773           else
774             {
775               struct stat file_stat;
776               if (stat ((char *) conn->args.socket_filename, &file_stat) == 0)
777                 {
778                   if (S_ISSOCK (file_stat.st_mode))
779                     unlink ((char *) conn->args.socket_filename);
780                   else
781                     return memif_syscall_error_handler (errno);
782                 }
783               DBG ("creating socket file");
784               ms = lm->alloc (sizeof (memif_socket_t));
785               if (ms == NULL)
786                 {
787                   err = MEMIF_ERR_NOMEM;
788                   goto error;
789                 }
790               ms->filename =
791                 lm->alloc (strlen ((char *) conn->args.socket_filename) +
792                            sizeof (char));
793               if (ms->filename == NULL)
794                 {
795                   err = MEMIF_ERR_NOMEM;
796                   goto error;
797                 }
798               memset (ms->filename, 0,
799                       strlen ((char *) conn->args.socket_filename) +
800                       sizeof (char));
801               strncpy ((char *) ms->filename,
802                        (char *) conn->args.socket_filename,
803                        strlen ((char *) conn->args.socket_filename));
804               ms->interface_list_len = 1;
805               ms->interface_list =
806                 lm->alloc (sizeof (memif_list_elt_t) *
807                            ms->interface_list_len);
808               if (ms->interface_list == NULL)
809                 {
810                   err = MEMIF_ERR_NOMEM;
811                   goto error;
812                 }
813               ms->interface_list[0].key = -1;
814               ms->interface_list[0].data_struct = NULL;
815               struct sockaddr_un un = { 0 };
816               int on = 1;
817
818               ms->fd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
819               if (ms->fd < 0)
820                 {
821                   err = memif_syscall_error_handler (errno);
822                   goto error;
823                 }
824               DBG ("socket %d created", ms->fd);
825               un.sun_family = AF_UNIX;
826               strncpy ((char *) un.sun_path, (char *) ms->filename,
827                        sizeof (un.sun_path) - 1);
828               DBG ("sockopt");
829               if (setsockopt
830                   (ms->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)) < 0)
831                 {
832                   err = memif_syscall_error_handler (errno);
833                   goto error;
834                 }
835               DBG ("bind");
836               if (bind (ms->fd, (struct sockaddr *) &un, sizeof (un)) < 0)
837                 {
838                   err = memif_syscall_error_handler (errno);
839                   goto error;
840                 }
841               DBG ("listen");
842               if (listen (ms->fd, 1) < 0)
843                 {
844                   err = memif_syscall_error_handler (errno);
845                   goto error;
846                 }
847               DBG ("stat");
848               if (stat ((char *) ms->filename, &file_stat) < 0)
849                 {
850                   err = memif_syscall_error_handler (errno);
851                   goto error;
852                 }
853
854               /* add interface to listener socket */
855               elt.key = conn->args.interface_id;
856               *c = elt.data_struct = conn;
857               add_list_elt (&elt, &ms->interface_list,
858                             &ms->interface_list_len);
859               ms->use_count = 1;
860               conn->listener_fd = ms->fd;
861
862               /* add listener socket to libmemif main */
863               elt.key = ms->fd;
864               elt.data_struct = ms;
865               add_list_elt (&elt, &lm->listener_list, &lm->listener_list_len);
866               lm->control_fd_update (ms->fd, MEMIF_FD_EVENT_READ);
867               break;
868             }
869         }
870     }
871   else
872     {
873       lm->disconn_slaves++;
874
875       list_elt.key = -1;
876       *c = list_elt.data_struct = conn;
877       if ((index =
878            add_list_elt (&list_elt, &lm->control_list,
879                          &lm->control_list_len)) < 0)
880         {
881           err = MEMIF_ERR_NOMEM;
882           goto error;
883         }
884
885       conn->index = index;
886
887       /* try connectiong to master */
888       err = memif_request_connection(conn);
889       if ((err < 0) && (lm->disconn_slaves == 1))
890         {
891           /* connection failed, arm reconnect timer (if not armed) */
892           if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
893             {
894               err = memif_syscall_error_handler (errno);
895               goto error;
896             }
897         }
898     }
899
900   return 0;
901
902 error:
903   if (sockfd > 0)
904     close (sockfd);
905   sockfd = -1;
906   if (conn->args.socket_filename)
907     lm->free (conn->args.socket_filename);
908   if (conn != NULL)
909     lm->free (conn);
910   *c = conn = NULL;
911   return err;
912 }
913
914 int
915 memif_request_connection(memif_conn_handle_t c)
916 {
917   libmemif_main_t *lm = &libmemif_main;
918   memif_connection_t *conn = (memif_connection_t *) c;
919   int err = MEMIF_ERR_SUCCESS;
920   int sockfd = -1;
921   struct sockaddr_un sun;
922
923   if (conn->args.is_master)
924     return MEMIF_ERR_INVAL_ARG;
925   if (conn->fd > 0)
926     return MEMIF_ERR_ALRCONN;
927
928   sockfd = socket (AF_UNIX, SOCK_SEQPACKET, 0);
929   if (sockfd < 0)
930     {
931       err = memif_syscall_error_handler (errno);
932       goto error;
933     }
934
935   sun.sun_family = AF_UNIX;
936
937   strncpy (sun.sun_path, (char *) conn->args.socket_filename,
938            sizeof (sun.sun_path) - 1);
939
940   if (connect (sockfd, (struct sockaddr *) &sun,
941       sizeof (struct sockaddr_un)) == 0)
942     {
943       conn->fd = sockfd;
944       conn->read_fn = memif_conn_fd_read_ready;
945       conn->write_fn = memif_conn_fd_write_ready;
946       conn->error_fn = memif_conn_fd_error;
947
948       lm->control_list[conn->index].key = conn->fd;
949
950       lm->control_fd_update (sockfd,
951                 MEMIF_FD_EVENT_READ |
952                 MEMIF_FD_EVENT_WRITE);
953
954       lm->disconn_slaves--;
955       if (lm->disconn_slaves == 0)
956         {
957           if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
958             {
959               err = memif_syscall_error_handler (errno);
960               return err;
961             }
962         }
963     }
964   else
965     {
966       strcpy ((char *) conn->remote_disconnect_string,
967           memif_strerror (memif_syscall_error_handler
968                   (errno)));
969       goto error;
970     }
971
972  return err;
973
974 error:
975   if (sockfd > 0)
976     close (sockfd);
977   sockfd = -1;
978   return err;
979 }
980
981 int
982 memif_control_fd_handler (int fd, uint8_t events)
983 {
984   int i, err = MEMIF_ERR_SUCCESS;       /* 0 */
985   uint16_t num;
986   memif_list_elt_t *e = NULL;
987   memif_connection_t *conn;
988   libmemif_main_t *lm = &libmemif_main;
989   if (fd == lm->timerfd)
990     {
991       uint64_t b;
992       ssize_t size;
993       size = read (fd, &b, sizeof (b));
994
995       if (size == -1)
996         goto error;
997
998       for (i = 0; i < lm->control_list_len; i++)
999         {
1000           if ((lm->control_list[i].key < 0)
1001               && (lm->control_list[i].data_struct != NULL))
1002             {
1003               conn = lm->control_list[i].data_struct;
1004               if (conn->args.is_master)
1005                 continue;
1006               memif_request_connection(conn);
1007             }
1008         }
1009     }
1010   else
1011     {
1012       get_list_elt (&e, lm->interrupt_list, lm->interrupt_list_len, fd);
1013       if (e != NULL)
1014         {
1015           if (((memif_connection_t *) e->data_struct)->on_interrupt != NULL)
1016             {
1017               num =
1018                 (((memif_connection_t *) e->data_struct)->
1019                  args.is_master) ? ((memif_connection_t *) e->
1020                                     data_struct)->run_args.
1021                 num_s2m_rings : ((memif_connection_t *) e->data_struct)->
1022                 run_args.num_m2s_rings;
1023               for (i = 0; i < num; i++)
1024                 {
1025                   if (((memif_connection_t *) e->data_struct)->
1026                       rx_queues[i].int_fd == fd)
1027                     {
1028                       ((memif_connection_t *) e->data_struct)->
1029                         on_interrupt ((void *) e->data_struct,
1030                                       ((memif_connection_t *) e->
1031                                        data_struct)->private_ctx, i);
1032                       return MEMIF_ERR_SUCCESS;
1033                     }
1034                 }
1035             }
1036           return MEMIF_ERR_SUCCESS;
1037         }
1038       get_list_elt (&e, lm->listener_list, lm->listener_list_len, fd);
1039       if (e != NULL)
1040         {
1041           err = memif_conn_fd_accept_ready ((memif_socket_t *) e->data_struct);
1042           return err;
1043         }
1044
1045       get_list_elt (&e, lm->pending_list, lm->pending_list_len, fd);
1046       if (e != NULL)
1047         {
1048           err = memif_read_ready (fd);
1049           return err;
1050         }
1051
1052       get_list_elt (&e, lm->control_list, lm->control_list_len, fd);
1053       if (e != NULL)
1054         {
1055           if (events & MEMIF_FD_EVENT_READ)
1056             {
1057               err =
1058                 ((memif_connection_t *) e->data_struct)->
1059                 read_fn (e->data_struct);
1060               if (err != MEMIF_ERR_SUCCESS)
1061                 return err;
1062             }
1063           if (events & MEMIF_FD_EVENT_WRITE)
1064             {
1065               err =
1066                 ((memif_connection_t *) e->data_struct)->
1067                 write_fn (e->data_struct);
1068               if (err != MEMIF_ERR_SUCCESS)
1069                 return err;
1070             }
1071           if (events & MEMIF_FD_EVENT_ERROR)
1072             {
1073               err =
1074                 ((memif_connection_t *) e->data_struct)->
1075                 error_fn (e->data_struct);
1076               if (err != MEMIF_ERR_SUCCESS)
1077                 return err;
1078             }
1079         }
1080     }
1081
1082   return MEMIF_ERR_SUCCESS;     /* 0 */
1083
1084 error:
1085   return err;
1086 }
1087
1088 int
1089 memif_poll_event (int timeout)
1090 {
1091   struct epoll_event evt;
1092   int en = 0, err = MEMIF_ERR_SUCCESS;  /* 0 */
1093   uint32_t events = 0;
1094   uint64_t counter = 0;
1095   ssize_t r = 0;
1096   memset (&evt, 0, sizeof (evt));
1097   evt.events = EPOLLIN | EPOLLOUT;
1098   sigset_t sigset;
1099   sigemptyset (&sigset);
1100   en = epoll_pwait (memif_epfd, &evt, 1, timeout, &sigset);
1101   if (en < 0)
1102     {
1103       err = errno;
1104       DBG ("epoll_pwait: %s", strerror (err));
1105       return memif_syscall_error_handler (err);
1106     }
1107   if (en > 0)
1108     {
1109       if (evt.data.fd == poll_cancel_fd)
1110         {
1111           r = read (evt.data.fd, &counter, sizeof (counter));
1112           if (r == -1)
1113             return MEMIF_ERR_DISCONNECTED;
1114
1115           return MEMIF_ERR_POLL_CANCEL;
1116         }
1117       if (evt.events & EPOLLIN)
1118         events |= MEMIF_FD_EVENT_READ;
1119       if (evt.events & EPOLLOUT)
1120         events |= MEMIF_FD_EVENT_WRITE;
1121       if (evt.events & EPOLLERR)
1122         events |= MEMIF_FD_EVENT_ERROR;
1123       err = memif_control_fd_handler (evt.data.fd, events);
1124       return err;
1125     }
1126   return 0;
1127 }
1128
1129 int
1130 memif_cancel_poll_event ()
1131 {
1132   uint64_t counter = 1;
1133   ssize_t w = 0;
1134
1135   if (poll_cancel_fd == -1)
1136     return 0;
1137   w = write (poll_cancel_fd, &counter, sizeof (counter));
1138   if (w < sizeof (counter))
1139     return MEMIF_ERR_INT_WRITE;
1140
1141   return 0;
1142 }
1143
1144 static void
1145 memif_msg_queue_free (libmemif_main_t * lm, memif_msg_queue_elt_t ** e)
1146 {
1147   if (*e == NULL)
1148     return;
1149   memif_msg_queue_free (lm, &(*e)->next);
1150   lm->free (*e);
1151   *e = NULL;
1152   return;
1153 }
1154
1155 /* send disconnect msg and close interface */
1156 int
1157 memif_disconnect_internal (memif_connection_t * c)
1158 {
1159   if (c == NULL)
1160     {
1161       DBG ("no connection");
1162       return MEMIF_ERR_NOCONN;
1163     }
1164   uint16_t num;
1165   int err = MEMIF_ERR_SUCCESS, i;       /* 0 */
1166   memif_queue_t *mq;
1167   libmemif_main_t *lm = &libmemif_main;
1168   memif_list_elt_t *e;
1169
1170   c->on_disconnect ((void *) c, c->private_ctx);
1171
1172   if (c->fd > 0)
1173     {
1174       memif_msg_send_disconnect (c->fd, (uint8_t *) "interface deleted", 0);
1175       lm->control_fd_update (c->fd, MEMIF_FD_EVENT_DEL);
1176       close (c->fd);
1177     }
1178   get_list_elt (&e, lm->control_list, lm->control_list_len, c->fd);
1179   if (e != NULL)
1180     {
1181       if (c->args.is_master)
1182         free_list_elt (lm->control_list, lm->control_list_len, c->fd);
1183       e->key = c->fd = -1;
1184     }
1185
1186   if (c->tx_queues != NULL)
1187     {
1188       num =
1189         (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1190         run_args.num_s2m_rings;
1191       for (i = 0; i < num; i++)
1192         {
1193           mq = &c->tx_queues[i];
1194           if (mq != NULL)
1195             {
1196               if (mq->int_fd > 0)
1197                 close (mq->int_fd);
1198               free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1199                              mq->int_fd);
1200               mq->int_fd = -1;
1201             }
1202         }
1203       lm->free (c->tx_queues);
1204       c->tx_queues = NULL;
1205     }
1206
1207   if (c->rx_queues != NULL)
1208     {
1209       num =
1210         (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1211         run_args.num_m2s_rings;
1212       for (i = 0; i < num; i++)
1213         {
1214           mq = &c->rx_queues[i];
1215           if (mq != NULL)
1216             {
1217               if (mq->int_fd > 0)
1218                 {
1219                   if (c->on_interrupt != NULL)
1220                     lm->control_fd_update (mq->int_fd, MEMIF_FD_EVENT_DEL);
1221                   close (mq->int_fd);
1222                 }
1223               free_list_elt (lm->interrupt_list, lm->interrupt_list_len,
1224                              mq->int_fd);
1225               mq->int_fd = -1;
1226             }
1227         }
1228       lm->free (c->rx_queues);
1229       c->rx_queues = NULL;
1230     }
1231
1232   for (i = 0; i < c->regions_num; i++)
1233     {
1234       if (&c->regions[i] == NULL)
1235         continue;
1236       if (c->regions[i].is_external != 0)
1237         {
1238           lm->del_external_region (c->regions[i].addr,
1239                                    c->regions[i].region_size,
1240                                    c->regions[i].fd, c->private_ctx);
1241         }
1242       else
1243         {
1244           if (munmap (c->regions[i].addr, c->regions[i].region_size) < 0)
1245             return memif_syscall_error_handler (errno);
1246           if (c->regions[i].fd > 0)
1247             close (c->regions[i].fd);
1248           c->regions[i].fd = -1;
1249         }
1250     }
1251   lm->free (c->regions);
1252   c->regions = NULL;
1253   c->regions_num = 0;
1254
1255   memset (&c->run_args, 0, sizeof (memif_conn_run_args_t));
1256
1257   memif_msg_queue_free (lm, &c->msg_queue);
1258
1259   if (!(c->args.is_master))
1260     {
1261       if (lm->disconn_slaves == 0)
1262         {
1263           if (timerfd_settime (lm->timerfd, 0, &lm->arm, NULL) < 0)
1264             {
1265               err = memif_syscall_error_handler (errno);
1266               DBG ("timerfd_settime: arm");
1267             }
1268         }
1269       lm->disconn_slaves++;
1270     }
1271
1272   return err;
1273 }
1274
1275 int
1276 memif_delete (memif_conn_handle_t * conn)
1277 {
1278   memif_connection_t *c = (memif_connection_t *) * conn;
1279   if (c == NULL)
1280     {
1281       DBG ("no connection");
1282       return MEMIF_ERR_NOCONN;
1283     }
1284   libmemif_main_t *lm = &libmemif_main;
1285   memif_list_elt_t *e = NULL;
1286   memif_socket_t *ms = NULL;
1287
1288   int err = MEMIF_ERR_SUCCESS;
1289
1290   if (c->fd > 0)
1291     {
1292       DBG ("DISCONNECTING");
1293       err = memif_disconnect_internal (c);
1294       if (err == MEMIF_ERR_NOCONN)
1295         return err;
1296     }
1297
1298   free_list_elt_ctx (lm->control_list, lm->control_list_len, c);
1299
1300   if (c->args.is_master)
1301     {
1302       get_list_elt (&e, lm->listener_list, lm->listener_list_len,
1303                     c->listener_fd);
1304       if (e != NULL)
1305         {
1306           ms = (memif_socket_t *) e->data_struct;
1307           ms->use_count--;
1308           free_list_elt (ms->interface_list, ms->interface_list_len,
1309                          c->args.interface_id);
1310           if (ms->use_count <= 0)
1311             {
1312               lm->control_fd_update (c->listener_fd, MEMIF_FD_EVENT_DEL);
1313               free_list_elt (lm->listener_list, lm->listener_list_len,
1314                              c->listener_fd);
1315               close (c->listener_fd);
1316               c->listener_fd = ms->fd = -1;
1317               lm->free (ms->interface_list);
1318               ms->interface_list = NULL;
1319               lm->free (ms->filename);
1320               ms->filename = NULL;
1321               lm->free (ms);
1322               ms = NULL;
1323             }
1324         }
1325     }
1326   else
1327     {
1328       lm->disconn_slaves--;
1329       if (lm->disconn_slaves <= 0)
1330         {
1331           if (timerfd_settime (lm->timerfd, 0, &lm->disarm, NULL) < 0)
1332             {
1333               err = memif_syscall_error_handler (errno);
1334               DBG ("timerfd_settime: disarm");
1335             }
1336         }
1337     }
1338
1339   if (c->args.socket_filename)
1340     lm->free (c->args.socket_filename);
1341   c->args.socket_filename = NULL;
1342
1343   lm->free (c);
1344   c = NULL;
1345
1346   *conn = c;
1347   return err;
1348 }
1349
1350 int
1351 memif_connect1 (memif_connection_t * c)
1352 {
1353   libmemif_main_t *lm = &libmemif_main;
1354   memif_region_t *mr;
1355   memif_queue_t *mq;
1356   int i;
1357
1358   for (i = 0; i < c->regions_num; i++)
1359     {
1360       mr = &c->regions[i];
1361       if (mr != NULL)
1362         {
1363           if (!mr->addr)
1364             {
1365               if (mr->is_external)
1366                 {
1367                   if (lm->get_external_region_addr == NULL)
1368                     return 99;  /* FIXME: proper error report */
1369                   mr->addr =
1370                     lm->get_external_region_addr (mr->region_size, mr->fd,
1371                                                   c->private_ctx);
1372                 }
1373               else
1374                 {
1375                   if (mr->fd < 0)
1376                     return MEMIF_ERR_NO_SHMFD;
1377
1378                   if ((mr->addr =
1379                        mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
1380                              MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
1381                     {
1382                       return memif_syscall_error_handler (errno);
1383                     }
1384                 }
1385             }
1386         }
1387     }
1388
1389   for (i = 0; i < c->rx_queues_num; i++)
1390     {
1391       mq = &c->rx_queues[i];
1392       if (mq != NULL)
1393         {
1394           mq->ring = c->regions[mq->region].addr + mq->offset;
1395           if (mq->ring->cookie != MEMIF_COOKIE)
1396             {
1397               DBG ("wrong cookie on rx ring %u", i);
1398               return MEMIF_ERR_COOKIE;
1399             }
1400           mq->ring->head = mq->ring->tail = mq->last_head = mq->alloc_bufs =
1401             0;
1402         }
1403     }
1404
1405   for (i = 0; i < c->tx_queues_num; i++)
1406     {
1407       mq = &c->tx_queues[i];
1408       if (mq != NULL)
1409         {
1410           mq->ring = c->regions[mq->region].addr + mq->offset;
1411           if (mq->ring->cookie != MEMIF_COOKIE)
1412             {
1413               DBG ("wrong cookie on tx ring %u", i);
1414               return MEMIF_ERR_COOKIE;
1415             }
1416           mq->ring->head = mq->ring->tail = mq->last_head = mq->alloc_bufs =
1417             0;
1418         }
1419     }
1420
1421   lm->control_fd_update (c->fd, MEMIF_FD_EVENT_READ | MEMIF_FD_EVENT_MOD);
1422
1423   return 0;
1424 }
1425
1426 static inline int
1427 memif_add_region (libmemif_main_t * lm, memif_connection_t * conn,
1428                   uint8_t has_buffers)
1429 {
1430   memif_region_t *r;
1431
1432   r =
1433     lm->realloc (conn->regions,
1434                  sizeof (memif_region_t) * ++conn->regions_num);
1435   if (r == NULL)
1436     return MEMIF_ERR_NOMEM;
1437
1438   conn->regions = r;
1439   r = &conn->regions[conn->regions_num - 1];
1440   memset (r, 0, sizeof (memif_region_t));
1441
1442   if (has_buffers != 0)
1443     {
1444       r->buffer_offset = 0;
1445     }
1446   else
1447     {
1448       r->buffer_offset =
1449         (conn->run_args.num_s2m_rings +
1450          conn->run_args.num_m2s_rings) * (sizeof (memif_ring_t) +
1451                                           sizeof (memif_desc_t) *
1452                                           (1 << conn->
1453                                            run_args.log2_ring_size));
1454     }
1455
1456   r->region_size = (has_buffers == 0) ? r->buffer_offset : r->buffer_offset +
1457     conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1458     (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1459
1460   if ((r->fd = memfd_create ("memif region 0", MFD_ALLOW_SEALING)) == -1)
1461     return memif_syscall_error_handler (errno);
1462
1463   if ((fcntl (r->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)
1464     return memif_syscall_error_handler (errno);
1465
1466   if ((ftruncate (r->fd, r->region_size)) == -1)
1467     return memif_syscall_error_handler (errno);
1468
1469   if ((r->addr = mmap (NULL, r->region_size, PROT_READ | PROT_WRITE,
1470                        MAP_SHARED, r->fd, 0)) == MAP_FAILED)
1471     return memif_syscall_error_handler (errno);
1472
1473   return MEMIF_ERR_SUCCESS;
1474 }
1475
1476 static inline int
1477 memif_init_queues (libmemif_main_t * lm, memif_connection_t * conn)
1478 {
1479   int i, j;
1480   memif_ring_t *ring;
1481
1482   for (i = 0; i < conn->run_args.num_s2m_rings; i++)
1483     {
1484       ring = memif_get_ring (conn, MEMIF_RING_S2M, i);
1485       DBG ("RING: %p I: %d", ring, i);
1486       ring->head = ring->tail = 0;
1487       ring->cookie = MEMIF_COOKIE;
1488       ring->flags = 0;
1489       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1490         {
1491           uint16_t slot = i * (1 << conn->run_args.log2_ring_size) + j;
1492           ring->desc[j].region = 1;
1493           ring->desc[j].offset =
1494             conn->regions[1].buffer_offset +
1495             (uint32_t) (slot * conn->run_args.buffer_size);
1496           ring->desc[j].length = conn->run_args.buffer_size;
1497         }
1498     }
1499   for (i = 0; i < conn->run_args.num_m2s_rings; i++)
1500     {
1501       ring = memif_get_ring (conn, MEMIF_RING_M2S, i);
1502       DBG ("RING: %p I: %d", ring, i);
1503       ring->head = ring->tail = 0;
1504       ring->cookie = MEMIF_COOKIE;
1505       ring->flags = 0;
1506       for (j = 0; j < (1 << conn->run_args.log2_ring_size); j++)
1507         {
1508           uint16_t slot = (i + conn->run_args.num_s2m_rings) *
1509             (1 << conn->run_args.log2_ring_size) + j;
1510           ring->desc[j].region = 1;
1511           ring->desc[j].offset =
1512             conn->regions[1].buffer_offset +
1513             (uint32_t) (slot * conn->run_args.buffer_size);
1514           ring->desc[j].length = conn->run_args.buffer_size;
1515         }
1516     }
1517   memif_queue_t *mq;
1518   DBG ("alloc: %p", lm->alloc);
1519   DBG ("size: %lu", sizeof (memif_queue_t) * conn->run_args.num_s2m_rings);
1520   mq =
1521     (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
1522                                  conn->run_args.num_s2m_rings);
1523   if (mq == NULL)
1524     return MEMIF_ERR_NOMEM;
1525
1526   int x;
1527   memif_list_elt_t e;
1528   for (x = 0; x < conn->run_args.num_s2m_rings; x++)
1529     {
1530       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1531         return memif_syscall_error_handler (errno);
1532       e.key = mq[x].int_fd;
1533       e.data_struct = conn;
1534       add_list_elt (&e, &lm->interrupt_list, &lm->interrupt_list_len);
1535
1536       mq[x].ring = memif_get_ring (conn, MEMIF_RING_S2M, x);
1537       DBG ("RING: %p I: %d", mq[x].ring, x);
1538       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1539       mq[x].region = 0;
1540       mq[x].offset =
1541         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1542       mq[x].last_head = mq[x].last_tail = 0;
1543       mq[x].alloc_bufs = 0;
1544     }
1545   conn->tx_queues = mq;
1546
1547   mq =
1548     (memif_queue_t *) lm->alloc (sizeof (memif_queue_t) *
1549                                  conn->run_args.num_m2s_rings);
1550   if (mq == NULL)
1551     return MEMIF_ERR_NOMEM;
1552
1553   for (x = 0; x < conn->run_args.num_m2s_rings; x++)
1554     {
1555       if ((mq[x].int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
1556         return memif_syscall_error_handler (errno);
1557       e.key = mq[x].int_fd;
1558       e.data_struct = conn;
1559       add_list_elt (&e, &lm->interrupt_list, &lm->interrupt_list_len);
1560
1561       mq[x].ring = memif_get_ring (conn, MEMIF_RING_M2S, x);
1562       DBG ("RING: %p I: %d", mq[x].ring, x);
1563       mq[x].log2_ring_size = conn->run_args.log2_ring_size;
1564       mq[x].region = 0;
1565       mq[x].offset =
1566         (void *) mq[x].ring - (void *) conn->regions[mq->region].addr;
1567       mq[x].last_head = mq[x].last_tail = 0;
1568       mq[x].alloc_bufs = 0;
1569     }
1570   conn->rx_queues = mq;
1571
1572   return MEMIF_ERR_SUCCESS;
1573 }
1574
1575 int
1576 memif_init_regions_and_queues (memif_connection_t * conn)
1577 {
1578   memif_region_t *r;
1579   libmemif_main_t *lm = &libmemif_main;
1580
1581   /* region 0. rings */
1582   memif_add_region (lm, conn, /* has_buffers */ 0);
1583
1584   /* region 1. buffers */
1585   if (lm->add_external_region)
1586     {
1587       r =
1588         (memif_region_t *) lm->realloc (conn->regions,
1589                                         sizeof (memif_region_t) *
1590                                         ++conn->regions_num);
1591       if (r == NULL)
1592         return MEMIF_ERR_NOMEM;
1593       conn->regions = r;
1594
1595       conn->regions[1].region_size =
1596         conn->run_args.buffer_size * (1 << conn->run_args.log2_ring_size) *
1597         (conn->run_args.num_s2m_rings + conn->run_args.num_m2s_rings);
1598       conn->regions[1].buffer_offset = 0;
1599       lm->add_external_region (&conn->regions[1].addr,
1600                                conn->regions[1].region_size,
1601                                &conn->regions[1].fd, conn->private_ctx);
1602       conn->regions[1].is_external = 1;
1603     }
1604   else
1605     {
1606       memif_add_region (lm, conn, 1);
1607     }
1608
1609   memif_init_queues (lm, conn);
1610
1611   return 0;
1612 }
1613
1614 int
1615 memif_buffer_enq_tx (memif_conn_handle_t conn, uint16_t qid,
1616                      memif_buffer_t * bufs, uint16_t count,
1617                      uint16_t * count_out)
1618 {
1619   memif_connection_t *c = (memif_connection_t *) conn;
1620   if (EXPECT_FALSE (c == NULL))
1621     return MEMIF_ERR_NOCONN;
1622   if (EXPECT_FALSE (c->fd < 0))
1623     return MEMIF_ERR_DISCONNECTED;
1624   uint8_t num =
1625     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1626     run_args.num_s2m_rings;
1627   if (EXPECT_FALSE (qid >= num))
1628     return MEMIF_ERR_QID;
1629   if (EXPECT_FALSE (!count_out))
1630     return MEMIF_ERR_INVAL_ARG;
1631   if (EXPECT_FALSE (c->args.is_master))
1632     return MEMIF_ERR_INVAL_ARG;
1633
1634   memif_queue_t *mq = &c->tx_queues[qid];
1635   memif_ring_t *ring = mq->ring;
1636   memif_buffer_t *b0;
1637   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1638   uint16_t ring_size;
1639   uint16_t slot, ns;
1640   int err = MEMIF_ERR_SUCCESS;  /* 0 */
1641   *count_out = 0;
1642
1643   ring_size = (1 << mq->log2_ring_size);
1644   slot = (c->args.is_master) ? ring->tail : ring->head;
1645   slot += mq->alloc_bufs;
1646
1647   /* can only be called by slave */
1648   ns = ring_size - (ring->head + mq->alloc_bufs) + ring->tail;
1649
1650   b0 = bufs;
1651
1652   while (count && ns)
1653     {
1654       if (EXPECT_FALSE ((b0->flags & MEMIF_BUFFER_FLAG_RX) == 0))
1655         {
1656           /* not a valid buffer */
1657           count--;
1658           continue;
1659         }
1660       b0->flags &= ~MEMIF_BUFFER_FLAG_RX;
1661
1662       ((memif_ring_t *) b0->ring)->desc[b0->desc_index & mask].offset = ring->desc[slot & mask].offset; /* put free buffer on rx ring */
1663
1664       ring->desc[slot & mask].offset =
1665         (uint32_t) (b0->data -
1666                     c->regions[ring->desc[slot & mask].region].addr);
1667       ring->desc[slot & mask].flags |=
1668         (b0->flags & MEMIF_BUFFER_FLAG_NEXT) ? MEMIF_DESC_FLAG_NEXT : 0;
1669
1670       b0->desc_index = slot;
1671
1672       mq->alloc_bufs++;
1673       slot++;
1674
1675       count--;
1676       ns--;
1677       b0++;
1678       *count_out += 1;
1679     }
1680
1681   DBG ("allocated: %u/%u bufs. Total %u allocated bufs", *count_out, count,
1682        mq->alloc_bufs);
1683
1684   if (count)
1685     {
1686       DBG ("ring buffer full! qid: %u", qid);
1687       err = MEMIF_ERR_NOBUF_RING;
1688     }
1689
1690   return err;
1691 }
1692
1693 int
1694 memif_buffer_alloc (memif_conn_handle_t conn, uint16_t qid,
1695                     memif_buffer_t * bufs, uint16_t count,
1696                     uint16_t * count_out, uint16_t size)
1697 {
1698   memif_connection_t *c = (memif_connection_t *) conn;
1699   if (EXPECT_FALSE (c == NULL))
1700     return MEMIF_ERR_NOCONN;
1701   if (EXPECT_FALSE (c->fd < 0))
1702     return MEMIF_ERR_DISCONNECTED;
1703   uint8_t num =
1704     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1705     run_args.num_s2m_rings;
1706   if (EXPECT_FALSE (qid >= num))
1707     return MEMIF_ERR_QID;
1708   if (EXPECT_FALSE (!count_out))
1709     return MEMIF_ERR_INVAL_ARG;
1710
1711   libmemif_main_t *lm = &libmemif_main;
1712   memif_queue_t *mq = &c->tx_queues[qid];
1713   memif_ring_t *ring = mq->ring;
1714   memif_buffer_t *b0;
1715   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1716   uint32_t offset_mask = c->run_args.buffer_size - 1;
1717   uint16_t ring_size;
1718   uint16_t slot, ns;
1719   int err = MEMIF_ERR_SUCCESS;  /* 0 */
1720   uint16_t dst_left, src_left;
1721   uint16_t saved_count;
1722   memif_buffer_t *saved_b;
1723   *count_out = 0;
1724
1725   ring_size = (1 << mq->log2_ring_size);
1726   slot = (c->args.is_master) ? ring->tail : ring->head;
1727   slot += mq->alloc_bufs;
1728
1729   if (c->args.is_master)
1730     ns = ring->head - (ring->tail + mq->alloc_bufs);
1731   else
1732     ns = ring_size - (ring->head + mq->alloc_bufs) + ring->tail;
1733
1734   while (count && ns)
1735     {
1736       b0 = (bufs + *count_out);
1737
1738       saved_b = b0;
1739       saved_count = count;
1740
1741       b0->desc_index = slot;
1742       ring->desc[slot & mask].flags = 0;
1743
1744       /* slave can produce buffer with original length */
1745       dst_left = (c->args.is_master) ? ring->desc[slot & mask].length :
1746         c->run_args.buffer_size;
1747       src_left = size;
1748
1749       while (src_left)
1750         {
1751           if (EXPECT_FALSE (dst_left == 0))
1752             {
1753               if (count && ns)
1754                 {
1755                   slot++;
1756                   *count_out += 1;
1757                   mq->alloc_bufs++;
1758                   ns--;
1759
1760                   ring->desc[b0->desc_index & mask].flags |=
1761                     MEMIF_DESC_FLAG_NEXT;
1762                   b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1763
1764                   b0 = (bufs + *count_out);
1765                   b0->desc_index = slot;
1766                   dst_left =
1767                     (c->args.is_master) ? ring->desc[slot & mask].
1768                     length : c->run_args.buffer_size;
1769                   ring->desc[slot & mask].flags = 0;
1770                 }
1771               else
1772                 {
1773                   /* rollback allocated chain buffers */
1774                   memset (saved_b, 0, sizeof (memif_buffer_t)
1775                           * (saved_count - count + 1));
1776                   *count_out -= saved_count - count;
1777                   mq->alloc_bufs = saved_count - count;
1778                   goto no_ns;
1779                 }
1780             }
1781           b0->len = memif_min (dst_left, src_left);
1782
1783           /* slave resets buffer offset */
1784           if (c->args.is_master == 0)
1785             {
1786               memif_desc_t *d = &ring->desc[slot & mask];
1787               if (lm->get_external_buffer_offset)
1788                 d->offset = lm->get_external_buffer_offset (c->private_ctx);
1789               else
1790                 d->offset = d->offset - (d->offset & offset_mask);
1791             }
1792           b0->data = memif_get_buffer (c, ring, slot & mask);
1793
1794           src_left -= b0->len;
1795           dst_left -= b0->len;
1796         }
1797
1798       slot++;
1799       *count_out += 1;
1800       mq->alloc_bufs++;
1801       ns--;
1802       count--;
1803     }
1804
1805 no_ns:
1806
1807   DBG ("allocated: %u/%u bufs. Total %u allocated bufs", *count_out, count,
1808        mq->alloc_bufs);
1809
1810   if (count)
1811     {
1812       DBG ("ring buffer full! qid: %u", qid);
1813       err = MEMIF_ERR_NOBUF_RING;
1814     }
1815
1816   return err;
1817 }
1818
1819 int
1820 memif_refill_queue (memif_conn_handle_t conn, uint16_t qid, uint16_t count,
1821                     uint16_t headroom)
1822 {
1823   memif_connection_t *c = (memif_connection_t *) conn;
1824   if (EXPECT_FALSE (c == NULL))
1825     return MEMIF_ERR_NOCONN;
1826   if (EXPECT_FALSE (c->fd < 0))
1827     return MEMIF_ERR_DISCONNECTED;
1828   uint8_t num =
1829     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1830     run_args.num_m2s_rings;
1831   if (EXPECT_FALSE (qid >= num))
1832     return MEMIF_ERR_QID;
1833   libmemif_main_t *lm = &libmemif_main;
1834   memif_queue_t *mq = &c->rx_queues[qid];
1835   memif_ring_t *ring = mq->ring;
1836   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1837   uint32_t offset_mask = c->run_args.buffer_size - 1;
1838   uint16_t slot;
1839
1840   if (c->args.is_master)
1841     {
1842       MEMIF_MEMORY_BARRIER ();
1843       ring->tail =
1844         (ring->tail + count <=
1845          mq->last_head) ? ring->tail + count : mq->last_head;
1846       return MEMIF_ERR_SUCCESS;
1847     }
1848
1849   uint16_t head = ring->head;
1850   uint16_t ns = (1 << mq->log2_ring_size) - head + mq->last_tail;
1851   head += (count < ns) ? count : ns;
1852
1853   slot = ring->head;
1854   memif_desc_t *d;
1855   while (slot < head)
1856     {
1857       d = &ring->desc[slot & mask];
1858       d->region = 1;
1859       d->length = c->run_args.buffer_size - headroom;
1860       if (lm->get_external_buffer_offset)
1861         d->offset = lm->get_external_buffer_offset (c->private_ctx);
1862       else
1863         d->offset = d->offset - (d->offset & offset_mask) + headroom;
1864       slot++;
1865     }
1866
1867   MEMIF_MEMORY_BARRIER ();
1868   ring->head = head;
1869
1870   return MEMIF_ERR_SUCCESS;     /* 0 */
1871 }
1872
1873 int
1874 memif_tx_burst (memif_conn_handle_t conn, uint16_t qid,
1875                 memif_buffer_t * bufs, uint16_t count, uint16_t * tx)
1876 {
1877   memif_connection_t *c = (memif_connection_t *) conn;
1878   if (EXPECT_FALSE (c == NULL))
1879     return MEMIF_ERR_NOCONN;
1880   if (EXPECT_FALSE (c->fd < 0))
1881     return MEMIF_ERR_DISCONNECTED;
1882   uint8_t num =
1883     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
1884     run_args.num_s2m_rings;
1885   if (EXPECT_FALSE (qid >= num))
1886     return MEMIF_ERR_QID;
1887   if (EXPECT_FALSE (!tx))
1888     return MEMIF_ERR_INVAL_ARG;
1889
1890   memif_queue_t *mq = &c->tx_queues[qid];
1891   memif_ring_t *ring = mq->ring;
1892   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1893   memif_buffer_t *b0;
1894   *tx = 0;
1895
1896   if (count > mq->alloc_bufs)
1897     count = mq->alloc_bufs;
1898
1899   if (EXPECT_FALSE (count == 0))
1900     return MEMIF_ERR_SUCCESS;
1901
1902   while (count)
1903     {
1904       b0 = (bufs + *tx);
1905       ring->desc[b0->desc_index & mask].length = b0->len;
1906
1907 #ifdef MEMIF_DBG_SHM
1908       printf ("offset: %-6d\n", ring->desc[b0->desc_index & mask].offset);
1909       printf ("data: %p\n",
1910               memif_get_buffer (c, ring, b0->desc_index & mask));
1911       printf ("index: %u\n", b0->desc_index);
1912       print_bytes (memif_get_buffer (c, ring, b0->desc_index & mask),
1913                    ring->desc[b0->desc_index & mask].length, DBG_TX_BUF);
1914 #endif /* MEMIF_DBG_SHM */
1915
1916       *tx += 1;
1917       count--;
1918     }
1919
1920
1921   MEMIF_MEMORY_BARRIER ();
1922   if (c->args.is_master)
1923     ring->tail = b0->desc_index + 1;
1924   else
1925     ring->head = b0->desc_index + 1;
1926
1927   mq->alloc_bufs -= *tx;
1928
1929   if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)
1930     {
1931       uint64_t a = 1;
1932       int r = write (mq->int_fd, &a, sizeof (a));
1933       if (r < 0)
1934         return MEMIF_ERR_INT_WRITE;
1935     }
1936
1937   return MEMIF_ERR_SUCCESS;     /* 0 */
1938 }
1939
1940 int
1941 memif_rx_burst (memif_conn_handle_t conn, uint16_t qid,
1942                 memif_buffer_t * bufs, uint16_t count, uint16_t * rx)
1943 {
1944   memif_connection_t *c = (memif_connection_t *) conn;
1945   if (EXPECT_FALSE (c == NULL))
1946     return MEMIF_ERR_NOCONN;
1947   if (EXPECT_FALSE (c->fd < 0))
1948     return MEMIF_ERR_DISCONNECTED;
1949   uint8_t num =
1950     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
1951     run_args.num_m2s_rings;
1952   if (EXPECT_FALSE (qid >= num))
1953     return MEMIF_ERR_QID;
1954   if (EXPECT_FALSE (!rx))
1955     return MEMIF_ERR_INVAL_ARG;
1956
1957   memif_queue_t *mq = &c->rx_queues[qid];
1958   memif_ring_t *ring = mq->ring;
1959   uint16_t cur_slot, last_slot;
1960   uint16_t ns;
1961   uint16_t mask = (1 << mq->log2_ring_size) - 1;
1962   memif_buffer_t *b0;
1963   *rx = 0;
1964
1965   uint64_t b;
1966   ssize_t r = read (mq->int_fd, &b, sizeof (b));
1967   if (EXPECT_FALSE ((r == -1) && (errno != EAGAIN)))
1968     return memif_syscall_error_handler (errno);
1969
1970   cur_slot = (c->args.is_master) ? mq->last_head : mq->last_tail;
1971   last_slot = (c->args.is_master) ? ring->head : ring->tail;
1972   if (cur_slot == last_slot)
1973     return MEMIF_ERR_SUCCESS;
1974
1975   ns = last_slot - cur_slot;
1976
1977   while (ns && count)
1978     {
1979       b0 = (bufs + *rx);
1980
1981       b0->desc_index = cur_slot;
1982       b0->data = memif_get_buffer (c, ring, cur_slot & mask);
1983       b0->len = ring->desc[cur_slot & mask].length;
1984       /* slave resets buffer length */
1985       if (c->args.is_master == 0)
1986         {
1987           ring->desc[cur_slot & mask].length = c->run_args.buffer_size;
1988         }
1989
1990       b0->flags = MEMIF_BUFFER_FLAG_RX;
1991       if (ring->desc[cur_slot & mask].flags & MEMIF_DESC_FLAG_NEXT)
1992         {
1993           b0->flags |= MEMIF_BUFFER_FLAG_NEXT;
1994           ring->desc[cur_slot & mask].flags &= ~MEMIF_DESC_FLAG_NEXT;
1995         }
1996 /*      b0->offset = ring->desc[cur_slot & mask].offset;*/
1997       b0->ring = ring;
1998 #ifdef MEMIF_DBG_SHM
1999       printf ("data: %p\n", b0->data);
2000       printf ("index: %u\n", b0->desc_index);
2001       printf ("ring: %p\n", b0->ring);
2002       print_bytes (b0->data, b0->len, DBG_RX_BUF);
2003 #endif /* MEMIF_DBG_SHM */
2004       ns--;
2005       *rx += 1;
2006
2007       count--;
2008       cur_slot++;
2009     }
2010
2011   if (c->args.is_master)
2012     mq->last_head = cur_slot;
2013   else
2014     mq->last_tail = cur_slot;
2015
2016   if (ns)
2017     {
2018       DBG ("not enough buffers!");
2019       return MEMIF_ERR_NOBUF;
2020     }
2021
2022   return MEMIF_ERR_SUCCESS;     /* 0 */
2023 }
2024
2025 int
2026 memif_get_details (memif_conn_handle_t conn, memif_details_t * md,
2027                    char *buf, ssize_t buflen)
2028 {
2029   libmemif_main_t *lm = &libmemif_main;
2030   memif_connection_t *c = (memif_connection_t *) conn;
2031   if (c == NULL)
2032     return MEMIF_ERR_NOCONN;
2033
2034   int err = MEMIF_ERR_SUCCESS, i;
2035   ssize_t l0, l1;
2036   l0 = 0;
2037
2038   l1 = strlen ((char *) c->args.interface_name);
2039   if (l0 + l1 < buflen)
2040     {
2041       md->if_name =
2042         (uint8_t *) strcpy (buf + l0, (char *) c->args.interface_name);
2043       l0 += l1 + 1;
2044     }
2045   else
2046     err = MEMIF_ERR_NOBUF_DET;
2047
2048   l1 = strlen ((char *) lm->app_name);
2049   if (l0 + l1 < buflen)
2050     {
2051       md->inst_name = (uint8_t *) strcpy (buf + l0, (char *) lm->app_name);
2052       l0 += l1 + 1;
2053     }
2054   else
2055     err = MEMIF_ERR_NOBUF_DET;
2056
2057   l1 = strlen ((char *) c->remote_if_name);
2058   if (l0 + l1 < buflen)
2059     {
2060       md->remote_if_name =
2061         (uint8_t *) strcpy (buf + l0, (char *) c->remote_if_name);
2062       l0 += l1 + 1;
2063     }
2064   else
2065     err = MEMIF_ERR_NOBUF_DET;
2066
2067   l1 = strlen ((char *) c->remote_name);
2068   if (l0 + l1 < buflen)
2069     {
2070       md->remote_inst_name =
2071         (uint8_t *) strcpy (buf + l0, (char *) c->remote_name);
2072       l0 += l1 + 1;
2073     }
2074   else
2075     err = MEMIF_ERR_NOBUF_DET;
2076
2077   md->id = c->args.interface_id;
2078
2079   if (strlen ((char *) c->args.secret) > 0)
2080     {
2081       l1 = strlen ((char *) c->args.secret);
2082       if (l0 + l1 < buflen)
2083         {
2084           md->secret = (uint8_t *) strcpy (buf + l0, (char *) c->args.secret);
2085           l0 += l1 + 1;
2086         }
2087       else
2088         err = MEMIF_ERR_NOBUF_DET;
2089     }
2090
2091   md->role = (c->args.is_master) ? 0 : 1;
2092   md->mode = c->args.mode;
2093
2094   l1 = strlen ((char *) c->args.socket_filename);
2095   if (l0 + l1 < buflen)
2096     {
2097       md->socket_filename =
2098         (uint8_t *) strcpy (buf + l0, (char *) c->args.socket_filename);
2099       l0 += l1 + 1;
2100     }
2101   else
2102     err = MEMIF_ERR_NOBUF_DET;
2103
2104   l1 = strlen ((char *) c->remote_disconnect_string);
2105   if (l0 + l1 < buflen)
2106     {
2107       md->error =
2108         (uint8_t *) strcpy (buf + l0, (char *) c->remote_disconnect_string);
2109       l0 += l1 + 1;
2110     }
2111   else
2112     err = MEMIF_ERR_NOBUF_DET;
2113
2114   md->regions_num = c->regions_num;
2115   l1 = sizeof (memif_region_details_t) * md->regions_num;
2116   if (l0 + l1 <= buflen)
2117     {
2118       md->regions = (memif_region_details_t *) (buf + l0);
2119       for (i = 0; i < md->regions_num; i++)
2120         {
2121           md->regions[i].index = i;
2122           md->regions[i].addr = c->regions[i].addr;
2123           md->regions[i].size = c->regions[i].region_size;
2124           md->regions[i].fd = c->regions[i].fd;
2125           md->regions[i].is_external = c->regions[i].is_external;
2126         }
2127       l0 += l1;
2128     }
2129   else
2130     err = MEMIF_ERR_NOBUF_DET;
2131
2132   md->rx_queues_num =
2133     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2134     run_args.num_m2s_rings;
2135
2136   l1 = sizeof (memif_queue_details_t) * md->rx_queues_num;
2137   if (l0 + l1 <= buflen)
2138     {
2139       md->rx_queues = (memif_queue_details_t *) (buf + l0);
2140       for (i = 0; i < md->rx_queues_num; i++)
2141         {
2142           md->rx_queues[i].region = c->rx_queues[i].region;
2143           md->rx_queues[i].qid = i;
2144           md->rx_queues[i].ring_size = (1 << c->rx_queues[i].log2_ring_size);
2145           md->rx_queues[i].flags = c->rx_queues[i].ring->flags;
2146           md->rx_queues[i].head = c->rx_queues[i].ring->head;
2147           md->rx_queues[i].tail = c->rx_queues[i].ring->tail;
2148           md->rx_queues[i].buffer_size = c->run_args.buffer_size;
2149         }
2150       l0 += l1;
2151     }
2152   else
2153     err = MEMIF_ERR_NOBUF_DET;
2154
2155   md->tx_queues_num =
2156     (c->args.is_master) ? c->run_args.num_m2s_rings : c->
2157     run_args.num_s2m_rings;
2158
2159   l1 = sizeof (memif_queue_details_t) * md->tx_queues_num;
2160   if (l0 + l1 <= buflen)
2161     {
2162       md->tx_queues = (memif_queue_details_t *) (buf + l0);
2163       for (i = 0; i < md->tx_queues_num; i++)
2164         {
2165           md->tx_queues[i].region = c->tx_queues[i].region;
2166           md->tx_queues[i].qid = i;
2167           md->tx_queues[i].ring_size = (1 << c->tx_queues[i].log2_ring_size);
2168           md->tx_queues[i].flags = c->tx_queues[i].ring->flags;
2169           md->tx_queues[i].head = c->tx_queues[i].ring->head;
2170           md->tx_queues[i].tail = c->tx_queues[i].ring->tail;
2171           md->tx_queues[i].buffer_size = c->run_args.buffer_size;
2172         }
2173       l0 += l1;
2174     }
2175   else
2176     err = MEMIF_ERR_NOBUF_DET;
2177
2178   md->link_up_down = (c->fd > 0) ? 1 : 0;
2179
2180   return err;                   /* 0 */
2181 }
2182
2183 int
2184 memif_get_queue_efd (memif_conn_handle_t conn, uint16_t qid, int *efd)
2185 {
2186   memif_connection_t *c = (memif_connection_t *) conn;
2187   *efd = -1;
2188   if (c == NULL)
2189     return MEMIF_ERR_NOCONN;
2190   if (c->fd < 0)
2191     return MEMIF_ERR_DISCONNECTED;
2192   uint8_t num =
2193     (c->args.is_master) ? c->run_args.num_s2m_rings : c->
2194     run_args.num_m2s_rings;
2195   if (qid >= num)
2196     return MEMIF_ERR_QID;
2197
2198   *efd = c->rx_queues[qid].int_fd;
2199
2200   return MEMIF_ERR_SUCCESS;
2201 }
2202
2203 int
2204 memif_cleanup ()
2205 {
2206   libmemif_main_t *lm = &libmemif_main;
2207   if (lm->control_list)
2208     lm->free (lm->control_list);
2209   lm->control_list = NULL;
2210   if (lm->interrupt_list)
2211     lm->free (lm->interrupt_list);
2212   lm->interrupt_list = NULL;
2213   if (lm->listener_list)
2214     lm->free (lm->listener_list);
2215   lm->listener_list = NULL;
2216   if (lm->pending_list)
2217     lm->free (lm->pending_list);
2218   lm->pending_list = NULL;
2219   if (poll_cancel_fd != -1)
2220     close (poll_cancel_fd);
2221
2222   return MEMIF_ERR_SUCCESS;     /* 0 */
2223 }