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