ac48ba88da5c9aecfa871754e02ca6e332a89787
[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_msg_t msg = { 0 };
412   clib_error_t *err = 0;
413   int fd = -1;
414   int i;
415   memif_if_t *mif = *mifp;
416
417   err = clib_socket_recvmsg (sock, &msg, sizeof (memif_msg_t), &fd, 1);
418   if (err)
419     goto error;
420
421   if (mif == 0 && msg.type != MEMIF_MSG_TYPE_INIT)
422     {
423       memif_socket_close (&sock);
424       err = clib_error_return (0, "unexpected message received");
425       goto error;
426     }
427
428   memif_log_debug (mif, "Message type %u received", msg.type);
429   /* process the message based on its type */
430   switch (msg.type)
431     {
432     case MEMIF_MSG_TYPE_ACK:
433       break;
434
435     case MEMIF_MSG_TYPE_HELLO:
436       if ((err = memif_msg_receive_hello (mif, &msg)))
437         goto error;
438       if ((err = memif_init_regions_and_queues (mif)))
439         goto error;
440       memif_msg_enq_init (mif);
441       /* *INDENT-OFF* */
442       vec_foreach_index (i, mif->regions)
443         memif_msg_enq_add_region (mif, i);
444       vec_foreach_index (i, mif->tx_queues)
445         memif_msg_enq_add_ring (mif, i, MEMIF_RING_S2M);
446       vec_foreach_index (i, mif->rx_queues)
447         memif_msg_enq_add_ring (mif, i, MEMIF_RING_M2S);
448       /* *INDENT-ON* */
449       memif_msg_enq_connect (mif);
450       break;
451
452     case MEMIF_MSG_TYPE_INIT:
453       if ((err = memif_msg_receive_init (mifp, &msg, sock, uf->private_data)))
454         goto error;
455       mif = *mifp;
456       vec_reset_length (uf->description);
457       uf->description = format (uf->description, "%U ctl",
458                                 format_memif_device_name, mif->dev_instance);
459       memif_msg_enq_ack (mif);
460       break;
461
462     case MEMIF_MSG_TYPE_ADD_REGION:
463       if ((err = memif_msg_receive_add_region (mif, &msg, fd)))
464         goto error;
465       memif_msg_enq_ack (mif);
466       break;
467
468     case MEMIF_MSG_TYPE_ADD_RING:
469       if ((err = memif_msg_receive_add_ring (mif, &msg, fd)))
470         goto error;
471       memif_msg_enq_ack (mif);
472       break;
473
474     case MEMIF_MSG_TYPE_CONNECT:
475       if ((err = memif_msg_receive_connect (mif, &msg)))
476         goto error;
477       memif_msg_enq_connected (mif);
478       break;
479
480     case MEMIF_MSG_TYPE_CONNECTED:
481       if ((err = memif_msg_receive_connected (mif, &msg)))
482         goto error;
483       break;
484
485     case MEMIF_MSG_TYPE_DISCONNECT:
486       if ((err = memif_msg_receive_disconnect (mif, &msg)))
487         goto error;
488       break;
489
490     default:
491       err = clib_error_return (0, "unknown message type (0x%x)", msg.type);
492       goto error;
493     }
494
495   if (clib_fifo_elts (mif->msg_queue))
496     clib_file_set_data_available_to_write (&file_main,
497                                            mif->sock->private_data, 1);
498   return 0;
499
500 error:
501   memif_log_err (mif, "%U", format_clib_error, err);
502   return err;
503 }
504
505 clib_error_t *
506 memif_master_conn_fd_read_ready (clib_file_t * uf)
507 {
508   memif_main_t *mm = &memif_main;
509   memif_socket_file_t *msf =
510     pool_elt_at_index (mm->socket_files, uf->private_data);
511   uword *p;
512   memif_if_t *mif = 0;
513   clib_socket_t *sock = 0;
514   clib_error_t *err = 0;
515
516   p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
517   if (p)
518     {
519       mif = vec_elt_at_index (mm->interfaces, p[0]);
520       sock = mif->sock;
521     }
522   else
523     {
524       /* This is new connection, remove index from pending vector */
525       int i;
526       vec_foreach_index (i, msf->pending_clients)
527         if (msf->pending_clients[i]->fd == uf->file_descriptor)
528         {
529           sock = msf->pending_clients[i];
530           vec_del1 (msf->pending_clients, i);
531           break;
532         }
533       ASSERT (sock != 0);
534     }
535   err = memif_msg_receive (&mif, sock, uf);
536   if (err)
537     {
538       memif_disconnect (mif, err);
539       clib_error_free (err);
540     }
541   return 0;
542 }
543
544 clib_error_t *
545 memif_slave_conn_fd_read_ready (clib_file_t * uf)
546 {
547   memif_main_t *mm = &memif_main;
548   clib_error_t *err;
549   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
550   err = memif_msg_receive (&mif, mif->sock, uf);
551   if (err)
552     {
553       memif_disconnect (mif, err);
554       clib_error_free (err);
555     }
556   return 0;
557 }
558
559 static clib_error_t *
560 memif_conn_fd_write_ready (clib_file_t * uf, memif_if_t * mif)
561 {
562   memif_msg_fifo_elt_t *e;
563   clib_fifo_sub2 (mif->msg_queue, e);
564   clib_file_set_data_available_to_write (&file_main,
565                                          mif->sock->private_data, 0);
566   return clib_socket_sendmsg (mif->sock, &e->msg, sizeof (memif_msg_t),
567                               &e->fd, e->fd > -1 ? 1 : 0);
568 }
569
570 clib_error_t *
571 memif_master_conn_fd_write_ready (clib_file_t * uf)
572 {
573   memif_main_t *mm = &memif_main;
574   memif_socket_file_t *msf =
575     pool_elt_at_index (mm->socket_files, uf->private_data);
576   uword *p;
577   memif_if_t *mif;
578
579   p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
580   if (!p)
581     return 0;
582
583   mif = vec_elt_at_index (mm->interfaces, p[0]);
584   return memif_conn_fd_write_ready (uf, mif);
585 }
586
587 clib_error_t *
588 memif_slave_conn_fd_write_ready (clib_file_t * uf)
589 {
590   memif_main_t *mm = &memif_main;
591   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
592   return memif_conn_fd_write_ready (uf, mif);
593 }
594
595 clib_error_t *
596 memif_slave_conn_fd_error (clib_file_t * uf)
597 {
598   memif_main_t *mm = &memif_main;
599   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
600   clib_error_t *err;
601
602   err = clib_error_return (0, "connection fd error");
603   memif_disconnect (mif, err);
604   clib_error_free (err);
605
606   return 0;
607 }
608
609 clib_error_t *
610 memif_master_conn_fd_error (clib_file_t * uf)
611 {
612   memif_main_t *mm = &memif_main;
613   memif_socket_file_t *msf =
614     pool_elt_at_index (mm->socket_files, uf->private_data);
615   uword *p;
616
617
618   p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
619   if (p)
620     {
621       memif_if_t *mif;
622       clib_error_t *err;
623       mif = vec_elt_at_index (mm->interfaces, p[0]);
624       err = clib_error_return (0, "connection fd error");
625       memif_disconnect (mif, err);
626       clib_error_free (err);
627     }
628   else
629     {
630       int i;
631       vec_foreach_index (i, msf->pending_clients)
632         if (msf->pending_clients[i]->fd == uf->file_descriptor)
633         {
634           clib_socket_t *s = msf->pending_clients[i];
635           memif_socket_close (&s);
636           vec_del1 (msf->pending_clients, i);
637           return 0;
638         }
639     }
640
641   memif_log_warn (0, "Error on unknown file descriptor %d",
642                   uf->file_descriptor);
643   memif_file_del (uf);
644   return 0;
645 }
646
647
648 clib_error_t *
649 memif_conn_fd_accept_ready (clib_file_t * uf)
650 {
651   memif_main_t *mm = &memif_main;
652   memif_socket_file_t *msf =
653     pool_elt_at_index (mm->socket_files, uf->private_data);
654   clib_file_t template = { 0 };
655   clib_error_t *err;
656   clib_socket_t *client;
657
658   client = clib_mem_alloc (sizeof (clib_socket_t));
659   memset (client, 0, sizeof (clib_socket_t));
660   err = clib_socket_accept (msf->sock, client);
661   if (err)
662     goto error;
663
664   template.read_function = memif_master_conn_fd_read_ready;
665   template.write_function = memif_master_conn_fd_write_ready;
666   template.error_function = memif_master_conn_fd_error;
667   template.file_descriptor = client->fd;
668   template.private_data = uf->private_data;
669   template.description = format (0, "memif in conn on %s", msf->filename);
670
671   memif_file_add (&client->private_data, &template);
672
673   err = memif_msg_enq_hello (client);
674   if (err)
675     {
676       clib_socket_close (client);
677       goto error;
678     }
679
680   vec_add1 (msf->pending_clients, client);
681
682   return 0;
683
684 error:
685   memif_log_err (0, "%U", format_clib_error, err);
686   clib_mem_free (client);
687   return err;
688 }
689
690 /*
691  * fd.io coding-style-patch-verification: ON
692  *
693  * Local Variables:
694  * eval: (c-set-style "gnu")
695  * End:
696  */