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