FD.io VPP  v21.06
Vector Packet Processing
memif.c
Go to the documentation of this file.
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/prctl.h>
30 #include <sys/eventfd.h>
31 #include <inttypes.h>
32 #include <limits.h>
33 
34 #include <vlib/vlib.h>
35 #include <vlib/unix/unix.h>
36 #include <vnet/plugin/plugin.h>
37 #include <vnet/ethernet/ethernet.h>
39 #include <vpp/app/version.h>
40 #include <memif/memif.h>
41 #include <memif/private.h>
42 
44 
45 static u32
47 {
48  /* nothing for now */
49  return 0;
50 }
51 
52 static void
54 {
55  if (mq->int_clib_file_index != ~0)
56  {
58  mq->int_clib_file_index = ~0;
59  mq->int_fd = -1;
60  }
61  else if (mq->int_fd > -1)
62  {
63  close (mq->int_fd);
64  mq->int_fd = -1;
65  }
66 }
67 
68 static void
70 {
72  u16 ring_size, n_slots, mask, start;
73 
74  ring_size = 1 << mq->log2_ring_size;
75  mask = ring_size - 1;
76  n_slots = mq->ring->head - mq->last_tail;
77  start = mq->last_tail & mask;
78  if (is_rx)
79  vlib_buffer_free_from_ring (vm, mq->buffers, start, ring_size, n_slots);
80  else
81  vlib_buffer_free_from_ring_no_next (vm, mq->buffers, start, ring_size,
82  n_slots);
83  vec_free (mq->buffers);
84 }
85 
86 void
88 {
89  memif_main_t *mm = &memif_main;
90  vnet_main_t *vnm = vnet_get_main ();
91  memif_region_t *mr;
92  memif_queue_t *mq;
93  int i;
94 
95  if (mif == 0)
96  return;
97 
98  memif_log_debug (mif, "disconnect %u (%v)", mif->dev_instance,
99  err ? err->what : 0);
100 
101  if (err)
102  {
103  clib_error_t *e = 0;
104  mif->local_disc_string = vec_dup (err->what);
105  if (mif->sock && clib_socket_is_connected (mif->sock))
106  e = memif_msg_send_disconnect (mif, err);
107  clib_error_free (e);
108  }
109 
110  /* set interface down */
111  mif->flags &= ~(MEMIF_IF_FLAG_CONNECTED | MEMIF_IF_FLAG_CONNECTING);
112  if (mif->hw_if_index != ~0)
114 
115  /* close connection socket */
116  if (mif->sock && mif->sock->fd)
117  {
119  mif->socket_file_index);
120  hash_unset (msf->dev_instance_by_fd, mif->sock->fd);
121  memif_socket_close (&mif->sock);
122  }
123  else if (mif->sock)
124  {
125  clib_error_t *err;
126  err = clib_socket_close (mif->sock);
127  if (err)
128  {
129  memif_log_err (mif, "%U", format_clib_error, err);
130  clib_error_free (err);
131  }
132  clib_mem_free (mif->sock);
133  }
134 
135  /* *INDENT-OFF* */
136  vec_foreach_index (i, mif->rx_queues)
137  {
138  mq = vec_elt_at_index (mif->rx_queues, i);
139  if (mq->ring)
140  {
141  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
142  {
144  }
145  mq->ring = 0;
146  }
147  }
150 
151  /* *INDENT-OFF* */
152  vec_foreach_index (i, mif->tx_queues)
153  {
154  mq = vec_elt_at_index (mif->tx_queues, i);
155  if (mq->ring)
156  {
157  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
158  {
160  }
161  }
162  mq->ring = 0;
163  }
164 
165  /* free tx and rx queues */
166  vec_foreach (mq, mif->rx_queues)
168  vec_free (mif->rx_queues);
169 
170  vec_foreach (mq, mif->tx_queues)
172  vec_free (mif->tx_queues);
173 
174  /* free memory regions */
175  vec_foreach (mr, mif->regions)
176  {
177  int rv;
178  if (mr->is_external)
179  continue;
180  if ((rv = munmap (mr->shm, mr->region_size)))
181  memif_log_err (mif, "munmap failed, rv = %d", rv);
182  if (mr->fd > -1)
183  close (mr->fd);
184  }
185  /* *INDENT-ON* */
186  vec_free (mif->regions);
187  vec_free (mif->remote_name);
188  vec_free (mif->remote_if_name);
189  clib_fifo_free (mif->msg_queue);
190 }
191 
192 static clib_error_t *
194 {
195  memif_main_t *mm = &memif_main;
196  u16 qid = uf->private_data & 0xFFFF;
197  memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data >> 16);
198 
199  memif_log_warn (mif, "unexpected EPOLLOUT on RX for queue %u", qid);
200  return 0;
201 }
202 
203 static clib_error_t *
205 {
206  memif_main_t *mm = &memif_main;
207  vnet_main_t *vnm = vnet_get_main ();
208  u16 qid = uf->private_data & 0xFFFF;
209  memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data >> 16);
210  memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, qid);
211  u64 b;
212  ssize_t size;
213 
214  size = read (uf->file_descriptor, &b, sizeof (b));
215  if (size < 0)
216  {
217  memif_log_debug (mif, "Failed to read from socket");
218  return 0;
219  }
220 
222  mq->int_count++;
223 
224  return 0;
225 }
226 
227 
228 clib_error_t *
230 {
232  vnet_main_t *vnm = vnet_get_main ();
233  clib_file_t template = { 0 };
234  memif_region_t *mr;
235  int i;
236  clib_error_t *err = NULL;
237 
238  memif_log_debug (mif, "connect %u", mif->dev_instance);
239 
242 
243  /* *INDENT-OFF* */
244  vec_foreach (mr, mif->regions)
245  {
246  if (mr->shm)
247  continue;
248 
249  if (mr->fd < 0)
250  {
251  err = clib_error_return (0, "no memory region fd");
252  goto error;
253  }
254 
255  if ((mr->shm = mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
256  MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
257  {
258  err = clib_error_return_unix (0, "mmap");
259  goto error;
260  }
261  }
262  /* *INDENT-ON* */
263 
264  template.read_function = memif_int_fd_read_ready;
265  template.write_function = memif_int_fd_write_ready;
266 
267  /* *INDENT-OFF* */
268  vec_foreach_index (i, mif->tx_queues)
269  {
270  memif_queue_t *mq = vec_elt_at_index (mif->tx_queues, i);
271 
272  mq->ring = mif->regions[mq->region].shm + mq->offset;
273  if (mq->ring->cookie != MEMIF_COOKIE)
274  {
275  err = clib_error_return (0, "wrong cookie on tx ring %u", i);
276  goto error;
277  }
278  }
279 
280  vec_foreach_index (i, mif->rx_queues)
281  {
282  memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, i);
283  u32 ti;
284  u32 qi;
285  int rv;
286 
287  mq->ring = mif->regions[mq->region].shm + mq->offset;
288  if (mq->ring->cookie != MEMIF_COOKIE)
289  {
290  err = clib_error_return (0, "wrong cookie on tx ring %u", i);
291  goto error;
292  }
293  qi = vnet_hw_if_register_rx_queue (vnm, mif->hw_if_index, i,
295  mq->queue_index = qi;
296  if (mq->int_fd > -1)
297  {
298  template.file_descriptor = mq->int_fd;
299  template.private_data = (mif->dev_instance << 16) | (i & 0xFFFF);
300  template.description = format (0, "%U rx %u int",
302  mif->dev_instance, i);
303  memif_file_add (&mq->int_clib_file_index, &template);
305  mq->int_clib_file_index);
306  }
309  vm, vlib_get_main_by_index (ti)->numa_node);
312 
313  if (rv)
315  (mif, "Warning: unable to set rx mode for interface %d queue %d: "
316  "rc=%d", mif->hw_if_index, i, rv);
317  else
318  {
320 
321  if (rxmode == VNET_HW_IF_RX_MODE_POLLING)
323  else
325  }
326  }
327  /* *INDENT-ON* */
328 
329  mif->flags &= ~MEMIF_IF_FLAG_CONNECTING;
330  mif->flags |= MEMIF_IF_FLAG_CONNECTED;
331 
334  return 0;
335 
336 error:
337  memif_log_err (mif, "%U", format_clib_error, err);
338  return err;
339 }
340 
343 {
344  if (vec_len (mif->regions) == 0)
345  return NULL;
346  void *p = mif->regions[0].shm;
347  int ring_size =
348  sizeof (memif_ring_t) +
349  sizeof (memif_desc_t) * (1 << mif->run.log2_ring_size);
350  p += (ring_num + type * mif->run.num_s2m_rings) * ring_size;
351 
352  return (memif_ring_t *) p;
353 }
354 
355 clib_error_t *
357 {
359  memif_socket_file_t *msf;
360  memif_ring_t *ring = NULL;
361  int fd, i, j;
362  u64 buffer_offset;
363  memif_region_t *r;
364  clib_error_t *err;
365 
366  ASSERT (vec_len (mif->regions) == 0);
368 
369  buffer_offset = (mif->run.num_s2m_rings + mif->run.num_m2s_rings) *
370  (sizeof (memif_ring_t) +
371  sizeof (memif_desc_t) * (1 << mif->run.log2_ring_size));
372 
373  r->region_size = buffer_offset;
374 
375  if ((mif->flags & MEMIF_IF_FLAG_ZERO_COPY) == 0)
376  r->region_size += mif->run.buffer_size * (1 << mif->run.log2_ring_size) *
377  (mif->run.num_s2m_rings + mif->run.num_m2s_rings);
378 
379  if ((fd = clib_mem_vm_create_fd (CLIB_MEM_PAGE_SZ_DEFAULT, "%U region 0",
381  mif->dev_instance)) == -1)
382  {
383  err = clib_mem_get_last_error ();
384  goto error;
385  }
386 
387  if ((ftruncate (fd, r->region_size)) == -1)
388  {
389  err = clib_error_return_unix (0, "ftruncate");
390  goto error;
391  }
392 
393  msf = pool_elt_at_index (memif_main.socket_files, mif->socket_file_index);
394  r->shm = clib_mem_vm_map_shared (0, r->region_size, fd, 0, "memif%lu/%lu:0",
395  msf->socket_id, mif->id);
396 
397  if (r->shm == CLIB_MEM_VM_MAP_FAILED)
398  {
399  err = clib_error_return_unix (0, "memif shared region map failed");
400  goto error;
401  }
402 
403  r->fd = fd;
404 
405  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
406  {
407  vlib_buffer_pool_t *bp;
408  /* *INDENT-OFF* */
410  {
411  vlib_physmem_map_t *pm;
414  r->fd = pm->fd;
415  r->region_size = pm->n_pages << pm->log2_page_size;
416  r->shm = pm->base;
417  r->is_external = 1;
418  }
419  /* *INDENT-ON* */
420  }
421 
422  for (i = 0; i < mif->run.num_s2m_rings; i++)
423  {
424  ring = memif_get_ring (mif, MEMIF_RING_S2M, i);
425  ring->head = ring->tail = 0;
426  ring->cookie = MEMIF_COOKIE;
427 
428  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
429  continue;
430 
431  for (j = 0; j < (1 << mif->run.log2_ring_size); j++)
432  {
433  u16 slot = i * (1 << mif->run.log2_ring_size) + j;
434  ring->desc[j].region = 0;
435  ring->desc[j].offset =
436  buffer_offset + (u32) (slot * mif->run.buffer_size);
437  ring->desc[j].length = mif->run.buffer_size;
438  }
439  }
440  for (i = 0; i < mif->run.num_m2s_rings; i++)
441  {
442  ring = memif_get_ring (mif, MEMIF_RING_M2S, i);
443  ring->head = ring->tail = 0;
444  ring->cookie = MEMIF_COOKIE;
445 
446  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
447  continue;
448 
449  for (j = 0; j < (1 << mif->run.log2_ring_size); j++)
450  {
451  u16 slot =
452  (i + mif->run.num_s2m_rings) * (1 << mif->run.log2_ring_size) + j;
453  ring->desc[j].region = 0;
454  ring->desc[j].offset =
455  buffer_offset + (u32) (slot * mif->run.buffer_size);
456  ring->desc[j].length = mif->run.buffer_size;
457  }
458  }
459 
460  ASSERT (mif->tx_queues == 0);
463 
464  /* *INDENT-OFF* */
465  vec_foreach_index (i, mif->tx_queues)
466  {
467  memif_queue_t *mq = vec_elt_at_index (mif->tx_queues, i);
468  if ((mq->int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
469  {
470  err = clib_error_return_unix (0, "eventfd[tx queue %u]", i);
471  goto error;
472  }
473  mq->int_clib_file_index = ~0;
474  mq->ring = memif_get_ring (mif, MEMIF_RING_S2M, i);
475  mq->log2_ring_size = mif->cfg.log2_ring_size;
476  mq->region = 0;
477  mq->offset = (void *) mq->ring - (void *) mif->regions[mq->region].shm;
478  mq->last_head = 0;
479  mq->type = MEMIF_RING_S2M;
480  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
483  }
484  /* *INDENT-ON* */
485 
486  ASSERT (mif->rx_queues == 0);
489 
490  /* *INDENT-OFF* */
491  vec_foreach_index (i, mif->rx_queues)
492  {
493  memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, i);
494  if ((mq->int_fd = eventfd (0, EFD_NONBLOCK)) < 0)
495  {
496  err = clib_error_return_unix (0, "eventfd[rx queue %u]", i);
497  goto error;
498  }
499  mq->int_clib_file_index = ~0;
500  mq->ring = memif_get_ring (mif, MEMIF_RING_M2S, i);
501  mq->log2_ring_size = mif->cfg.log2_ring_size;
502  mq->region = 0;
503  mq->offset = (void *) mq->ring - (void *) mif->regions[mq->region].shm;
504  mq->last_head = 0;
505  mq->type = MEMIF_RING_M2S;
506  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
509  }
510  /* *INDENT-ON* */
511 
512  return 0;
513 
514 error:
515  memif_log_err (mif, "%U", format_clib_error, err);
516  return err;
517 }
518 
519 static uword
521 {
522  memif_main_t *mm = &memif_main;
523  memif_if_t *mif;
524  clib_socket_t *sock;
525  uword *event_data = 0, event_type;
526  u8 enabled = 0;
527  f64 start_time, last_run_duration = 0, now;
528  clib_error_t *err;
529 
530  sock = clib_mem_alloc (sizeof (clib_socket_t));
531  clib_memset (sock, 0, sizeof (clib_socket_t));
532 
533  while (1)
534  {
535  if (enabled)
537  last_run_duration);
538  else
540 
541  event_type = vlib_process_get_events (vm, &event_data);
542  vec_reset_length (event_data);
543 
544  switch (event_type)
545  {
546  case ~0:
547  break;
549  enabled = 1;
550  break;
552  enabled = 0;
553  continue;
555  break;
556  default:
557  ASSERT (0);
558  }
559 
560  last_run_duration = start_time = vlib_time_now (vm);
561  /* *INDENT-OFF* */
562  pool_foreach (mif, mm->interfaces)
563  {
565  /* Allow no more than 10us without a pause */
566  now = vlib_time_now (vm);
567  if (now > start_time + 10e-6)
568  {
569  vlib_process_suspend (vm, 100e-6); /* suspend for 100 us */
570  start_time = vlib_time_now (vm);
571  }
572 
573  if ((mif->flags & MEMIF_IF_FLAG_ADMIN_UP) == 0)
574  continue;
575 
576  if (mif->flags & MEMIF_IF_FLAG_CONNECTING)
577  continue;
578 
579  if (mif->flags & MEMIF_IF_FLAG_CONNECTED)
580  continue;
581 
582  if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
583  {
584  clib_memset (sock, 0, sizeof(clib_socket_t));
585  sock->config = (char *) msf->filename;
588 
589  if ((err = clib_socket_init (sock)))
590  {
591  clib_error_free (err);
592  }
593  else
594  {
595  clib_file_t t = { 0 };
596 
600  t.file_descriptor = sock->fd;
601  t.private_data = mif->dev_instance;
602  memif_file_add (&sock->private_data, &t);
603  t.description = format (0, "%U ctl",
605  mif->dev_instance);
606  hash_set (msf->dev_instance_by_fd, sock->fd, mif->dev_instance);
607 
608  mif->flags |= MEMIF_IF_FLAG_CONNECTING;
609  mif->sock = sock;
610  sock = clib_mem_alloc (sizeof(clib_socket_t));
611  }
612  }
613  }
614  /* *INDENT-ON* */
615  last_run_duration = vlib_time_now (vm) - last_run_duration;
616  }
617  return 0;
618 }
619 
620 /* *INDENT-OFF* */
622  .function = memif_process,
623  .type = VLIB_NODE_TYPE_PROCESS,
624  .name = "memif-process",
625 };
626 /* *INDENT-ON* */
627 
628 static int
629 memif_add_socket_file (u32 sock_id, u8 * socket_filename)
630 {
631  memif_main_t *mm = &memif_main;
632  uword *p;
633  memif_socket_file_t *msf;
634 
635  p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
636  if (p)
637  {
638  msf = pool_elt_at_index (mm->socket_files, *p);
639  if (strcmp ((char *) msf->filename, (char *) socket_filename) == 0)
640  {
641  /* Silently accept identical "add". */
642  return 0;
643  }
644 
645  /* But don't allow a direct add of a different filename. */
646  return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
647  }
648 
649  pool_get (mm->socket_files, msf);
650  clib_memset (msf, 0, sizeof (memif_socket_file_t));
651 
652  msf->filename = socket_filename;
653  msf->socket_id = sock_id;
654 
656  msf - mm->socket_files);
657 
658  return 0;
659 }
660 
661 static int
663 {
664  memif_main_t *mm = &memif_main;
665  uword *p;
666  memif_socket_file_t *msf;
667 
668  p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
669  if (!p)
670  {
671  /* Don't delete non-existent entries. */
672  return VNET_API_ERROR_INVALID_ARGUMENT;
673  }
674 
675  msf = pool_elt_at_index (mm->socket_files, *p);
676  if (msf->ref_cnt > 0)
677  {
678  return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
679  }
680 
681  vec_free (msf->filename);
682  pool_put (mm->socket_files, msf);
683 
685 
686  return 0;
687 }
688 
689 int
690 memif_socket_filename_add_del (u8 is_add, u32 sock_id, u8 * sock_filename)
691 {
692  char *dir = 0, *tmp;
693  u32 idx = 0;
694 
695  /* allow adding socket id 0 */
696  if ((sock_id == 0 && is_add == 0) || sock_id == ~0)
697  {
698  return VNET_API_ERROR_INVALID_ARGUMENT;
699  }
700 
701  if (is_add == 0)
702  {
703  return memif_delete_socket_file (sock_id);
704  }
705 
706  if (sock_filename == 0 || sock_filename[0] == 0)
707  {
708  return VNET_API_ERROR_INVALID_ARGUMENT;
709  }
710 
711  if (sock_filename[0] != '/')
712  {
714 
715  /* copy runtime dir path */
717  strlen (vlib_unix_get_runtime_dir ()));
718  vec_add1 (dir, '/');
719 
720  /* if sock_filename contains dirs, add them to path */
721  tmp = strrchr ((char *) sock_filename, '/');
722  if (tmp)
723  {
724  idx = tmp - (char *) sock_filename;
725  vec_add (dir, sock_filename, idx);
726  }
727 
728  vec_add1 (dir, '\0');
729  /* create socket dir */
730  error = vlib_unix_recursive_mkdir (dir);
731  if (error)
732  {
733  clib_error_free (error);
734  return VNET_API_ERROR_SYSCALL_ERROR_1;
735  }
736 
737  sock_filename = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
738  sock_filename, 0);
739  }
740  else
741  {
742  sock_filename = vec_dup (sock_filename);
743 
744  /* check if directory exists */
745  tmp = strrchr ((char *) sock_filename, '/');
746  if (tmp)
747  {
748  idx = tmp - (char *) sock_filename;
749  vec_add (dir, sock_filename, idx);
750  vec_add1 (dir, '\0');
751  }
752 
753  /* check dir existance and access rights for effective user/group IDs */
754  if ((dir == NULL)
755  ||
756  (faccessat ( /* ignored */ -1, dir, F_OK | R_OK | W_OK, AT_EACCESS)
757  < 0))
758  {
759  vec_free (dir);
760  return VNET_API_ERROR_INVALID_ARGUMENT;
761  }
762  }
763  vec_free (dir);
764 
765  return memif_add_socket_file (sock_id, sock_filename);
766 }
767 
768 int
770 {
771  vnet_main_t *vnm = vnet_get_main ();
772  memif_main_t *mm = &memif_main;
773  memif_socket_file_t *msf =
775  clib_error_t *err;
776 
777  mif->flags |= MEMIF_IF_FLAG_DELETING;
780 
781  /* bring down the interface */
784 
785  err = clib_error_return (0, "interface deleted");
786  memif_disconnect (mif, err);
787  clib_error_free (err);
788 
789  if (mif->hw_if_index != ~0)
790  {
791  /* remove the interface */
792  if (mif->mode == MEMIF_INTERFACE_MODE_IP)
794  else
796  mif->hw_if_index = ~0;
797  }
798 
799  /* free interface data structures */
800  clib_spinlock_free (&mif->lockp);
801  mhash_unset (&msf->dev_instance_by_id, &mif->id, 0);
802 
803  /* remove socket file */
804  if (--(msf->ref_cnt) == 0)
805  {
806  if (msf->is_listener)
807  {
808  int i;
809  /* *INDENT-OFF* */
812  /* *INDENT-ON* */
813  memif_socket_close (&msf->sock);
814  vec_free (msf->pending_clients);
815  }
818  if (msf->sock)
819  {
820  err = clib_socket_close (msf->sock);
821  if (err)
822  {
823  memif_log_err (mif, "%U", format_clib_error, err);
824  clib_error_free (err);
825  }
826  clib_mem_free (msf->sock);
827  }
828  }
829 
830  clib_memset (mif, 0, sizeof (*mif));
831  pool_put (mm->interfaces, mif);
832 
833  if (pool_elts (mm->interfaces) == 0)
836 
837  return 0;
838 }
839 
840 /* *INDENT-OFF* */
841 VNET_HW_INTERFACE_CLASS (memif_ip_hw_if_class, static) =
842 {
843  .name = "memif-ip",
845 };
846 /* *INDENT-ON* */
847 
848 int
850 {
851  memif_main_t *mm = &memif_main;
853  vnet_main_t *vnm = vnet_get_main ();
854  memif_if_t *mif = 0;
856  clib_error_t *error = 0;
857  int ret = 0;
858  uword *p;
860  memif_socket_file_t *msf = 0;
861  int rv = 0;
862 
864  if (p == 0)
865  {
866  rv = VNET_API_ERROR_INVALID_ARGUMENT;
867  goto done;
868  }
869 
870  msf = vec_elt_at_index (mm->socket_files, p[0]);
871 
872  /* existing socket file can be either master or slave but cannot be both */
873  if (msf->ref_cnt > 0)
874  {
875  if ((!msf->is_listener != !args->is_master))
876  {
877  rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
878  goto done;
879  }
880 
881  p = mhash_get (&msf->dev_instance_by_id, &args->id);
882  if (p)
883  {
884  rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
885  goto done;
886  }
887  }
888 
889  /* Create new socket file */
890  if (msf->ref_cnt == 0)
891  {
892  struct stat file_stat;
893 
894  /* If we are creating listener make sure file doesn't exist or if it
895  * exists thn delete it if it is old socket file */
896  if (args->is_master && (stat ((char *) msf->filename, &file_stat) == 0))
897  {
898  if (S_ISSOCK (file_stat.st_mode))
899  {
900  unlink ((char *) msf->filename);
901  }
902  else
903  {
904  error = clib_error_return (0, "File exists for %s",
905  msf->filename);
906  rv = VNET_API_ERROR_VALUE_EXIST;
907  goto done;
908  }
909  }
910 
911  mhash_init (&msf->dev_instance_by_id, sizeof (uword),
912  sizeof (memif_interface_id_t));
913  msf->dev_instance_by_fd = hash_create (0, sizeof (uword));
914  msf->is_listener = (args->is_master != 0);
915 
916  memif_log_debug (0, "initializing socket file %s", msf->filename);
917  }
918 
919  if (mm->per_thread_data == 0)
920  {
921  int i;
922 
925 
926  for (i = 0; i < tm->n_vlib_mains; i++)
927  {
930  vlib_buffer_t *bt = &ptd->buffer_template;
931  clib_memset (bt, 0, sizeof (vlib_buffer_t));
932  bt->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
934  vnet_buffer (bt)->sw_if_index[VLIB_TX] = (u32) ~ 0;
935 
936  /* initially prealloc copy_ops so we can use
937  _vec_len instead of vec_elen */
939  vec_reset_length (ptd->copy_ops);
941  vec_reset_length (ptd->buffers);
942  }
943  }
944 
945  pool_get (mm->interfaces, mif);
946  clib_memset (mif, 0, sizeof (*mif));
947  mif->dev_instance = mif - mm->interfaces;
948  mif->socket_file_index = msf - mm->socket_files;
949  mif->id = args->id;
950  mif->sw_if_index = mif->hw_if_index = mif->per_interface_next_index = ~0;
951  mif->mode = args->mode;
952  if (args->secret)
953  mif->secret = vec_dup (args->secret);
954 
955  if (tm->n_vlib_mains > 1)
956  clib_spinlock_init (&mif->lockp);
957 
959  {
960 
961  if (!args->hw_addr_set)
962  {
963  f64 now = vlib_time_now (vm);
964  u32 rnd;
965  rnd = (u32) (now * 1e6);
966  rnd = random_u32 (&rnd);
967 
968  memcpy (args->hw_addr + 2, &rnd, sizeof (rnd));
969  args->hw_addr[0] = 2;
970  args->hw_addr[1] = 0xfe;
971  }
973  mif->dev_instance, args->hw_addr,
974  &mif->hw_if_index,
976  }
977  else if (mif->mode == MEMIF_INTERFACE_MODE_IP)
978  {
979  mif->hw_if_index =
981  mif->dev_instance,
982  memif_ip_hw_if_class.index,
983  mif->dev_instance);
984  }
985  else
986  error = clib_error_return (0, "unsupported interface mode");
987 
988  if (error)
989  {
990  ret = VNET_API_ERROR_SYSCALL_ERROR_2;
991  goto error;
992  }
993 
994  sw = vnet_get_hw_sw_interface (vnm, mif->hw_if_index);
995  mif->sw_if_index = sw->sw_if_index;
996 
997  mif->cfg.log2_ring_size = args->log2_ring_size;
998  mif->cfg.buffer_size = args->buffer_size;
999  mif->cfg.num_s2m_rings =
1000  args->is_master ? args->rx_queues : args->tx_queues;
1001  mif->cfg.num_m2s_rings =
1002  args->is_master ? args->tx_queues : args->rx_queues;
1003 
1004  args->sw_if_index = mif->sw_if_index;
1005 
1006  /* If this is new one, start listening */
1007  if (msf->is_listener && msf->ref_cnt == 0)
1008  {
1009  struct stat file_stat;
1010  clib_socket_t *s = clib_mem_alloc (sizeof (clib_socket_t));
1011 
1012  ASSERT (msf->sock == 0);
1013  msf->sock = s;
1014 
1015  clib_memset (s, 0, sizeof (clib_socket_t));
1016  s->config = (char *) msf->filename;
1017  s->flags = CLIB_SOCKET_F_IS_SERVER |
1020 
1021  if ((error = clib_socket_init (s)))
1022  {
1023  ret = VNET_API_ERROR_SYSCALL_ERROR_4;
1024  goto error;
1025  }
1026 
1027  if (stat ((char *) msf->filename, &file_stat) == -1)
1028  {
1029  ret = VNET_API_ERROR_SYSCALL_ERROR_8;
1030  goto error;
1031  }
1032 
1033  clib_file_t template = { 0 };
1035  template.file_descriptor = msf->sock->fd;
1036  template.private_data = mif->socket_file_index;
1037  template.description = format (0, "memif listener %s", msf->filename);
1038  memif_file_add (&msf->sock->private_data, &template);
1039  }
1040 
1041  msf->ref_cnt++;
1042 
1043  if (args->is_master == 0)
1044  {
1045  mif->flags |= MEMIF_IF_FLAG_IS_SLAVE;
1046  if (args->is_zero_copy)
1047  mif->flags |= MEMIF_IF_FLAG_ZERO_COPY;
1048  }
1049 
1050  hw = vnet_get_hw_interface (vnm, mif->hw_if_index);
1053  mhash_set (&msf->dev_instance_by_id, &mif->id, mif->dev_instance, 0);
1054 
1055  if (pool_elts (mm->interfaces) == 1)
1056  {
1059  }
1060  goto done;
1061 
1062 error:
1063  memif_delete_if (vm, mif);
1064  if (error)
1065  {
1066  memif_log_err (mif, "%U", format_clib_error, error);
1067  clib_error_free (error);
1068  }
1069  return ret;
1070 
1071 done:
1072  return rv;
1073 }
1074 
1075 clib_error_t *
1077 {
1078  memif_main_t *mm = &memif_main;
1079  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1081  static clib_error_t *error = 0;
1082 
1083  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1084  mif->flags |= MEMIF_IF_FLAG_ADMIN_UP;
1085  else
1086  mif->flags &= ~MEMIF_IF_FLAG_ADMIN_UP;
1087 
1090  return error;
1091 }
1092 
1093 static clib_error_t *
1095 {
1096  memif_main_t *mm = &memif_main;
1097 
1098  clib_memset (mm, 0, sizeof (memif_main_t));
1099 
1100  mm->log_class = vlib_log_register_class ("memif_plugin", 0);
1101  memif_log_debug (0, "initialized");
1102 
1103  /* initialize binary API */
1105 
1106  /*
1107  * Pre-stuff socket filename pool with a non-modifieable mapping
1108  * for socket-id 0 to MEMIF_DEFAULT_SOCKET_FILENAME in the
1109  * default run-time directory.
1110  */
1112 
1113  return 0;
1114 }
1115 
1117 
1118 /* *INDENT-OFF* */
1119 VLIB_PLUGIN_REGISTER () = {
1120  .version = VPP_BUILD_VER,
1121  .description = "Packet Memory Interface (memif) -- Experimental",
1122 };
1123 /* *INDENT-ON* */
1124 
1125 /*
1126  * fd.io coding-style-patch-verification: ON
1127  *
1128  * Local Variables:
1129  * eval: (c-set-style "gnu")
1130  * End:
1131  */
memif_if_t * interfaces
Definition: private.h:250
#define memif_log_err(dev, f,...)
Definition: private.h:55
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:339
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:133
vlib_log_class_t log_class
Definition: private.h:259
__clib_export int clib_mem_vm_create_fd(clib_mem_page_sz_t log2_page_size, char *fmt,...)
Definition: mem.c:263
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define hash_set(h, key, value)
Definition: hash.h:255
#define CLIB_MEM_VM_MAP_FAILED
Definition: mem.h:54
vnet_interface_output_runtime_t * rt
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:755
#define hash_unset(h, key)
Definition: hash.h:261
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
u8 * secret
Definition: private.h:180
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, vnet_sw_interface_flags_t flags)
Definition: interface.c:523
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:660
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
clib_socket_t ** pending_clients
Definition: private.h:96
vnet_hw_if_output_node_runtime_t * r
static uword clib_socket_is_connected(clib_socket_t *sock)
Definition: socket.h:112
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
unsigned long u64
Definition: types.h:89
memif_socket_file_t * socket_files
Definition: private.h:253
__clib_export void * clib_mem_vm_map_shared(void *base, uword size, int fd, uword offset, char *fmt,...)
Definition: mem.c:59
memif_log2_ring_size_t log2_ring_size
Definition: private.h:193
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:325
#define vec_add2_aligned(V, P, N, A)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:657
vnet_hw_interface_capabilities_t caps
Definition: interface.h:645
u64 private_data
Definition: file.h:64
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 physmem_map_index
Definition: buffer.h:458
u32 file_descriptor
Definition: file.h:54
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
static clib_error_t * memif_init(vlib_main_t *vm)
Definition: memif.c:1094
vlib_buffer_main_t * buffer_main
Definition: main.h:165
clib_error_t * memif_msg_send_disconnect(memif_if_t *mif, clib_error_t *err)
Definition: socket.c:198
memif_interface_mode_t mode
Definition: private.h:281
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:812
static_always_inline void vnet_hw_if_rx_queue_set_int_pending(vnet_main_t *vnm, u32 queue_index)
vlib_physmem_map_t * vlib_physmem_get_map(vlib_main_t *vm, u32 index)
Definition: physmem.c:86
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:535
u32 * buffers
Definition: private.h:134
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:513
u8 num_m2s_rings
Definition: private.h:195
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
#define CLIB_SOCKET_F_BLOCKING
Definition: socket.h:65
__clib_export clib_error_t * clib_socket_init(clib_socket_t *s)
Definition: socket.c:390
#define memif_file_del_by_index(a)
Definition: private.h:83
uint32_t length
Definition: memif.h:154
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
clib_file_function_t * read_function
Definition: file.h:67
double f64
Definition: types.h:142
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:72
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
unsigned int u32
Definition: types.h:88
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:689
#define CLIB_SOCKET_F_IS_SERVER
Definition: socket.h:58
vlib_frame_t * f
static uword vlib_process_suspend(vlib_main_t *vm, f64 dt)
Suspend a vlib cooperative multi-tasking thread for a period of time.
Definition: node_funcs.h:486
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
#define static_always_inline
Definition: clib.h:112
u8 * remote_name
Definition: private.h:188
static int memif_add_socket_file(u32 sock_id, u8 *socket_filename)
Definition: memif.c:629
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:583
clib_error_t * memif_plugin_api_hookup(vlib_main_t *vm)
Definition: memif_api.c:354
uword socket_file_index
Definition: private.h:178
static char * vlib_unix_get_runtime_dir(void)
Definition: unix.h:151
uint32_t cookie
Definition: memif.h:168
u8 buffer_pool_index
Definition: private.h:135
clib_error_t * memif_init_regions_and_queues(memif_if_t *mif)
Definition: memif.c:356
u16 buffer_size
Definition: private.h:196
description fragment has unexpected format
Definition: map.api:433
memif_log2_ring_size_t log2_ring_size
Definition: private.h:282
static void memif_disconnect_free_zc_queue_buffer(memif_queue_t *mq, u8 is_rx)
Definition: memif.c:69
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
vnet_device_class_t memif_device_class
u32 per_interface_next_index
Definition: private.h:174
static int memif_delete_socket_file(u32 sock_id)
Definition: memif.c:662
#define clib_error_return(e, args...)
Definition: error.h:99
clib_error_t * memif_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: memif.c:1076
vnet_main_t * vnet_get_main(void)
memif_region_offset_t offset
Definition: private.h:130
vlib_node_registration_t memif_input_node
(constructor) VLIB_REGISTER_NODE (memif_input_node)
Definition: node.c:885
#define memif_file_add(a, b)
Definition: private.h:66
int __clib_unused rv
Definition: application.c:491
void * shm
Definition: private.h:111
static u32 memif_eth_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hi, u32 flags)
Definition: memif.c:46
mhash_t dev_instance_by_id
Definition: private.h:101
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
static void vlib_buffer_free_from_ring(vlib_main_t *vm, u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
Free buffers from ring.
vl_api_fib_path_type_t type
Definition: fib_types.api:123
memif_region_index_t region
Definition: memif.h:153
u16 last_head
Definition: private.h:132
Definition: cJSON.c:88
u8 * description
Definition: file.h:70
#define hash_get(h, key)
Definition: hash.h:249
memif_copy_op_t * copy_ops
Definition: private.h:235
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
u32 vnet_hw_if_register_rx_queue(vnet_main_t *vnm, u32 hw_if_index, u32 queue_id, u32 thread_index)
Definition: rx_queue.c:64
vlib_main_t * vlib_main
Definition: vnet.h:111
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1019
int memif_delete_if(vlib_main_t *vm, memif_if_t *mif)
Definition: memif.c:769
uword dev_instance
Definition: private.h:171
static clib_error_t * clib_socket_close(clib_socket_t *sock)
Definition: socket.h:175
clib_spinlock_t lockp
Definition: private.h:166
unsigned short u16
Definition: types.h:57
#define clib_error_return_unix(e, args...)
Definition: error.h:102
u32 size
Definition: vhost_user.h:125
#define hash_free(h)
Definition: hash.h:310
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:444
vlib_buffer_pool_t * buffer_pools
Definition: buffer.h:482
u32 * tmp
memif_interface_id_t id
Definition: private.h:276
int memif_create_if(vlib_main_t *vm, memif_create_if_args_t *args)
Definition: memif.c:849
uword int_clib_file_index
Definition: private.h:139
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
void vnet_hw_if_update_runtime_data(vnet_main_t *vnm, u32 hw_if_index)
Definition: runtime.c:58
VNET_HW_INTERFACE_CLASS(memif_ip_hw_if_class, static)
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
static clib_error_t * memif_int_fd_write_ready(clib_file_t *uf)
Definition: memif.c:193
__clib_export void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
memif_queue_t * tx_queues
Definition: private.h:185
clib_error_t * memif_connect(memif_if_t *mif)
Definition: memif.c:229
int vnet_hw_if_set_rx_queue_mode(vnet_main_t *vnm, u32 queue_index, vnet_hw_if_rx_mode mode)
Definition: rx_queue.c:167
u8 slot
Definition: pci_types.api:22
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 ti
u8 * local_disc_string
Definition: private.h:208
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
vl_api_pnat_mask_t mask
Definition: pnat.api:45
int memif_socket_filename_add_del(u8 is_add, u32 sock_id, u8 *sock_filename)
Definition: memif.c:690
uint32_t memif_interface_id_t
Definition: memif.h:66
u16 last_tail
Definition: private.h:133
void memif_disconnect(memif_if_t *mif, clib_error_t *err)
Definition: memif.c:87
u8 * format_memif_device_name(u8 *s, va_list *args)
Definition: device.c:51
memif_ring_type_t type
Definition: private.h:143
memif_desc_t desc[]
Definition: memif.h:175
memif_region_t * regions
Definition: private.h:182
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define ASSERT(truth)
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
static void memif_queue_intfd_close(memif_queue_t *mq)
Definition: memif.c:53
static void mhash_free(mhash_t *h)
Definition: mhash.h:149
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:1052
static clib_error_t * memif_int_fd_read_ready(clib_file_t *uf)
Definition: memif.c:204
u32 flags
Definition: private.h:167
memif_ring_t * ring
Definition: private.h:127
static void clib_mem_free(void *p)
Definition: mem.h:311
struct memif_if_t::@719 run
#define CLIB_SOCKET_F_IS_CLIENT
Definition: socket.h:59
vlib_buffer_t buffer_template
Definition: private.h:239
u32 hw_if_index
Definition: private.h:169
struct memif_if_t::@718 cfg
struct _socket_t clib_socket_t
u32 queue_index
Definition: private.h:144
clib_error_t * memif_slave_conn_fd_write_ready(clib_file_t *uf)
Definition: socket.c:596
#define clib_fifo_free(f)
Definition: fifo.h:257
#define MEMIF_RING_FLAG_MASK_INT
Definition: memif.h:170
static void * clib_mem_alloc(uword size)
Definition: mem.h:253
clib_error_t * memif_slave_conn_fd_error(clib_file_t *uf)
Definition: socket.c:604
#define CLIB_SOCKET_F_SEQPACKET
Definition: socket.h:63
clib_error_t * memif_slave_conn_fd_read_ready(clib_file_t *uf)
Definition: socket.c:553
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
vl_api_ip4_address_t hi
Definition: arp.api:37
u64 int_count
Definition: private.h:140
memif_region_offset_t offset
Definition: memif.h:155
uword * dev_instance_by_fd
Definition: private.h:104
u8 num_s2m_rings
Definition: private.h:194
__clib_export uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
static_always_inline clib_error_t * clib_mem_get_last_error(void)
Definition: mem.h:553
VLIB_PLUGIN_REGISTER()
void vnet_hw_if_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: rx_queue.c:157
Definition: defs.h:47
clib_error_t * vlib_unix_recursive_mkdir(char *path)
Definition: util.c:103
static vlib_main_t * vlib_get_main_by_index(u32 thread_index)
Definition: global_funcs.h:29
static_always_inline memif_ring_t * memif_get_ring(memif_if_t *mif, memif_ring_type_t type, u16 ring_num)
Definition: memif.c:342
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define MEMIF_DEFAULT_SOCKET_FILENAME
Definition: private.h:21
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, const u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:348
#define CLIB_SOCKET_F_PASSCRED
Definition: socket.h:64
#define memif_log_warn(dev, f,...)
Definition: private.h:44
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
a point 2 point interface
Definition: interface.h:394
void memif_socket_close(clib_socket_t **sock)
Definition: socket.c:43
void vnet_hw_if_unregister_all_rx_queues(vnet_main_t *vnm, u32 hw_if_index)
Definition: rx_queue.c:122
#define clib_error_free(e)
Definition: error.h:86
u8 * remote_if_name
Definition: private.h:189
clib_file_function_t * error_function
Definition: file.h:67
memif_interface_id_t id
Definition: private.h:168
memif_log2_ring_size_t log2_ring_size
Definition: private.h:128
#define vnet_buffer(b)
Definition: buffer.h:437
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
uint16_t flags
Definition: memif.h:169
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:56
memif_per_thread_data_t * per_thread_data
Definition: private.h:257
static vlib_node_registration_t memif_process_node
(constructor) VLIB_REGISTER_NODE (memif_process_node)
Definition: memif.c:621
f64 now
vnet_hw_if_rx_mode
Definition: interface.h:53
#define memif_log_debug(dev, f,...)
Definition: private.h:33
u8 * remote_disc_string
Definition: private.h:209
memif_ring_type_t
Definition: memif.h:49
#define vec_foreach(var, vec)
Vector iterator.
volatile uint16_t head
Definition: memif.h:171
vnet_hw_if_rx_mode vnet_hw_if_get_rx_queue_mode(vnet_main_t *vnm, u32 queue_index)
Definition: rx_queue.c:208
Definition: file.h:51
clib_socket_t * sock
Definition: private.h:177
memif_queue_t * rx_queues
Definition: private.h:184
clib_error_t * memif_conn_fd_accept_ready(clib_file_t *uf)
Definition: socket.c:657
uword * socket_file_index_by_sock_id
Definition: private.h:254
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:176
#define CLIB_SOCKET_F_ALLOW_GROUP_WRITE
Definition: socket.h:62
memif_msg_fifo_elt_t * msg_queue
Definition: private.h:179
memif_main_t memif_main
Definition: memif.c:43
clib_file_function_t * write_function
Definition: file.h:67
static u8 vlib_buffer_pool_get_default_for_numa(vlib_main_t *vm, u32 numa_node)
Definition: buffer_funcs.h:189
static void vlib_buffer_free_from_ring_no_next(vlib_main_t *vm, u32 *ring, u32 start, u32 ring_size, u32 n_buffers)
Free buffers from ring without freeing tail buffers.
memif_region_index_t region
Definition: private.h:129
#define VNET_HW_IF_RXQ_THREAD_ANY
Definition: interface.h:598
clib_socket_t * sock
Definition: private.h:95
#define MEMIF_COOKIE
Definition: memif.h:25
__clib_export u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
u32 sw_if_index
Definition: private.h:170
volatile uint16_t tail
Definition: memif.h:173
void vnet_hw_if_set_rx_queue_file_index(vnet_main_t *vnm, u32 queue_index, u32 file_index)
Definition: rx_queue.c:144
memif_interface_mode_t mode
Definition: private.h:172
static uword memif_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: memif.c:520
memif_region_size_t region_size
Definition: private.h:112
static_always_inline u32 vnet_hw_if_get_rx_queue_thread_index(vnet_main_t *vnm, u32 queue_index)
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127