memif: add ip mode
[vpp.git] / src / plugins / memif / socket.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2016 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 <sys/eventfd.h>
30 #include <inttypes.h>
31 #include <limits.h>
32
33 #include <vlib/vlib.h>
34 #include <vlib/unix/unix.h>
35 #include <vnet/plugin/plugin.h>
36 #include <vnet/ethernet/ethernet.h>
37 #include <vpp/app/version.h>
38
39 #include <memif/memif.h>
40 #include <memif/private.h>
41
42 static u8 *
43 memif_str2vec (uint8_t * str, int len)
44 {
45   u8 *s = 0;
46   int i;
47
48   if (str[0] == 0)
49     return s;
50
51   for (i = 0; i < len; i++)
52     {
53       vec_add1 (s, str[i]);
54       if (str[i] == 0)
55         return s;
56     }
57   vec_add1 (s, 0);
58
59   return s;
60 }
61
62 static clib_error_t *
63 memif_msg_send (int fd, memif_msg_t * msg, int afd)
64 {
65   struct msghdr mh = { 0 };
66   struct iovec iov[1];
67   char ctl[CMSG_SPACE (sizeof (int))];
68   int rv;
69
70   iov[0].iov_base = (void *) msg;
71   iov[0].iov_len = sizeof (memif_msg_t);
72   mh.msg_iov = iov;
73   mh.msg_iovlen = 1;
74
75   if (afd > 0)
76     {
77       struct cmsghdr *cmsg;
78       memset (&ctl, 0, sizeof (ctl));
79       mh.msg_control = ctl;
80       mh.msg_controllen = sizeof (ctl);
81       cmsg = CMSG_FIRSTHDR (&mh);
82       cmsg->cmsg_len = CMSG_LEN (sizeof (int));
83       cmsg->cmsg_level = SOL_SOCKET;
84       cmsg->cmsg_type = SCM_RIGHTS;
85       memcpy (CMSG_DATA (cmsg), &afd, sizeof (int));
86     }
87   rv = sendmsg (fd, &mh, 0);
88   if (rv < 0)
89     return clib_error_return_unix (0, "sendmsg");
90   DBG ("Message type %u sent (fd %d)", msg->type, afd);
91   return 0;
92 }
93
94 static void
95 memif_msg_enq_ack (memif_if_t * mif)
96 {
97   memif_msg_fifo_elt_t *e;
98   clib_fifo_add2 (mif->msg_queue, e);
99
100   e->msg.type = MEMIF_MSG_TYPE_ACK;
101   e->fd = -1;
102 }
103
104 static clib_error_t *
105 memif_msg_enq_hello (int fd)
106 {
107   u8 *s;
108   memif_msg_t msg = { 0 };
109   memif_msg_hello_t *h = &msg.hello;
110   msg.type = MEMIF_MSG_TYPE_HELLO;
111   h->min_version = MEMIF_VERSION;
112   h->max_version = MEMIF_VERSION;
113   h->max_m2s_ring = MEMIF_MAX_M2S_RING;
114   h->max_s2m_ring = MEMIF_MAX_M2S_RING;
115   h->max_region = MEMIF_MAX_REGION;
116   h->max_log2_ring_size = MEMIF_MAX_LOG2_RING_SIZE;
117   s = format (0, "VPP %s%c", VPP_BUILD_VER, 0);
118   strncpy ((char *) h->name, (char *) s, sizeof (h->name));
119   vec_free (s);
120   return memif_msg_send (fd, &msg, -1);
121 }
122
123 static void
124 memif_msg_enq_init (memif_if_t * mif)
125 {
126   u8 *s;
127   memif_msg_fifo_elt_t *e;
128   clib_fifo_add2 (mif->msg_queue, e);
129   memif_msg_init_t *i = &e->msg.init;
130
131   e->msg.type = MEMIF_MSG_TYPE_INIT;
132   e->fd = -1;
133   i->version = MEMIF_VERSION;
134   i->id = mif->id;
135   i->mode = mif->mode;
136   s = format (0, "VPP %s%c", VPP_BUILD_VER, 0);
137   strncpy ((char *) i->name, (char *) s, sizeof (i->name));
138   if (mif->secret)
139     strncpy ((char *) i->secret, (char *) mif->secret, sizeof (i->secret));
140   vec_free (s);
141 }
142
143 static void
144 memif_msg_enq_add_region (memif_if_t * mif, u8 region)
145 {
146   memif_msg_fifo_elt_t *e;
147   clib_fifo_add2 (mif->msg_queue, e);
148   memif_msg_add_region_t *ar = &e->msg.add_region;
149
150   e->msg.type = MEMIF_MSG_TYPE_ADD_REGION;
151   e->fd = mif->regions[region].fd;
152   ar->index = region;
153   ar->size = mif->regions[region].region_size;
154 }
155
156 static void
157 memif_msg_enq_add_ring (memif_if_t * mif, u8 index, u8 direction)
158 {
159   memif_msg_fifo_elt_t *e;
160   clib_fifo_add2 (mif->msg_queue, e);
161   memif_msg_add_ring_t *ar = &e->msg.add_ring;
162   memif_queue_t *mq;
163
164   ASSERT ((mif->flags & MEMIF_IF_FLAG_IS_SLAVE) != 0);
165
166   e->msg.type = MEMIF_MSG_TYPE_ADD_RING;
167
168   if (direction == MEMIF_RING_M2S)
169     mq = vec_elt_at_index (mif->rx_queues, index);
170   else
171     mq = vec_elt_at_index (mif->tx_queues, index);
172
173   e->fd = mq->int_fd;
174   ar->index = index;
175   ar->region = mq->region;
176   ar->offset = mq->offset;
177   ar->log2_ring_size = mq->log2_ring_size;
178   ar->flags = (direction == MEMIF_RING_S2M) ? MEMIF_MSG_ADD_RING_FLAG_S2M : 0;
179 }
180
181 static void
182 memif_msg_enq_connect (memif_if_t * mif)
183 {
184   memif_msg_fifo_elt_t *e;
185   clib_fifo_add2 (mif->msg_queue, e);
186   memif_msg_connect_t *c = &e->msg.connect;
187   u8 *s;
188
189   e->msg.type = MEMIF_MSG_TYPE_CONNECT;
190   e->fd = -1;
191   s = format (0, "%U%c", format_memif_device_name, mif->dev_instance, 0);
192   strncpy ((char *) c->if_name, (char *) s, sizeof (c->if_name));
193   vec_free (s);
194 }
195
196 static void
197 memif_msg_enq_connected (memif_if_t * mif)
198 {
199   memif_msg_fifo_elt_t *e;
200   clib_fifo_add2 (mif->msg_queue, e);
201   memif_msg_connected_t *c = &e->msg.connected;
202   u8 *s;
203
204   e->msg.type = MEMIF_MSG_TYPE_CONNECTED;
205   e->fd = -1;
206   s = format (0, "%U%c", format_memif_device_name, mif->dev_instance, 0);
207   strncpy ((char *) c->if_name, (char *) s, sizeof (c->if_name));
208   vec_free (s);
209 }
210
211 clib_error_t *
212 memif_msg_send_disconnect (memif_if_t * mif, clib_error_t * err)
213 {
214   memif_msg_t msg = { 0 };
215   msg.type = MEMIF_MSG_TYPE_DISCONNECT;
216   memif_msg_disconnect_t *d = &msg.disconnect;
217
218   d->code = err->code;
219   strncpy ((char *) d->string, (char *) err->what, sizeof (d->string));
220
221   return memif_msg_send (mif->conn_fd, &msg, -1);
222 }
223
224 static clib_error_t *
225 memif_msg_receive_hello (memif_if_t * mif, memif_msg_t * msg)
226 {
227   memif_msg_hello_t *h = &msg->hello;
228
229   if (msg->hello.min_version > MEMIF_VERSION ||
230       msg->hello.max_version < MEMIF_VERSION)
231     return clib_error_return (0, "incompatible protocol version");
232
233   mif->run.num_s2m_rings = clib_min (h->max_s2m_ring + 1,
234                                      mif->cfg.num_s2m_rings);
235   mif->run.num_m2s_rings = clib_min (h->max_m2s_ring + 1,
236                                      mif->cfg.num_m2s_rings);
237   mif->run.log2_ring_size = clib_min (h->max_log2_ring_size,
238                                       mif->cfg.log2_ring_size);
239   mif->run.buffer_size = mif->cfg.buffer_size;
240
241   mif->remote_name = memif_str2vec (h->name, sizeof (h->name));
242
243   return 0;
244 }
245
246 static clib_error_t *
247 memif_msg_receive_init (memif_if_t ** mifp, memif_msg_t * msg,
248                         unix_file_t * uf)
249 {
250   memif_main_t *mm = &memif_main;
251   memif_socket_file_t *msf =
252     vec_elt_at_index (mm->socket_files, uf->private_data);
253   memif_msg_init_t *i = &msg->init;
254   memif_if_t *mif, tmp;
255   clib_error_t *err;
256   uword *p;
257
258   if (i->version != MEMIF_VERSION)
259     {
260       memif_file_del_by_index (uf - unix_main.file_pool);
261       return clib_error_return (0, "unsupported version");
262     }
263
264   p = mhash_get (&msf->dev_instance_by_id, &i->id);
265
266   if (!p)
267     {
268       err = clib_error_return (0, "unmatched interface id");
269       goto error;
270     }
271
272   mif = vec_elt_at_index (mm->interfaces, p[0]);
273
274   if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
275     {
276       err = clib_error_return (0, "cannot connect to slave");
277       goto error;
278     }
279
280   if (mif->conn_fd != -1)
281     {
282       err = clib_error_return (0, "already connected");
283       goto error;
284     }
285
286   if (i->mode != mif->mode)
287     {
288       err = clib_error_return (0, "mode mismatch");
289       goto error;
290     }
291
292   mif->conn_fd = uf->file_descriptor;
293   mif->conn_unix_file_index = uf - unix_main.file_pool;
294   hash_set (msf->dev_instance_by_fd, mif->conn_fd, mif->dev_instance);
295   mif->remote_name = memif_str2vec (i->name, sizeof (i->name));
296   *mifp = mif;
297
298   if (mif->secret)
299     {
300       u8 *s;
301       int r;
302       s = memif_str2vec (i->secret, sizeof (i->secret));
303       if (s == 0)
304         return clib_error_return (0, "secret required");
305
306       r = vec_cmp (s, mif->secret);
307       vec_free (s);
308
309       if (r)
310         return clib_error_return (0, "incorrect secret");
311     }
312
313   return 0;
314
315 error:
316   tmp.conn_fd = uf->file_descriptor;
317   memif_msg_send_disconnect (&tmp, err);
318   memif_file_del_by_index (uf - unix_main.file_pool);
319   return err;
320 }
321
322 static clib_error_t *
323 memif_msg_receive_add_region (memif_if_t * mif, memif_msg_t * msg, int fd)
324 {
325   memif_msg_add_region_t *ar = &msg->add_region;
326   memif_region_t *mr;
327   if (fd < 0)
328     return clib_error_return (0, "missing memory region fd");
329
330   if (ar->index != vec_len (mif->regions))
331     return clib_error_return (0, "unexpected region index");
332
333   if (ar->index > MEMIF_MAX_REGION)
334     return clib_error_return (0, "too many regions");
335
336   vec_validate_aligned (mif->regions, ar->index, CLIB_CACHE_LINE_BYTES);
337   mr = vec_elt_at_index (mif->regions, ar->index);
338   mr->fd = fd;
339   mr->region_size = ar->size;
340
341   return 0;
342 }
343
344 static clib_error_t *
345 memif_msg_receive_add_ring (memif_if_t * mif, memif_msg_t * msg, int fd)
346 {
347   memif_msg_add_ring_t *ar = &msg->add_ring;
348   memif_queue_t *mq;
349
350   if (fd < 0)
351     return clib_error_return (0, "missing ring interrupt fd");
352
353   if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M)
354     {
355       if (ar->index != vec_len (mif->rx_queues))
356         return clib_error_return (0, "unexpected ring index");
357
358       if (ar->index > MEMIF_MAX_S2M_RING)
359         return clib_error_return (0, "too many rings");
360
361       vec_validate_aligned (mif->rx_queues, ar->index, CLIB_CACHE_LINE_BYTES);
362       mq = vec_elt_at_index (mif->rx_queues, ar->index);
363       mif->run.num_s2m_rings = vec_len (mif->rx_queues);
364     }
365   else
366     {
367       if (ar->index != vec_len (mif->tx_queues))
368         return clib_error_return (0, "unexpected ring index");
369
370       if (ar->index > MEMIF_MAX_M2S_RING)
371         return clib_error_return (0, "too many rings");
372
373       vec_validate_aligned (mif->tx_queues, ar->index, CLIB_CACHE_LINE_BYTES);
374       mq = vec_elt_at_index (mif->tx_queues, ar->index);
375       mif->run.num_m2s_rings = vec_len (mif->tx_queues);
376     }
377
378   mq->int_fd = fd;
379   mq->int_unix_file_index = ~0;
380   mq->log2_ring_size = ar->log2_ring_size;
381   mq->region = ar->region;
382   mq->offset = ar->offset;
383
384   return 0;
385 }
386
387 static clib_error_t *
388 memif_msg_receive_connect (memif_if_t * mif, memif_msg_t * msg)
389 {
390   clib_error_t *err;
391   memif_msg_connect_t *c = &msg->connect;
392
393   if ((err = memif_connect (mif)))
394     return err;
395
396   mif->remote_if_name = memif_str2vec (c->if_name, sizeof (c->if_name));
397
398   return 0;
399 }
400
401 static clib_error_t *
402 memif_msg_receive_connected (memif_if_t * mif, memif_msg_t * msg)
403 {
404   clib_error_t *err;
405   memif_msg_connected_t *c = &msg->connected;
406
407   if ((err = memif_connect (mif)))
408     return err;
409
410   mif->remote_if_name = memif_str2vec (c->if_name, sizeof (c->if_name));
411   return 0;
412 }
413
414 static clib_error_t *
415 memif_msg_receive_disconnect (memif_if_t * mif, memif_msg_t * msg)
416 {
417   memif_msg_disconnect_t *d = &msg->disconnect;
418
419   mif->remote_disc_string = memif_str2vec (d->string, sizeof (d->string));
420   return clib_error_return (0, "disconnect received");
421 }
422
423 static clib_error_t *
424 memif_msg_receive (memif_if_t ** mifp, unix_file_t * uf)
425 {
426   char ctl[CMSG_SPACE (sizeof (int)) +
427            CMSG_SPACE (sizeof (struct ucred))] = { 0 };
428   struct msghdr mh = { 0 };
429   struct iovec iov[1];
430   memif_msg_t msg = { 0 };
431   ssize_t size;
432   clib_error_t *err = 0;
433   int fd = -1;
434   int i;
435   memif_if_t *mif = *mifp;
436
437   iov[0].iov_base = (void *) &msg;
438   iov[0].iov_len = sizeof (memif_msg_t);
439   mh.msg_iov = iov;
440   mh.msg_iovlen = 1;
441   mh.msg_control = ctl;
442   mh.msg_controllen = sizeof (ctl);
443
444   /* receive the incoming message */
445   size = recvmsg (uf->file_descriptor, &mh, 0);
446   if (size != sizeof (memif_msg_t))
447     {
448       return (size == 0) ? clib_error_return (0, "disconnected") :
449         clib_error_return_unix (0,
450                                 "recvmsg: malformed message received on fd %d",
451                                 uf->file_descriptor);
452     }
453
454   if (mif == 0 && msg.type != MEMIF_MSG_TYPE_INIT)
455     {
456       memif_file_del (uf);
457       return clib_error_return (0, "unexpected message received");
458     }
459
460   /* process anciliary data */
461   struct ucred *cr = 0;
462   struct cmsghdr *cmsg;
463
464   cmsg = CMSG_FIRSTHDR (&mh);
465   while (cmsg)
466     {
467       if (cmsg->cmsg_level == SOL_SOCKET)
468         {
469           if (cmsg->cmsg_type == SCM_CREDENTIALS)
470             {
471               cr = (struct ucred *) CMSG_DATA (cmsg);
472             }
473           else if (cmsg->cmsg_type == SCM_RIGHTS)
474             {
475               int *fdp = (int *) CMSG_DATA (cmsg);
476               fd = *fdp;
477             }
478         }
479       cmsg = CMSG_NXTHDR (&mh, cmsg);
480     }
481
482   DBG ("Message type %u received", msg.type);
483   /* process the message based on its type */
484   switch (msg.type)
485     {
486     case MEMIF_MSG_TYPE_ACK:
487       break;
488
489     case MEMIF_MSG_TYPE_HELLO:
490       if ((err = memif_msg_receive_hello (mif, &msg)))
491         return err;
492       if ((err = memif_init_regions_and_queues (mif)))
493         return err;
494       memif_msg_enq_init (mif);
495       memif_msg_enq_add_region (mif, 0);
496       vec_foreach_index (i, mif->tx_queues)
497         memif_msg_enq_add_ring (mif, i, MEMIF_RING_S2M);
498       vec_foreach_index (i, mif->rx_queues)
499         memif_msg_enq_add_ring (mif, i, MEMIF_RING_M2S);
500       memif_msg_enq_connect (mif);
501       break;
502
503     case MEMIF_MSG_TYPE_INIT:
504       if ((err = memif_msg_receive_init (mifp, &msg, uf)))
505         return err;
506       mif = *mifp;
507       mif->remote_pid = cr->pid;
508       mif->remote_uid = cr->uid;
509       mif->remote_gid = cr->gid;
510       memif_msg_enq_ack (mif);
511       break;
512
513     case MEMIF_MSG_TYPE_ADD_REGION:
514       if ((err = memif_msg_receive_add_region (mif, &msg, fd)))
515         return err;
516       memif_msg_enq_ack (mif);
517       break;
518
519     case MEMIF_MSG_TYPE_ADD_RING:
520       if ((err = memif_msg_receive_add_ring (mif, &msg, fd)))
521         return err;
522       memif_msg_enq_ack (mif);
523       break;
524
525     case MEMIF_MSG_TYPE_CONNECT:
526       if ((err = memif_msg_receive_connect (mif, &msg)))
527         return err;
528       memif_msg_enq_connected (mif);
529       break;
530
531     case MEMIF_MSG_TYPE_CONNECTED:
532       if ((err = memif_msg_receive_connected (mif, &msg)))
533         return err;
534       break;
535
536     case MEMIF_MSG_TYPE_DISCONNECT:
537       if ((err = memif_msg_receive_disconnect (mif, &msg)))
538         return err;
539       break;
540
541     default:
542       err = clib_error_return (0, "unknown message type (0x%x)", msg.type);
543       return err;
544     }
545
546   if (clib_fifo_elts (mif->msg_queue) && mif->conn_unix_file_index != ~0)
547     unix_file_set_data_available_to_write (mif->conn_unix_file_index, 1);
548   return 0;
549 }
550
551 clib_error_t *
552 memif_master_conn_fd_read_ready (unix_file_t * uf)
553 {
554   memif_main_t *mm = &memif_main;
555   memif_socket_file_t *msf =
556     pool_elt_at_index (mm->socket_files, uf->private_data);
557   uword *p;
558   memif_if_t *mif = 0;
559   uword conn_unix_file_index = ~0;
560   clib_error_t *err = 0;
561
562   p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
563   if (p)
564     {
565       mif = vec_elt_at_index (mm->interfaces, p[0]);
566     }
567   else
568     {
569       /* This is new connection, remove index from pending vector */
570       int i;
571       vec_foreach_index (i, msf->pending_file_indices)
572         if (msf->pending_file_indices[i] == uf - unix_main.file_pool)
573         {
574           conn_unix_file_index = msf->pending_file_indices[i];
575           vec_del1 (msf->pending_file_indices, i);
576           break;
577         }
578       ASSERT (conn_unix_file_index != ~0);
579     }
580   err = memif_msg_receive (&mif, uf);
581   if (err)
582     {
583       memif_disconnect (mif, err);
584       clib_error_free (err);
585     }
586   return 0;
587 }
588
589 clib_error_t *
590 memif_slave_conn_fd_read_ready (unix_file_t * uf)
591 {
592   memif_main_t *mm = &memif_main;
593   clib_error_t *err;
594   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
595   err = memif_msg_receive (&mif, uf);
596   if (err)
597     {
598       memif_disconnect (mif, err);
599       clib_error_free (err);
600     }
601   return 0;
602 }
603
604 static clib_error_t *
605 memif_conn_fd_write_ready (unix_file_t * uf, memif_if_t * mif)
606 {
607   memif_msg_fifo_elt_t *e;
608   clib_fifo_sub2 (mif->msg_queue, e);
609   unix_file_set_data_available_to_write (mif->conn_unix_file_index, 0);
610   memif_msg_send (mif->conn_fd, &e->msg, e->fd);
611   return 0;
612 }
613
614 clib_error_t *
615 memif_master_conn_fd_write_ready (unix_file_t * uf)
616 {
617   memif_main_t *mm = &memif_main;
618   memif_socket_file_t *msf =
619     pool_elt_at_index (mm->socket_files, uf->private_data);
620   uword *p;
621   memif_if_t *mif;
622
623   p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
624   if (!p)
625     return 0;
626
627   mif = vec_elt_at_index (mm->interfaces, p[0]);
628   return memif_conn_fd_write_ready (uf, mif);
629 }
630
631 clib_error_t *
632 memif_slave_conn_fd_write_ready (unix_file_t * uf)
633 {
634   memif_main_t *mm = &memif_main;
635   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
636   return memif_conn_fd_write_ready (uf, mif);
637 }
638
639 clib_error_t *
640 memif_slave_conn_fd_error (unix_file_t * uf)
641 {
642   memif_main_t *mm = &memif_main;
643   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
644   clib_error_t *err;
645
646   err = clib_error_return (0, "connection fd error");
647   memif_disconnect (mif, err);
648   clib_error_free (err);
649
650   return 0;
651 }
652
653 clib_error_t *
654 memif_master_conn_fd_error (unix_file_t * uf)
655 {
656   memif_main_t *mm = &memif_main;
657   memif_socket_file_t *msf =
658     pool_elt_at_index (mm->socket_files, uf->private_data);
659   uword *p;
660
661
662   p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
663   if (p)
664     {
665       memif_if_t *mif;
666       clib_error_t *err;
667       mif = vec_elt_at_index (mm->interfaces, p[0]);
668       err = clib_error_return (0, "connection fd error");
669       memif_disconnect (mif, err);
670       clib_error_free (err);
671     }
672   else
673     {
674       int i;
675       vec_foreach_index (i, msf->pending_file_indices)
676         if (msf->pending_file_indices[i] == uf - unix_main.file_pool)
677         {
678           vec_del1 (msf->pending_file_indices, i);
679           memif_file_del (uf);
680           return 0;
681         }
682     }
683
684   clib_warning ("Error on unknown file descriptor %d", uf->file_descriptor);
685   memif_file_del (uf);
686   return 0;
687 }
688
689
690 clib_error_t *
691 memif_conn_fd_accept_ready (unix_file_t * uf)
692 {
693   memif_main_t *mm = &memif_main;
694   memif_socket_file_t *msf =
695     pool_elt_at_index (mm->socket_files, uf->private_data);
696   int addr_len;
697   struct sockaddr_un client;
698   int conn_fd;
699   unix_file_t template = { 0 };
700   uword unix_file_index = ~0;
701   clib_error_t *err;
702
703
704   addr_len = sizeof (client);
705   conn_fd = accept (uf->file_descriptor,
706                     (struct sockaddr *) &client, (socklen_t *) & addr_len);
707
708   if (conn_fd < 0)
709     return clib_error_return_unix (0, "accept fd %d", uf->file_descriptor);
710
711   template.read_function = memif_master_conn_fd_read_ready;
712   template.write_function = memif_master_conn_fd_write_ready;
713   template.error_function = memif_master_conn_fd_error;
714   template.file_descriptor = conn_fd;
715   template.private_data = uf->private_data;
716
717   memif_file_add (&unix_file_index, &template);
718
719   err = memif_msg_enq_hello (conn_fd);
720   if (err)
721     {
722       clib_error_report (err);
723       memif_file_del_by_index (unix_file_index);
724     }
725   else
726     vec_add1 (msf->pending_file_indices, unix_file_index);
727
728   return 0;
729 }
730
731 /*
732  * fd.io coding-style-patch-verification: ON
733  *
734  * Local Variables:
735  * eval: (c-set-style "gnu")
736  * End:
737  */