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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
21 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
28 #include <sys/prctl.h>
29 #include <sys/eventfd.h>
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>
39 #include <memif/memif.h>
40 #include <memif/private.h>
43 memif_socket_close (clib_socket_t ** s)
45 memif_file_del_by_index ((*s)->private_data);
51 memif_str2vec (uint8_t * str, int len)
59 for (i = 0; i < len; i++)
71 memif_msg_enq_ack (memif_if_t * mif)
73 memif_msg_fifo_elt_t *e;
74 clib_fifo_add2 (mif->msg_queue, e);
76 e->msg.type = MEMIF_MSG_TYPE_ACK;
81 memif_msg_enq_hello (clib_socket_t * sock)
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);
96 return clib_socket_sendmsg (sock, &msg, sizeof (memif_msg_t), 0, 0);
100 memif_msg_enq_init (memif_if_t * mif)
103 memif_msg_fifo_elt_t *e;
104 clib_fifo_add2 (mif->msg_queue, e);
105 memif_msg_init_t *i = &e->msg.init;
107 e->msg.type = MEMIF_MSG_TYPE_INIT;
109 i->version = MEMIF_VERSION;
112 s = format (0, "VPP %s%c", VPP_BUILD_VER, 0);
113 strncpy ((char *) i->name, (char *) s, sizeof (i->name) - 1);
115 strncpy ((char *) i->secret, (char *) mif->secret,
116 sizeof (i->secret) - 1);
121 memif_msg_enq_add_region (memif_if_t * mif, u8 region)
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;
127 e->msg.type = MEMIF_MSG_TYPE_ADD_REGION;
128 e->fd = mif->regions[region].fd;
130 ar->size = mif->regions[region].region_size;
134 memif_msg_enq_add_ring (memif_if_t * mif, u8 index, u8 direction)
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;
141 ASSERT ((mif->flags & MEMIF_IF_FLAG_IS_SLAVE) != 0);
143 e->msg.type = MEMIF_MSG_TYPE_ADD_RING;
145 if (direction == MEMIF_RING_M2S)
146 mq = vec_elt_at_index (mif->rx_queues, index);
148 mq = vec_elt_at_index (mif->tx_queues, 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;
159 memif_msg_enq_connect (memif_if_t * mif)
161 memif_msg_fifo_elt_t *e;
162 clib_fifo_add2 (mif->msg_queue, e);
163 memif_msg_connect_t *c = &e->msg.connect;
166 e->msg.type = MEMIF_MSG_TYPE_CONNECT;
168 s = format (0, "%U%c", format_memif_device_name, mif->dev_instance, 0);
169 strncpy ((char *) c->if_name, (char *) s, sizeof (c->if_name) - 1);
174 memif_msg_enq_connected (memif_if_t * mif)
176 memif_msg_fifo_elt_t *e;
177 clib_fifo_add2 (mif->msg_queue, e);
178 memif_msg_connected_t *c = &e->msg.connected;
181 e->msg.type = MEMIF_MSG_TYPE_CONNECTED;
183 s = format (0, "%U%c", format_memif_device_name, mif->dev_instance, 0);
184 strncpy ((char *) c->if_name, (char *) s, sizeof (c->if_name) - 1);
189 memif_msg_send_disconnect (memif_if_t * mif, clib_error_t * err)
191 memif_msg_t msg = { 0 };
192 msg.type = MEMIF_MSG_TYPE_DISCONNECT;
193 memif_msg_disconnect_t *d = &msg.disconnect;
196 strncpy ((char *) d->string, (char *) err->what, sizeof (d->string) - 1);
198 return clib_socket_sendmsg (mif->sock, &msg, sizeof (memif_msg_t), 0, 0);
201 static clib_error_t *
202 memif_msg_receive_hello (memif_if_t * mif, memif_msg_t * msg)
204 memif_msg_hello_t *h = &msg->hello;
206 if (msg->hello.min_version > MEMIF_VERSION ||
207 msg->hello.max_version < MEMIF_VERSION)
208 return clib_error_return (0, "incompatible protocol version");
210 mif->run.num_s2m_rings = clib_min (h->max_s2m_ring + 1,
211 mif->cfg.num_s2m_rings);
212 mif->run.num_m2s_rings = clib_min (h->max_m2s_ring + 1,
213 mif->cfg.num_m2s_rings);
214 mif->run.log2_ring_size = clib_min (h->max_log2_ring_size,
215 mif->cfg.log2_ring_size);
216 mif->run.buffer_size = mif->cfg.buffer_size;
218 mif->remote_name = memif_str2vec (h->name, sizeof (h->name));
223 static clib_error_t *
224 memif_msg_receive_init (memif_if_t ** mifp, memif_msg_t * msg,
225 clib_socket_t * sock, uword socket_file_index)
227 memif_main_t *mm = &memif_main;
228 memif_socket_file_t *msf =
229 vec_elt_at_index (mm->socket_files, socket_file_index);
230 memif_msg_init_t *i = &msg->init;
231 memif_if_t *mif, tmp;
235 if (i->version != MEMIF_VERSION)
237 memif_file_del_by_index (sock->private_data);
238 return clib_error_return (0, "unsupported version");
241 p = mhash_get (&msf->dev_instance_by_id, &i->id);
245 err = clib_error_return (0, "unmatched interface id");
249 mif = vec_elt_at_index (mm->interfaces, p[0]);
251 if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
253 err = clib_error_return (0, "cannot connect to slave");
259 err = clib_error_return (0, "already connected");
263 if (i->mode != mif->mode)
265 err = clib_error_return (0, "mode mismatch");
270 hash_set (msf->dev_instance_by_fd, mif->sock->fd, mif->dev_instance);
271 mif->remote_name = memif_str2vec (i->name, sizeof (i->name));
278 s = memif_str2vec (i->secret, sizeof (i->secret));
280 return clib_error_return (0, "secret required");
282 r = vec_cmp (s, mif->secret);
286 return clib_error_return (0, "incorrect secret");
292 memif_msg_send_disconnect (&tmp, err);
296 static clib_error_t *
297 memif_msg_receive_add_region (memif_if_t * mif, memif_msg_t * msg, int fd)
299 memif_msg_add_region_t *ar = &msg->add_region;
302 return clib_error_return (0, "missing memory region fd");
304 if (ar->index != vec_len (mif->regions))
305 return clib_error_return (0, "unexpected region index");
307 if (ar->index > MEMIF_MAX_REGION)
308 return clib_error_return (0, "too many regions");
310 vec_validate_aligned (mif->regions, ar->index, CLIB_CACHE_LINE_BYTES);
311 mr = vec_elt_at_index (mif->regions, ar->index);
313 mr->region_size = ar->size;
318 static clib_error_t *
319 memif_msg_receive_add_ring (memif_if_t * mif, memif_msg_t * msg, int fd)
321 memif_msg_add_ring_t *ar = &msg->add_ring;
325 return clib_error_return (0, "missing ring interrupt fd");
327 if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M)
329 if (ar->index != vec_len (mif->rx_queues))
330 return clib_error_return (0, "unexpected ring index");
332 if (ar->index > MEMIF_MAX_S2M_RING)
333 return clib_error_return (0, "too many rings");
335 vec_validate_aligned (mif->rx_queues, ar->index, CLIB_CACHE_LINE_BYTES);
336 mq = vec_elt_at_index (mif->rx_queues, ar->index);
337 mif->run.num_s2m_rings = vec_len (mif->rx_queues);
341 if (ar->index != vec_len (mif->tx_queues))
342 return clib_error_return (0, "unexpected ring index");
344 if (ar->index > MEMIF_MAX_M2S_RING)
345 return clib_error_return (0, "too many rings");
347 vec_validate_aligned (mif->tx_queues, ar->index, CLIB_CACHE_LINE_BYTES);
348 mq = vec_elt_at_index (mif->tx_queues, ar->index);
349 mif->run.num_m2s_rings = vec_len (mif->tx_queues);
353 mq->int_clib_file_index = ~0;
354 mq->log2_ring_size = ar->log2_ring_size;
355 mq->region = ar->region;
356 mq->offset = ar->offset;
361 static clib_error_t *
362 memif_msg_receive_connect (memif_if_t * mif, memif_msg_t * msg)
365 memif_msg_connect_t *c = &msg->connect;
367 if ((err = memif_connect (mif)))
370 mif->remote_if_name = memif_str2vec (c->if_name, sizeof (c->if_name));
375 static clib_error_t *
376 memif_msg_receive_connected (memif_if_t * mif, memif_msg_t * msg)
379 memif_msg_connected_t *c = &msg->connected;
381 if ((err = memif_connect (mif)))
384 mif->remote_if_name = memif_str2vec (c->if_name, sizeof (c->if_name));
388 static clib_error_t *
389 memif_msg_receive_disconnect (memif_if_t * mif, memif_msg_t * msg)
391 memif_msg_disconnect_t *d = &msg->disconnect;
393 mif->remote_disc_string = memif_str2vec (d->string, sizeof (d->string));
394 return clib_error_return (0, "disconnect received");
397 static clib_error_t *
398 memif_msg_receive (memif_if_t ** mifp, clib_socket_t * sock, clib_file_t * uf)
400 memif_msg_t msg = { 0 };
401 clib_error_t *err = 0;
404 memif_if_t *mif = *mifp;
406 err = clib_socket_recvmsg (sock, &msg, sizeof (memif_msg_t), &fd, 1);
410 if (mif == 0 && msg.type != MEMIF_MSG_TYPE_INIT)
412 memif_socket_close (&sock);
413 return clib_error_return (0, "unexpected message received");
416 DBG ("Message type %u received", msg.type);
417 /* process the message based on its type */
420 case MEMIF_MSG_TYPE_ACK:
423 case MEMIF_MSG_TYPE_HELLO:
424 if ((err = memif_msg_receive_hello (mif, &msg)))
426 if ((err = memif_init_regions_and_queues (mif)))
428 memif_msg_enq_init (mif);
429 memif_msg_enq_add_region (mif, 0);
430 vec_foreach_index (i, mif->tx_queues)
431 memif_msg_enq_add_ring (mif, i, MEMIF_RING_S2M);
432 vec_foreach_index (i, mif->rx_queues)
433 memif_msg_enq_add_ring (mif, i, MEMIF_RING_M2S);
434 memif_msg_enq_connect (mif);
437 case MEMIF_MSG_TYPE_INIT:
438 if ((err = memif_msg_receive_init (mifp, &msg, sock, uf->private_data)))
441 memif_msg_enq_ack (mif);
444 case MEMIF_MSG_TYPE_ADD_REGION:
445 if ((err = memif_msg_receive_add_region (mif, &msg, fd)))
447 memif_msg_enq_ack (mif);
450 case MEMIF_MSG_TYPE_ADD_RING:
451 if ((err = memif_msg_receive_add_ring (mif, &msg, fd)))
453 memif_msg_enq_ack (mif);
456 case MEMIF_MSG_TYPE_CONNECT:
457 if ((err = memif_msg_receive_connect (mif, &msg)))
459 memif_msg_enq_connected (mif);
462 case MEMIF_MSG_TYPE_CONNECTED:
463 if ((err = memif_msg_receive_connected (mif, &msg)))
467 case MEMIF_MSG_TYPE_DISCONNECT:
468 if ((err = memif_msg_receive_disconnect (mif, &msg)))
473 err = clib_error_return (0, "unknown message type (0x%x)", msg.type);
477 if (clib_fifo_elts (mif->msg_queue))
478 clib_file_set_data_available_to_write (&file_main,
479 mif->sock->private_data, 1);
484 memif_master_conn_fd_read_ready (clib_file_t * uf)
486 memif_main_t *mm = &memif_main;
487 memif_socket_file_t *msf =
488 pool_elt_at_index (mm->socket_files, uf->private_data);
491 clib_socket_t *sock = 0;
492 clib_error_t *err = 0;
494 p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
497 mif = vec_elt_at_index (mm->interfaces, p[0]);
502 /* This is new connection, remove index from pending vector */
504 vec_foreach_index (i, msf->pending_clients)
505 if (msf->pending_clients[i]->fd == uf->file_descriptor)
507 sock = msf->pending_clients[i];
508 vec_del1 (msf->pending_clients, i);
513 err = memif_msg_receive (&mif, sock, uf);
516 memif_disconnect (mif, err);
517 clib_error_free (err);
523 memif_slave_conn_fd_read_ready (clib_file_t * uf)
525 memif_main_t *mm = &memif_main;
527 memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
528 err = memif_msg_receive (&mif, mif->sock, uf);
531 memif_disconnect (mif, err);
532 clib_error_free (err);
537 static clib_error_t *
538 memif_conn_fd_write_ready (clib_file_t * uf, memif_if_t * mif)
540 memif_msg_fifo_elt_t *e;
541 clib_fifo_sub2 (mif->msg_queue, e);
542 clib_file_set_data_available_to_write (&file_main,
543 mif->sock->private_data, 0);
544 return clib_socket_sendmsg (mif->sock, &e->msg, sizeof (memif_msg_t),
545 &e->fd, e->fd > -1 ? 1 : 0);
549 memif_master_conn_fd_write_ready (clib_file_t * uf)
551 memif_main_t *mm = &memif_main;
552 memif_socket_file_t *msf =
553 pool_elt_at_index (mm->socket_files, uf->private_data);
557 p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
561 mif = vec_elt_at_index (mm->interfaces, p[0]);
562 return memif_conn_fd_write_ready (uf, mif);
566 memif_slave_conn_fd_write_ready (clib_file_t * uf)
568 memif_main_t *mm = &memif_main;
569 memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
570 return memif_conn_fd_write_ready (uf, mif);
574 memif_slave_conn_fd_error (clib_file_t * uf)
576 memif_main_t *mm = &memif_main;
577 memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
580 err = clib_error_return (0, "connection fd error");
581 memif_disconnect (mif, err);
582 clib_error_free (err);
588 memif_master_conn_fd_error (clib_file_t * uf)
590 memif_main_t *mm = &memif_main;
591 memif_socket_file_t *msf =
592 pool_elt_at_index (mm->socket_files, uf->private_data);
596 p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
601 mif = vec_elt_at_index (mm->interfaces, p[0]);
602 err = clib_error_return (0, "connection fd error");
603 memif_disconnect (mif, err);
604 clib_error_free (err);
609 vec_foreach_index (i, msf->pending_clients)
610 if (msf->pending_clients[i]->fd == uf->file_descriptor)
612 clib_socket_t *s = msf->pending_clients[i];
613 memif_socket_close (&s);
614 vec_del1 (msf->pending_clients, i);
619 clib_warning ("Error on unknown file descriptor %d", uf->file_descriptor);
626 memif_conn_fd_accept_ready (clib_file_t * uf)
628 memif_main_t *mm = &memif_main;
629 memif_socket_file_t *msf =
630 pool_elt_at_index (mm->socket_files, uf->private_data);
631 clib_file_t template = { 0 };
633 clib_socket_t *client;
635 client = clib_mem_alloc (sizeof (clib_socket_t));
636 memset (client, 0, sizeof (clib_socket_t));
637 err = clib_socket_accept (msf->sock, client);
641 template.read_function = memif_master_conn_fd_read_ready;
642 template.write_function = memif_master_conn_fd_write_ready;
643 template.error_function = memif_master_conn_fd_error;
644 template.file_descriptor = client->fd;
645 template.private_data = uf->private_data;
647 memif_file_add (&client->private_data, &template);
649 err = memif_msg_enq_hello (client);
652 clib_socket_close (client);
656 vec_add1 (msf->pending_clients, client);
661 clib_error_report (err);
662 clib_mem_free (client);
667 * fd.io coding-style-patch-verification: ON
670 * eval: (c-set-style "gnu")