misc: remove GNU Indent directives
[vpp.git] / src / plugins / memif / memif.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 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
19 #define _GNU_SOURCE
20 #include <stdint.h>
21 #include <net/if.h>
22 #include <sys/types.h>
23 #include <fcntl.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/un.h>
27 #include <sys/uio.h>
28 #include <sys/mman.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 <vnet/interface/rx_queue_funcs.h>
38 #include <vnet/interface/tx_queue_funcs.h>
39 #include <vpp/app/version.h>
40 #include <memif/memif.h>
41 #include <memif/private.h>
42
43 memif_main_t memif_main;
44
45 static u32
46 memif_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
47 {
48   /* nothing for now */
49   return 0;
50 }
51
52 static clib_error_t *
53 memif_eth_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hi,
54                               u32 flags)
55 {
56   /* nothing for now */
57   return 0;
58 }
59
60 static void
61 memif_queue_intfd_close (memif_queue_t * mq)
62 {
63   if (mq->int_clib_file_index != ~0)
64     {
65       memif_file_del_by_index (mq->int_clib_file_index);
66       mq->int_clib_file_index = ~0;
67       mq->int_fd = -1;
68     }
69   else if (mq->int_fd > -1)
70     {
71       close (mq->int_fd);
72       mq->int_fd = -1;
73     }
74 }
75
76 static void
77 memif_disconnect_free_zc_queue_buffer (memif_queue_t * mq, u8 is_rx)
78 {
79   vlib_main_t *vm = vlib_get_main ();
80   u16 ring_size, n_slots, mask, start;
81
82   ring_size = 1 << mq->log2_ring_size;
83   mask = ring_size - 1;
84   n_slots = mq->ring->head - mq->last_tail;
85   start = mq->last_tail & mask;
86   if (is_rx)
87     vlib_buffer_free_from_ring (vm, mq->buffers, start, ring_size, n_slots);
88   else
89     vlib_buffer_free_from_ring_no_next (vm, mq->buffers, start, ring_size,
90                                         n_slots);
91   vec_free (mq->buffers);
92 }
93
94 void
95 memif_disconnect (memif_if_t * mif, clib_error_t * err)
96 {
97   memif_main_t *mm = &memif_main;
98   vnet_main_t *vnm = vnet_get_main ();
99   memif_region_t *mr;
100   memif_queue_t *mq;
101   int i;
102   vlib_main_t *vm = vlib_get_main ();
103   int with_barrier = 0;
104
105   if (mif == 0)
106     return;
107
108   memif_log_debug (mif, "disconnect %u (%v)", mif->dev_instance,
109                    err ? err->what : 0);
110
111   if (err)
112     {
113       clib_error_t *e = 0;
114       mif->local_disc_string = vec_dup (err->what);
115       if (mif->sock && clib_socket_is_connected (mif->sock))
116         e = memif_msg_send_disconnect (mif, err);
117       clib_error_free (e);
118     }
119
120   /* set interface down */
121   mif->flags &= ~(MEMIF_IF_FLAG_CONNECTED | MEMIF_IF_FLAG_CONNECTING);
122   if (mif->hw_if_index != ~0)
123     vnet_hw_interface_set_flags (vnm, mif->hw_if_index, 0);
124
125   /* close connection socket */
126   if (mif->sock && mif->sock->fd)
127     {
128       memif_socket_file_t *msf = vec_elt_at_index (mm->socket_files,
129                                                    mif->socket_file_index);
130       hash_unset (msf->dev_instance_by_fd, mif->sock->fd);
131       memif_socket_close (&mif->sock);
132     }
133   else if (mif->sock)
134     {
135       clib_error_t *err;
136       err = clib_socket_close (mif->sock);
137       if (err)
138         {
139           memif_log_err (mif, "%U", format_clib_error, err);
140           clib_error_free (err);
141         }
142       clib_mem_free (mif->sock);
143     }
144
145   if (vlib_worker_thread_barrier_held () == 0)
146     {
147       with_barrier = 1;
148       vlib_worker_thread_barrier_sync (vm);
149     }
150
151   vec_foreach_index (i, mif->rx_queues)
152     {
153       mq = vec_elt_at_index (mif->rx_queues, i);
154       if (mq->ring)
155         {
156           if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
157           {
158             memif_disconnect_free_zc_queue_buffer(mq, 1);
159           }
160           mq->ring = 0;
161         }
162     }
163   vnet_hw_if_unregister_all_rx_queues (vnm, mif->hw_if_index);
164
165   vec_foreach_index (i, mif->tx_queues)
166   {
167     mq = vec_elt_at_index (mif->tx_queues, i);
168     if (mq->ring)
169     {
170       if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
171       {
172         memif_disconnect_free_zc_queue_buffer(mq, 0);
173       }
174       clib_spinlock_free (&mq->lockp);
175     }
176     mq->ring = 0;
177   }
178   vnet_hw_if_unregister_all_tx_queues (vnm, mif->hw_if_index);
179   vnet_hw_if_update_runtime_data (vnm, mif->hw_if_index);
180
181   /* free tx and rx queues */
182   vec_foreach (mq, mif->rx_queues)
183     memif_queue_intfd_close (mq);
184   vec_free (mif->rx_queues);
185
186   vec_foreach (mq, mif->tx_queues)
187     memif_queue_intfd_close (mq);
188   vec_free (mif->tx_queues);
189
190   /* free memory regions */
191   vec_foreach (mr, mif->regions)
192     {
193       int rv;
194       if (mr->is_external)
195         continue;
196       if ((rv = munmap (mr->shm, mr->region_size)))
197         memif_log_err (mif, "munmap failed, rv = %d", rv);
198       if (mr->fd > -1)
199         close (mr->fd);
200     }
201   vec_free (mif->regions);
202   vec_free (mif->remote_name);
203   vec_free (mif->remote_if_name);
204   clib_fifo_free (mif->msg_queue);
205
206   if (with_barrier)
207     vlib_worker_thread_barrier_release (vm);
208 }
209
210 static clib_error_t *
211 memif_int_fd_write_ready (clib_file_t * uf)
212 {
213   memif_main_t *mm = &memif_main;
214   u16 qid = uf->private_data & 0xFFFF;
215   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data >> 16);
216
217   memif_log_warn (mif, "unexpected EPOLLOUT on RX for queue %u", qid);
218   return 0;
219 }
220
221 static clib_error_t *
222 memif_int_fd_read_ready (clib_file_t * uf)
223 {
224   memif_main_t *mm = &memif_main;
225   vnet_main_t *vnm = vnet_get_main ();
226   u16 qid = uf->private_data & 0xFFFF;
227   memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data >> 16);
228   memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, qid);
229   u64 b;
230   ssize_t size;
231
232   size = read (uf->file_descriptor, &b, sizeof (b));
233   if (size < 0)
234     {
235       memif_log_debug (mif, "Failed to read from socket");
236       return 0;
237     }
238
239   vnet_hw_if_rx_queue_set_int_pending (vnm, mq->queue_index);
240   mq->int_count++;
241
242   return 0;
243 }
244
245
246 clib_error_t *
247 memif_connect (memif_if_t * mif)
248 {
249   memif_main_t *mm = &memif_main;
250   vlib_main_t *vm = vlib_get_main ();
251   vnet_main_t *vnm = vnet_get_main ();
252   clib_file_t template = { 0 };
253   memif_region_t *mr;
254   int i, j;
255   u32 n_txqs = 0, n_threads = vlib_get_n_threads ();
256   clib_error_t *err = NULL;
257   u8 max_log2_ring_sz = 0;
258   int with_barrier = 0;
259
260   memif_log_debug (mif, "connect %u", mif->dev_instance);
261
262   vec_free (mif->local_disc_string);
263   vec_free (mif->remote_disc_string);
264
265   vec_foreach (mr, mif->regions)
266     {
267       if (mr->shm)
268         continue;
269
270       if (mr->fd < 0)
271         {
272           err = clib_error_return (0, "no memory region fd");
273           goto error;
274         }
275
276       if ((mr->shm = mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
277                            MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
278         {
279           err = clib_error_return_unix (0, "mmap");
280           goto error;
281         }
282     }
283
284   template.read_function = memif_int_fd_read_ready;
285   template.write_function = memif_int_fd_write_ready;
286
287   with_barrier = 1;
288   if (vlib_worker_thread_barrier_held ())
289     with_barrier = 0;
290
291   if (with_barrier)
292     vlib_worker_thread_barrier_sync (vm);
293
294   vec_foreach_index (i, mif->tx_queues)
295     {
296       memif_queue_t *mq = vec_elt_at_index (mif->tx_queues, i);
297       max_log2_ring_sz = clib_max (max_log2_ring_sz, mq->log2_ring_size);
298
299       mq->ring = mif->regions[mq->region].shm + mq->offset;
300       if (mq->ring->cookie != MEMIF_COOKIE)
301         {
302           err = clib_error_return (0, "wrong cookie on tx ring %u", i);
303           goto error;
304         }
305       mq->queue_index =
306         vnet_hw_if_register_tx_queue (vnm, mif->hw_if_index, i);
307       clib_spinlock_init (&mq->lockp);
308
309       if (mif->flags & MEMIF_IF_FLAG_USE_DMA)
310         {
311           memif_dma_info_t *dma_info;
312           mq->dma_head = 0;
313           mq->dma_tail = 0;
314           mq->dma_info_head = 0;
315           mq->dma_info_tail = 0;
316           mq->dma_info_size = MEMIF_DMA_INFO_SIZE;
317           vec_validate_aligned (mq->dma_info, MEMIF_DMA_INFO_SIZE,
318                                 CLIB_CACHE_LINE_BYTES);
319
320           vec_foreach (dma_info, mq->dma_info)
321             {
322               vec_validate_aligned (dma_info->data.desc_data,
323                                     pow2_mask (max_log2_ring_sz),
324                                     CLIB_CACHE_LINE_BYTES);
325               vec_validate_aligned (dma_info->data.desc_len,
326                                     pow2_mask (max_log2_ring_sz),
327                                     CLIB_CACHE_LINE_BYTES);
328               vec_validate_aligned (dma_info->data.desc_status,
329                                     pow2_mask (max_log2_ring_sz),
330                                     CLIB_CACHE_LINE_BYTES);
331               vec_validate_aligned (dma_info->data.copy_ops, 0,
332                                     CLIB_CACHE_LINE_BYTES);
333               vec_reset_length (dma_info->data.copy_ops);
334               vec_validate_aligned (dma_info->data.buffers, 0,
335                                     CLIB_CACHE_LINE_BYTES);
336               vec_reset_length (dma_info->data.buffers);
337             }
338         }
339     }
340
341   if (vec_len (mif->tx_queues) > 0)
342     {
343       n_txqs = vec_len (mif->tx_queues);
344       for (j = 0; j < n_threads; j++)
345         {
346           u32 qi = mif->tx_queues[j % n_txqs].queue_index;
347           vnet_hw_if_tx_queue_assign_thread (vnm, qi, j);
348         }
349     }
350
351   vec_foreach_index (i, mif->rx_queues)
352     {
353       memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, i);
354       u32 ti;
355       u32 qi;
356       int rv;
357
358       max_log2_ring_sz = clib_max (max_log2_ring_sz, mq->log2_ring_size);
359
360       mq->ring = mif->regions[mq->region].shm + mq->offset;
361       if (mq->ring->cookie != MEMIF_COOKIE)
362         {
363           err = clib_error_return (0, "wrong cookie on tx ring %u", i);
364           goto error;
365         }
366       qi = vnet_hw_if_register_rx_queue (vnm, mif->hw_if_index, i,
367                                          VNET_HW_IF_RXQ_THREAD_ANY);
368       mq->queue_index = qi;
369
370       if (mif->flags & MEMIF_IF_FLAG_USE_DMA)
371         {
372           memif_dma_info_t *dma_info;
373           mq->dma_head = 0;
374           mq->dma_tail = 0;
375           mq->dma_info_head = 0;
376           mq->dma_info_tail = 0;
377           mq->dma_info_size = MEMIF_DMA_INFO_SIZE;
378           vec_validate_aligned (mq->dma_info, MEMIF_DMA_INFO_SIZE,
379                                 CLIB_CACHE_LINE_BYTES);
380           vec_foreach (dma_info, mq->dma_info)
381             {
382               vec_validate_aligned (dma_info->data.desc_data,
383                                     pow2_mask (max_log2_ring_sz),
384                                     CLIB_CACHE_LINE_BYTES);
385               vec_validate_aligned (dma_info->data.desc_len,
386                                     pow2_mask (max_log2_ring_sz),
387                                     CLIB_CACHE_LINE_BYTES);
388               vec_validate_aligned (dma_info->data.desc_status,
389                                     pow2_mask (max_log2_ring_sz),
390                                     CLIB_CACHE_LINE_BYTES);
391               vec_validate_aligned (dma_info->data.copy_ops, 0,
392                                     CLIB_CACHE_LINE_BYTES);
393               vec_reset_length (dma_info->data.copy_ops);
394               vec_validate_aligned (dma_info->data.buffers, 0,
395                                     CLIB_CACHE_LINE_BYTES);
396               vec_reset_length (dma_info->data.buffers);
397             }
398         }
399
400       if (mq->int_fd > -1)
401         {
402           template.file_descriptor = mq->int_fd;
403           template.private_data = (mif->dev_instance << 16) | (i & 0xFFFF);
404           template.description = format (0, "%U rx %u int",
405                                          format_memif_device_name,
406                                          mif->dev_instance, i);
407           memif_file_add (&mq->int_clib_file_index, &template);
408           vnet_hw_if_set_rx_queue_file_index (vnm, qi,
409                                               mq->int_clib_file_index);
410         }
411       ti = vnet_hw_if_get_rx_queue_thread_index (vnm, qi);
412       mq->buffer_pool_index = vlib_buffer_pool_get_default_for_numa (
413         vm, vlib_get_main_by_index (ti)->numa_node);
414       rv = vnet_hw_if_set_rx_queue_mode (vnm, qi, VNET_HW_IF_RX_MODE_DEFAULT);
415       vnet_hw_if_update_runtime_data (vnm, mif->hw_if_index);
416
417       if (rv)
418         memif_log_err
419           (mif, "Warning: unable to set rx mode for interface %d queue %d: "
420            "rc=%d", mif->hw_if_index, i, rv);
421       else
422         {
423           vnet_hw_if_rx_mode rxmode = vnet_hw_if_get_rx_queue_mode (vnm, qi);
424
425           if (rxmode == VNET_HW_IF_RX_MODE_POLLING)
426             mq->ring->flags |= MEMIF_RING_FLAG_MASK_INT;
427           else
428             vnet_hw_if_rx_queue_set_int_pending (vnm, qi);
429         }
430     }
431
432   if (1 << max_log2_ring_sz > vec_len (mm->per_thread_data[0].desc_data))
433     {
434       memif_per_thread_data_t *ptd;
435
436       vec_foreach (ptd, mm->per_thread_data)
437         {
438           vec_validate_aligned (ptd->desc_data, pow2_mask (max_log2_ring_sz),
439                                 CLIB_CACHE_LINE_BYTES);
440           vec_validate_aligned (ptd->desc_len, pow2_mask (max_log2_ring_sz),
441                                 CLIB_CACHE_LINE_BYTES);
442           vec_validate_aligned (ptd->desc_status, pow2_mask (max_log2_ring_sz),
443                                 CLIB_CACHE_LINE_BYTES);
444         }
445     }
446   if (with_barrier)
447     vlib_worker_thread_barrier_release (vm);
448
449   mif->flags &= ~MEMIF_IF_FLAG_CONNECTING;
450   mif->flags |= MEMIF_IF_FLAG_CONNECTED;
451
452   vnet_hw_interface_set_flags (vnm, mif->hw_if_index,
453                                VNET_HW_INTERFACE_FLAG_LINK_UP);
454   return 0;
455
456 error:
457   if (with_barrier)
458     vlib_worker_thread_barrier_release (vm);
459   memif_log_err (mif, "%U", format_clib_error, err);
460   return err;
461 }
462
463 static_always_inline memif_ring_t *
464 memif_get_ring (memif_if_t * mif, memif_ring_type_t type, u16 ring_num)
465 {
466   if (vec_len (mif->regions) == 0)
467     return NULL;
468   void *p = mif->regions[0].shm;
469   int ring_size =
470     sizeof (memif_ring_t) +
471     sizeof (memif_desc_t) * (1 << mif->run.log2_ring_size);
472   p += (ring_num + type * mif->run.num_s2m_rings) * ring_size;
473
474   return (memif_ring_t *) p;
475 }
476
477 clib_error_t *
478 memif_init_regions_and_queues (memif_if_t * mif)
479 {
480   vlib_main_t *vm = vlib_get_main ();
481   memif_socket_file_t *msf;
482   memif_ring_t *ring = NULL;
483   int fd, i, j;
484   u64 buffer_offset;
485   memif_region_t *r;
486   clib_error_t *err;
487
488   ASSERT (vec_len (mif->regions) == 0);
489   vec_add2_aligned (mif->regions, r, 1, CLIB_CACHE_LINE_BYTES);
490
491   buffer_offset = (mif->run.num_s2m_rings + mif->run.num_m2s_rings) *
492     (sizeof (memif_ring_t) +
493      sizeof (memif_desc_t) * (1 << mif->run.log2_ring_size));
494
495   r->region_size = buffer_offset;
496
497   if ((mif->flags & MEMIF_IF_FLAG_ZERO_COPY) == 0)
498     r->region_size += mif->run.buffer_size * (1 << mif->run.log2_ring_size) *
499       (mif->run.num_s2m_rings + mif->run.num_m2s_rings);
500
501   if ((fd = clib_mem_vm_create_fd (CLIB_MEM_PAGE_SZ_DEFAULT, "%U region 0",
502                                    format_memif_device_name,
503                                    mif->dev_instance)) == -1)
504     {
505       err = clib_mem_get_last_error ();
506       goto error;
507     }
508
509   if ((ftruncate (fd, r->region_size)) == -1)
510     {
511       err = clib_error_return_unix (0, "ftruncate");
512       goto error;
513     }
514
515   msf = pool_elt_at_index (memif_main.socket_files, mif->socket_file_index);
516   r->shm = clib_mem_vm_map_shared (0, r->region_size, fd, 0, "memif%lu/%lu:0",
517                                    msf->socket_id, mif->id);
518
519   if (r->shm == CLIB_MEM_VM_MAP_FAILED)
520     {
521       err = clib_error_return_unix (0, "memif shared region map failed");
522       goto error;
523     }
524
525   r->fd = fd;
526
527   if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
528     {
529       vlib_buffer_pool_t *bp;
530       vec_foreach (bp, vm->buffer_main->buffer_pools)
531         {
532           vlib_physmem_map_t *pm;
533           pm = vlib_physmem_get_map (vm, bp->physmem_map_index);
534           vec_add2_aligned (mif->regions, r, 1, CLIB_CACHE_LINE_BYTES);
535           r->fd = pm->fd;
536           r->region_size = pm->n_pages << pm->log2_page_size;
537           r->shm = pm->base;
538           r->is_external = 1;
539         }
540     }
541
542   for (i = 0; i < mif->run.num_s2m_rings; i++)
543     {
544       ring = memif_get_ring (mif, MEMIF_RING_S2M, i);
545       ring->head = ring->tail = 0;
546       ring->cookie = MEMIF_COOKIE;
547
548       if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
549         continue;
550
551       for (j = 0; j < (1 << mif->run.log2_ring_size); j++)
552         {
553           u16 slot = i * (1 << mif->run.log2_ring_size) + j;
554           ring->desc[j].region = 0;
555           ring->desc[j].offset =
556             buffer_offset + (u32) (slot * mif->run.buffer_size);
557           ring->desc[j].length = mif->run.buffer_size;
558         }
559     }
560   for (i = 0; i < mif->run.num_m2s_rings; i++)
561     {
562       ring = memif_get_ring (mif, MEMIF_RING_M2S, i);
563       ring->head = ring->tail = 0;
564       ring->cookie = MEMIF_COOKIE;
565
566       if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
567         continue;
568
569       for (j = 0; j < (1 << mif->run.log2_ring_size); j++)
570         {
571           u16 slot =
572             (i + mif->run.num_s2m_rings) * (1 << mif->run.log2_ring_size) + j;
573           ring->desc[j].region = 0;
574           ring->desc[j].offset =
575             buffer_offset + (u32) (slot * mif->run.buffer_size);
576           ring->desc[j].length = mif->run.buffer_size;
577         }
578     }
579
580   ASSERT (mif->tx_queues == 0);
581   vec_validate_aligned (mif->tx_queues, mif->run.num_s2m_rings - 1,
582                         CLIB_CACHE_LINE_BYTES);
583
584   vec_foreach_index (i, mif->tx_queues)
585     {
586       memif_queue_t *mq = vec_elt_at_index (mif->tx_queues, i);
587       if ((mq->int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
588         {
589           err = clib_error_return_unix (0, "eventfd[tx queue %u]", i);
590           goto error;
591         }
592
593       mq->int_clib_file_index = ~0;
594       mq->ring = memif_get_ring (mif, MEMIF_RING_S2M, i);
595       mq->log2_ring_size = mif->cfg.log2_ring_size;
596       mq->region = 0;
597       mq->offset = (void *) mq->ring - (void *) mif->regions[mq->region].shm;
598       mq->last_head = 0;
599       mq->type = MEMIF_RING_S2M;
600       if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
601         vec_validate_aligned (mq->buffers, 1 << mq->log2_ring_size,
602                               CLIB_CACHE_LINE_BYTES);
603     }
604
605   ASSERT (mif->rx_queues == 0);
606   vec_validate_aligned (mif->rx_queues, mif->run.num_m2s_rings - 1,
607                         CLIB_CACHE_LINE_BYTES);
608
609   vec_foreach_index (i, mif->rx_queues)
610     {
611       memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, i);
612       if ((mq->int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
613         {
614           err = clib_error_return_unix (0, "eventfd[rx queue %u]", i);
615           goto error;
616         }
617       mq->int_clib_file_index = ~0;
618       mq->ring = memif_get_ring (mif, MEMIF_RING_M2S, i);
619       mq->log2_ring_size = mif->cfg.log2_ring_size;
620       mq->region = 0;
621       mq->offset = (void *) mq->ring - (void *) mif->regions[mq->region].shm;
622       mq->last_head = 0;
623       mq->type = MEMIF_RING_M2S;
624       if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
625         vec_validate_aligned (mq->buffers, 1 << mq->log2_ring_size,
626                               CLIB_CACHE_LINE_BYTES);
627     }
628
629   return 0;
630
631 error:
632   memif_log_err (mif, "%U", format_clib_error, err);
633   return err;
634 }
635
636 static uword
637 memif_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
638 {
639   memif_main_t *mm = &memif_main;
640   memif_if_t *mif;
641   clib_socket_t *sock;
642   uword *event_data = 0, event_type;
643   u8 enabled = 0;
644   f64 start_time, last_run_duration = 0, now;
645   clib_error_t *err;
646
647   sock = clib_mem_alloc (sizeof (clib_socket_t));
648   clib_memset (sock, 0, sizeof (clib_socket_t));
649
650   while (1)
651     {
652       if (enabled)
653         vlib_process_wait_for_event_or_clock (vm, (f64) 3 -
654                                               last_run_duration);
655       else
656         vlib_process_wait_for_event (vm);
657
658       event_type = vlib_process_get_events (vm, &event_data);
659       vec_reset_length (event_data);
660
661       switch (event_type)
662         {
663         case ~0:
664           break;
665         case MEMIF_PROCESS_EVENT_START:
666           enabled = 1;
667           break;
668         case MEMIF_PROCESS_EVENT_STOP:
669           enabled = 0;
670           continue;
671         case MEMIF_PROCESS_EVENT_ADMIN_UP_DOWN:
672           break;
673         default:
674           ASSERT (0);
675         }
676
677       last_run_duration = start_time = vlib_time_now (vm);
678       pool_foreach (mif, mm->interfaces)
679          {
680           memif_socket_file_t * msf = vec_elt_at_index (mm->socket_files, mif->socket_file_index);
681           /* Allow no more than 10us without a pause */
682           now = vlib_time_now (vm);
683           if (now > start_time + 10e-6)
684             {
685               vlib_process_suspend (vm, 100e-6);        /* suspend for 100 us */
686               start_time = vlib_time_now (vm);
687             }
688
689           if ((mif->flags & MEMIF_IF_FLAG_ADMIN_UP) == 0)
690             continue;
691
692           if (mif->flags & MEMIF_IF_FLAG_CONNECTING)
693             continue;
694
695           if (mif->flags & MEMIF_IF_FLAG_CONNECTED)
696             continue;
697
698           if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
699             {
700               clib_memset (sock, 0, sizeof(clib_socket_t));
701               sock->config = (char *) msf->filename;
702               sock->is_seqpacket = 1;
703               sock->is_blocking = 1;
704
705               if ((err = clib_socket_init (sock)))
706                 {
707                   clib_error_free (err);
708                 }
709               else
710                 {
711                   clib_file_t t = { 0 };
712
713                   t.read_function = memif_slave_conn_fd_read_ready;
714                   t.write_function = memif_slave_conn_fd_write_ready;
715                   t.error_function = memif_slave_conn_fd_error;
716                   t.file_descriptor = sock->fd;
717                   t.private_data = mif->dev_instance;
718                   memif_file_add (&sock->private_data, &t);
719                   t.description = format (0, "%U ctl",
720                                           format_memif_device_name,
721                                           mif->dev_instance);
722                   hash_set (msf->dev_instance_by_fd, sock->fd, mif->dev_instance);
723
724                   mif->flags |= MEMIF_IF_FLAG_CONNECTING;
725                   mif->sock = sock;
726                   sock = clib_mem_alloc (sizeof(clib_socket_t));
727                 }
728             }
729         }
730       last_run_duration = vlib_time_now (vm) - last_run_duration;
731     }
732   return 0;
733 }
734
735 VLIB_REGISTER_NODE (memif_process_node,static) = {
736   .function = memif_process,
737   .type = VLIB_NODE_TYPE_PROCESS,
738   .name = "memif-process",
739 };
740
741 /*
742  * Returns an unused socket id, and ~0 if it can't find one.
743  */
744 u32
745 memif_get_unused_socket_id ()
746 {
747   memif_main_t *mm = &memif_main;
748   uword *p;
749   int i, j;
750
751   static u32 seed = 0;
752   /* limit to 1M tries */
753   for (j = 0; j < 1 << 10; j++)
754     {
755       seed = random_u32 (&seed);
756       for (i = 0; i < 1 << 10; i++)
757         {
758           /* look around randomly generated id */
759           seed += (2 * (i % 2) - 1) * i;
760           if (seed == (u32) ~0)
761             continue;
762           p = hash_get (mm->socket_file_index_by_sock_id, seed);
763           if (!p)
764             return seed;
765         }
766     }
767
768   return ~0;
769 }
770
771 clib_error_t *
772 memif_socket_filename_add_del (u8 is_add, u32 sock_id, char *sock_filename)
773 {
774   memif_main_t *mm = &memif_main;
775   uword *p;
776   memif_socket_file_t *msf;
777   clib_error_t *err = 0;
778   char *dir = 0, *tmp;
779   u32 idx = 0;
780   u8 *name = 0;
781
782   /* allow adding socket id 0 */
783   if (sock_id == 0 && is_add == 0)
784     return vnet_error (VNET_ERR_INVALID_ARGUMENT, "cannot delete socket id 0");
785
786   if (sock_id == ~0)
787     return vnet_error (VNET_ERR_INVALID_ARGUMENT,
788                        "socked id is not specified");
789
790   if (is_add == 0)
791     {
792       p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
793       if (!p)
794         /* Don't delete non-existent entries. */
795         return vnet_error (VNET_ERR_INVALID_ARGUMENT,
796                            "socket file with id %u does not exist", sock_id);
797
798       msf = pool_elt_at_index (mm->socket_files, *p);
799       if (msf->ref_cnt > 0)
800         return vnet_error (VNET_ERR_UNEXPECTED_INTF_STATE,
801                            "socket file '%s' is in use", msf->filename);
802
803       vec_free (msf->filename);
804       pool_put (mm->socket_files, msf);
805
806       hash_unset (mm->socket_file_index_by_sock_id, sock_id);
807
808       return 0;
809     }
810
811   if (sock_filename == 0 || sock_filename[0] == 0)
812     return vnet_error (VNET_ERR_INVALID_ARGUMENT,
813                        "socket filename not specified");
814
815   if (clib_socket_prefix_is_valid (sock_filename))
816     {
817       name = format (0, "%s%c", sock_filename, 0);
818     }
819   else if (sock_filename[0] == '/')
820     {
821       name = format (0, "%s%c", sock_filename, 0);
822     }
823   else
824     {
825       /* copy runtime dir path */
826       vec_add (dir, vlib_unix_get_runtime_dir (),
827                strlen (vlib_unix_get_runtime_dir ()));
828       vec_add1 (dir, '/');
829
830       /* if sock_filename contains dirs, add them to path */
831       tmp = strrchr (sock_filename, '/');
832       if (tmp)
833         {
834           idx = tmp - sock_filename;
835           vec_add (dir, sock_filename, idx);
836         }
837
838       vec_add1 (dir, '\0');
839       /* create socket dir */
840       if ((err = vlib_unix_recursive_mkdir (dir)))
841         {
842           clib_error_free (err);
843           err = vnet_error (VNET_ERR_SYSCALL_ERROR_1,
844                             "unable to create socket dir");
845           goto done;
846         }
847
848       name =
849         format (0, "%s/%s%c", vlib_unix_get_runtime_dir (), sock_filename, 0);
850     }
851
852   p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
853   if (p)
854     {
855       msf = pool_elt_at_index (mm->socket_files, *p);
856       if (strcmp ((char *) msf->filename, (char *) name) == 0)
857         {
858           /* Silently accept identical "add". */
859           goto done;
860         }
861
862       /* But don't allow a direct add of a different filename. */
863       err = vnet_error (VNET_ERR_ENTRY_ALREADY_EXISTS, "entry already exists");
864       goto done;
865     }
866
867   pool_get (mm->socket_files, msf);
868   clib_memset (msf, 0, sizeof (memif_socket_file_t));
869
870   msf->filename = name;
871   msf->socket_id = sock_id;
872   name = 0;
873
874   hash_set (mm->socket_file_index_by_sock_id, sock_id, msf - mm->socket_files);
875
876 done:
877   vec_free (name);
878   vec_free (dir);
879   return err;
880 }
881
882 clib_error_t *
883 memif_delete_if (vlib_main_t *vm, memif_if_t *mif)
884 {
885   vnet_main_t *vnm = vnet_get_main ();
886   memif_main_t *mm = &memif_main;
887   memif_socket_file_t *msf =
888     vec_elt_at_index (mm->socket_files, mif->socket_file_index);
889   clib_error_t *err;
890
891   mif->flags |= MEMIF_IF_FLAG_DELETING;
892   vec_free (mif->local_disc_string);
893   vec_free (mif->remote_disc_string);
894
895   /* bring down the interface */
896   vnet_hw_interface_set_flags (vnm, mif->hw_if_index, 0);
897   vnet_sw_interface_set_flags (vnm, mif->sw_if_index, 0);
898
899   err = clib_error_return (0, "interface deleted");
900   memif_disconnect (mif, err);
901   clib_error_free (err);
902
903   if (mif->hw_if_index != ~0)
904     {
905       /* remove the interface */
906       if (mif->mode == MEMIF_INTERFACE_MODE_IP)
907         vnet_delete_hw_interface (vnm, mif->hw_if_index);
908       else
909         ethernet_delete_interface (vnm, mif->hw_if_index);
910       mif->hw_if_index = ~0;
911     }
912
913   /* free interface data structures */
914   mhash_unset (&msf->dev_instance_by_id, &mif->id, 0);
915
916   /* remove socket file */
917   if (--(msf->ref_cnt) == 0)
918     {
919       if (msf->is_listener)
920         {
921           int i;
922           vec_foreach_index (i, msf->pending_clients)
923             memif_socket_close (msf->pending_clients + i);
924           memif_socket_close (&msf->sock);
925           vec_free (msf->pending_clients);
926         }
927       mhash_free (&msf->dev_instance_by_id);
928       hash_free (msf->dev_instance_by_fd);
929       if (msf->sock)
930         {
931           err = clib_socket_close (msf->sock);
932           if (err)
933             {
934               memif_log_err (mif, "%U", format_clib_error, err);
935               clib_error_free (err);
936             }
937           clib_mem_free (msf->sock);
938         }
939     }
940
941   vec_free (mif->local_disc_string);
942   clib_memset (mif, 0, sizeof (*mif));
943   pool_put (mm->interfaces, mif);
944
945   if (pool_elts (mm->interfaces) == 0)
946     vlib_process_signal_event (vm, memif_process_node.index,
947                                MEMIF_PROCESS_EVENT_STOP, 0);
948
949   return 0;
950 }
951
952 VNET_HW_INTERFACE_CLASS (memif_ip_hw_if_class, static) = {
953   .name = "memif-ip",
954   .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
955   .tx_hash_fn_type = VNET_HASH_FN_TYPE_IP,
956 };
957
958 static void
959 memif_prepare_dma_args (vlib_dma_config_t *args)
960 {
961   args->max_batches = 256;
962   args->max_transfer_size = VLIB_BUFFER_DEFAULT_DATA_SIZE;
963   args->barrier_before_last = 1;
964   args->sw_fallback = 1;
965   args->callback_fn = NULL;
966 }
967
968 clib_error_t *
969 memif_create_if (vlib_main_t *vm, memif_create_if_args_t *args)
970 {
971   memif_main_t *mm = &memif_main;
972   vlib_thread_main_t *tm = vlib_get_thread_main ();
973   vnet_main_t *vnm = vnet_get_main ();
974   vnet_eth_interface_registration_t eir = {};
975   memif_if_t *mif = 0;
976   vnet_sw_interface_t *sw;
977   uword *p;
978   memif_socket_file_t *msf = 0;
979   clib_error_t *err = 0;
980
981   p = hash_get (mm->socket_file_index_by_sock_id, args->socket_id);
982   if (p == 0)
983     {
984       err = vnet_error (VNET_ERR_INVALID_ARGUMENT, "unknown socket id");
985       goto done;
986     }
987
988   msf = vec_elt_at_index (mm->socket_files, p[0]);
989
990   /* existing socket file can be either master or slave but cannot be both */
991   if (msf->ref_cnt > 0)
992     {
993       if ((!msf->is_listener != !args->is_master))
994         {
995           err =
996             vnet_error (VNET_ERR_SUBIF_ALREADY_EXISTS,
997                         "socket file cannot be used by both master and slave");
998           goto done;
999         }
1000
1001       p = mhash_get (&msf->dev_instance_by_id, &args->id);
1002       if (p)
1003         {
1004           err = vnet_error (VNET_ERR_SUBIF_ALREADY_EXISTS,
1005                             "interface already exists");
1006           goto done;
1007         }
1008     }
1009
1010   /* Create new socket file */
1011   if (msf->ref_cnt == 0)
1012     {
1013       mhash_init (&msf->dev_instance_by_id, sizeof (uword),
1014                   sizeof (memif_interface_id_t));
1015       msf->dev_instance_by_fd = hash_create (0, sizeof (uword));
1016       msf->is_listener = (args->is_master != 0);
1017
1018       memif_log_debug (0, "initializing socket file %s", msf->filename);
1019     }
1020
1021   if (mm->per_thread_data == 0)
1022     {
1023       int i;
1024
1025       vec_validate_aligned (mm->per_thread_data, tm->n_vlib_mains - 1,
1026                             CLIB_CACHE_LINE_BYTES);
1027
1028       for (i = 0; i < tm->n_vlib_mains; i++)
1029         {
1030           memif_per_thread_data_t *ptd =
1031             vec_elt_at_index (mm->per_thread_data, i);
1032           vlib_buffer_t *bt = &ptd->buffer_template;
1033           clib_memset (bt, 0, sizeof (vlib_buffer_t));
1034           bt->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
1035           bt->total_length_not_including_first_buffer = 0;
1036           vnet_buffer (bt)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1037
1038           vec_validate_aligned (ptd->copy_ops, 0, CLIB_CACHE_LINE_BYTES);
1039           vec_reset_length (ptd->copy_ops);
1040           vec_validate_aligned (ptd->buffers, 0, CLIB_CACHE_LINE_BYTES);
1041           vec_reset_length (ptd->buffers);
1042         }
1043     }
1044
1045   pool_get (mm->interfaces, mif);
1046   clib_memset (mif, 0, sizeof (*mif));
1047   mif->dev_instance = mif - mm->interfaces;
1048   mif->socket_file_index = msf - mm->socket_files;
1049   mif->id = args->id;
1050   mif->sw_if_index = mif->hw_if_index = mif->per_interface_next_index = ~0;
1051   mif->mode = args->mode;
1052   if (args->secret)
1053     mif->secret = vec_dup (args->secret);
1054
1055   /* register dma config if enabled */
1056   if (args->use_dma)
1057     {
1058       vlib_dma_config_t dma_args;
1059       bzero (&dma_args, sizeof (dma_args));
1060       memif_prepare_dma_args (&dma_args);
1061
1062       dma_args.max_transfers = 1 << args->log2_ring_size;
1063       dma_args.callback_fn = memif_dma_completion_cb;
1064       mif->dma_input_config = vlib_dma_config_add (vm, &dma_args);
1065       dma_args.callback_fn = memif_tx_dma_completion_cb;
1066       mif->dma_tx_config = vlib_dma_config_add (vm, &dma_args);
1067     }
1068
1069   if (mif->mode == MEMIF_INTERFACE_MODE_ETHERNET)
1070     {
1071
1072       if (!args->hw_addr_set)
1073         {
1074           f64 now = vlib_time_now (vm);
1075           u32 rnd;
1076           rnd = (u32) (now * 1e6);
1077           rnd = random_u32 (&rnd);
1078
1079           memcpy (args->hw_addr + 2, &rnd, sizeof (rnd));
1080           args->hw_addr[0] = 2;
1081           args->hw_addr[1] = 0xfe;
1082         }
1083
1084       eir.dev_class_index = memif_device_class.index;
1085       eir.dev_instance = mif->dev_instance;
1086       eir.address = args->hw_addr;
1087       eir.cb.flag_change = memif_eth_flag_change;
1088       eir.cb.set_max_frame_size = memif_eth_set_max_frame_size;
1089       mif->hw_if_index = vnet_eth_register_interface (vnm, &eir);
1090     }
1091   else if (mif->mode == MEMIF_INTERFACE_MODE_IP)
1092     {
1093       mif->hw_if_index =
1094         vnet_register_interface (vnm, memif_device_class.index,
1095                                  mif->dev_instance,
1096                                  memif_ip_hw_if_class.index,
1097                                  mif->dev_instance);
1098     }
1099   else
1100     {
1101       err =
1102         vnet_error (VNET_ERR_SYSCALL_ERROR_2, "unsupported interface mode");
1103       goto error;
1104     }
1105
1106   sw = vnet_get_hw_sw_interface (vnm, mif->hw_if_index);
1107   mif->sw_if_index = sw->sw_if_index;
1108
1109   mif->cfg.log2_ring_size = args->log2_ring_size;
1110   mif->cfg.buffer_size = args->buffer_size;
1111   mif->cfg.num_s2m_rings =
1112     args->is_master ? args->rx_queues : args->tx_queues;
1113   mif->cfg.num_m2s_rings =
1114     args->is_master ? args->tx_queues : args->rx_queues;
1115
1116   args->sw_if_index = mif->sw_if_index;
1117
1118   /* If this is new one, start listening */
1119   if (msf->is_listener && msf->ref_cnt == 0)
1120     {
1121       clib_socket_t *s = clib_mem_alloc (sizeof (clib_socket_t));
1122
1123       ASSERT (msf->sock == 0);
1124       msf->sock = s;
1125
1126       clib_memset (s, 0, sizeof (clib_socket_t));
1127       s->config = (char *) msf->filename;
1128       s->local_only = 1;
1129       s->is_server = 1;
1130       s->allow_group_write = 1;
1131       s->is_seqpacket = 1;
1132       s->passcred = 1;
1133
1134       if ((err = clib_socket_init (s)))
1135         {
1136           err->code = VNET_ERR_SYSCALL_ERROR_4;
1137           goto error;
1138         }
1139
1140       clib_file_t template = { 0 };
1141       template.read_function = memif_conn_fd_accept_ready;
1142       template.file_descriptor = msf->sock->fd;
1143       template.private_data = mif->socket_file_index;
1144       template.description = format (0, "memif listener %s", msf->filename);
1145       memif_file_add (&msf->sock->private_data, &template);
1146     }
1147
1148   msf->ref_cnt++;
1149
1150   if (args->is_master == 0)
1151     {
1152       mif->flags |= MEMIF_IF_FLAG_IS_SLAVE;
1153       if (args->is_zero_copy)
1154         mif->flags |= MEMIF_IF_FLAG_ZERO_COPY;
1155     }
1156
1157   if (args->use_dma)
1158     mif->flags |= MEMIF_IF_FLAG_USE_DMA;
1159
1160   vnet_hw_if_set_caps (vnm, mif->hw_if_index, VNET_HW_IF_CAP_INT_MODE);
1161   vnet_hw_if_set_input_node (vnm, mif->hw_if_index, memif_input_node.index);
1162   mhash_set (&msf->dev_instance_by_id, &mif->id, mif->dev_instance, 0);
1163
1164   if (pool_elts (mm->interfaces) == 1)
1165     {
1166       vlib_process_signal_event (vm, memif_process_node.index,
1167                                  MEMIF_PROCESS_EVENT_START, 0);
1168     }
1169   goto done;
1170
1171 error:
1172   memif_delete_if (vm, mif);
1173   if (err)
1174     memif_log_err (mif, "%U", format_clib_error, err);
1175   return err;
1176
1177 done:
1178   return err;
1179 }
1180
1181 clib_error_t *
1182 memif_interface_admin_up_down (vnet_main_t *vnm, u32 hw_if_index, u32 flags)
1183 {
1184   memif_main_t *mm = &memif_main;
1185   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1186   memif_if_t *mif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
1187   static clib_error_t *error = 0;
1188
1189   if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1190     {
1191       if (mif->flags & MEMIF_IF_FLAG_CONNECTED)
1192         {
1193           vnet_hw_interface_set_flags (vnm, mif->hw_if_index,
1194                                        VNET_HW_INTERFACE_FLAG_LINK_UP);
1195         }
1196       mif->flags |= MEMIF_IF_FLAG_ADMIN_UP;
1197     }
1198   else
1199     mif->flags &= ~MEMIF_IF_FLAG_ADMIN_UP;
1200
1201   vlib_process_signal_event (vnm->vlib_main, memif_process_node.index,
1202                              MEMIF_PROCESS_EVENT_ADMIN_UP_DOWN, 0);
1203   return error;
1204 }
1205
1206 static clib_error_t *
1207 memif_init (vlib_main_t * vm)
1208 {
1209   memif_main_t *mm = &memif_main;
1210
1211   clib_memset (mm, 0, sizeof (memif_main_t));
1212
1213   mm->log_class = vlib_log_register_class ("memif_plugin", 0);
1214   memif_log_debug (0, "initialized");
1215
1216   /* initialize binary API */
1217   memif_plugin_api_hookup (vm);
1218
1219   /*
1220    * Pre-stuff socket filename pool with a non-modifieable mapping
1221    * for socket-id 0 to MEMIF_DEFAULT_SOCKET_FILENAME in the
1222    * default run-time directory.
1223    */
1224   return memif_socket_filename_add_del (1, 0, MEMIF_DEFAULT_SOCKET_FILENAME);
1225 }
1226
1227 VLIB_INIT_FUNCTION (memif_init);
1228
1229 VLIB_PLUGIN_REGISTER () = {
1230     .version = VPP_BUILD_VER,
1231     .description = "Packet Memory Interface (memif) -- Experimental",
1232 };
1233
1234 /*
1235  * fd.io coding-style-patch-verification: ON
1236  *
1237  * Local Variables:
1238  * eval: (c-set-style "gnu")
1239  * End:
1240  */