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