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