FD.io VPP  v21.01.1
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 <vppinfra/linux/syscall.h>
37 #include <vnet/plugin/plugin.h>
38 #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  int rv;
143  if (rv)
144  memif_log_warn (mif,
145  "Unable to unassign interface %d, queue %d: rc=%d",
146  mif->hw_if_index, i, rv);
147  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
148  {
150  }
151  mq->ring = 0;
152  }
153  }
154 
155  /* *INDENT-OFF* */
156  vec_foreach_index (i, mif->tx_queues)
157  {
158  mq = vec_elt_at_index (mif->tx_queues, i);
159  if (mq->ring)
160  {
161  if (mif->flags & MEMIF_IF_FLAG_ZERO_COPY)
162  {
164  }
165  }
166  mq->ring = 0;
167  }
168 
169  /* free tx and rx queues */
170  vec_foreach (mq, mif->rx_queues)
172  vec_free (mif->rx_queues);
173 
174  vec_foreach (mq, mif->tx_queues)
176  vec_free (mif->tx_queues);
177 
178  /* free memory regions */
179  vec_foreach (mr, mif->regions)
180  {
181  int rv;
182  if (mr->is_external)
183  continue;
184  if ((rv = munmap (mr->shm, mr->region_size)))
185  memif_log_err (mif, "munmap failed, rv = %d", rv);
186  if (mr->fd > -1)
187  close (mr->fd);
188  }
189  /* *INDENT-ON* */
190  vec_free (mif->regions);
191  vec_free (mif->remote_name);
192  vec_free (mif->remote_if_name);
193  clib_fifo_free (mif->msg_queue);
194 }
195 
196 static clib_error_t *
198 {
199  memif_main_t *mm = &memif_main;
200  u16 qid = uf->private_data & 0xFFFF;
201  memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data >> 16);
202 
203  memif_log_warn (mif, "unexpected EPOLLOUT on RX for queue %u", qid);
204  return 0;
205 }
206 
207 static clib_error_t *
209 {
210  memif_main_t *mm = &memif_main;
211  vnet_main_t *vnm = vnet_get_main ();
212  u16 qid = uf->private_data & 0xFFFF;
213  memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data >> 16);
214  memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, qid);
215  u64 b;
216  ssize_t size;
217 
218  size = read (uf->file_descriptor, &b, sizeof (b));
219  if (size < 0)
220  {
221  memif_log_debug (mif, "Failed to read from socket");
222  return 0;
223  }
224 
226  mq->int_count++;
227 
228  return 0;
229 }
230 
231 
232 clib_error_t *
234 {
236  vnet_main_t *vnm = vnet_get_main ();
237  clib_file_t template = { 0 };
238  memif_region_t *mr;
239  int i;
240  clib_error_t *err = NULL;
241 
242  memif_log_debug (mif, "connect %u", mif->dev_instance);
243 
246 
247  /* *INDENT-OFF* */
248  vec_foreach (mr, mif->regions)
249  {
250  if (mr->shm)
251  continue;
252 
253  if (mr->fd < 0)
254  {
255  err = clib_error_return (0, "no memory region fd");
256  goto error;
257  }
258 
259  if ((mr->shm = mmap (NULL, mr->region_size, PROT_READ | PROT_WRITE,
260  MAP_SHARED, mr->fd, 0)) == MAP_FAILED)
261  {
262  err = clib_error_return_unix (0, "mmap");
263  goto error;
264  }
265  }
266  /* *INDENT-ON* */
267 
268  template.read_function = memif_int_fd_read_ready;
269  template.write_function = memif_int_fd_write_ready;
270 
271  /* *INDENT-OFF* */
272  vec_foreach_index (i, mif->tx_queues)
273  {
274  memif_queue_t *mq = vec_elt_at_index (mif->tx_queues, i);
275 
276  mq->ring = mif->regions[mq->region].shm + mq->offset;
277  if (mq->ring->cookie != MEMIF_COOKIE)
278  {
279  err = clib_error_return (0, "wrong cookie on tx ring %u", i);
280  goto error;
281  }
282  }
283 
284  vec_foreach_index (i, mif->rx_queues)
285  {
286  memif_queue_t *mq = vec_elt_at_index (mif->rx_queues, i);
287  u32 ti;
288  int rv;
289 
290  mq->ring = mif->regions[mq->region].shm + mq->offset;
291  if (mq->ring->cookie != MEMIF_COOKIE)
292  {
293  err = clib_error_return (0, "wrong cookie on tx ring %u", i);
294  goto error;
295  }
296 
297  if (mq->int_fd > -1)
298  {
299  template.file_descriptor = mq->int_fd;
300  template.private_data = (mif->dev_instance << 16) | (i & 0xFFFF);
301  template.description = format (0, "%U rx %u int",
303  mif->dev_instance, i);
304  memif_file_add (&mq->int_clib_file_index, &template);
305  }
308  mq->buffer_pool_index =
310  rv = vnet_hw_interface_set_rx_mode (vnm, mif->hw_if_index, i,
312  if (rv)
314  (mif, "Warning: unable to set rx mode for interface %d queue %d: "
315  "rc=%d", mif->hw_if_index, i, rv);
316  else
317  {
318  vnet_hw_if_rx_mode rxmode;
319  vnet_hw_interface_get_rx_mode (vnm, mif->hw_if_index, i, &rxmode);
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;
554  default:
555  ASSERT (0);
556  }
557 
558  last_run_duration = start_time = vlib_time_now (vm);
559  /* *INDENT-OFF* */
560  pool_foreach (mif, mm->interfaces)
561  {
563  /* Allow no more than 10us without a pause */
564  now = vlib_time_now (vm);
565  if (now > start_time + 10e-6)
566  {
567  vlib_process_suspend (vm, 100e-6); /* suspend for 100 us */
568  start_time = vlib_time_now (vm);
569  }
570 
571  if ((mif->flags & MEMIF_IF_FLAG_ADMIN_UP) == 0)
572  continue;
573 
574  if (mif->flags & MEMIF_IF_FLAG_CONNECTING)
575  continue;
576 
577  if (mif->flags & MEMIF_IF_FLAG_CONNECTED)
578  continue;
579 
580  if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
581  {
582  clib_memset (sock, 0, sizeof(clib_socket_t));
583  sock->config = (char *) msf->filename;
585 
586  if ((err = clib_socket_init (sock)))
587  {
588  clib_error_free (err);
589  }
590  else
591  {
592  clib_file_t t = { 0 };
593 
597  t.file_descriptor = sock->fd;
598  t.private_data = mif->dev_instance;
599  memif_file_add (&sock->private_data, &t);
600  t.description = format (0, "%U ctl",
602  mif->dev_instance);
603  hash_set (msf->dev_instance_by_fd, sock->fd, mif->dev_instance);
604 
605  mif->flags |= MEMIF_IF_FLAG_CONNECTING;
606  mif->sock = sock;
607  sock = clib_mem_alloc (sizeof(clib_socket_t));
608  }
609  }
610  }
611  /* *INDENT-ON* */
612  last_run_duration = vlib_time_now (vm) - last_run_duration;
613  }
614  return 0;
615 }
616 
617 /* *INDENT-OFF* */
619  .function = memif_process,
620  .type = VLIB_NODE_TYPE_PROCESS,
621  .name = "memif-process",
622 };
623 /* *INDENT-ON* */
624 
625 static int
626 memif_add_socket_file (u32 sock_id, u8 * socket_filename)
627 {
628  memif_main_t *mm = &memif_main;
629  uword *p;
630  memif_socket_file_t *msf;
631 
632  p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
633  if (p)
634  {
635  msf = pool_elt_at_index (mm->socket_files, *p);
636  if (strcmp ((char *) msf->filename, (char *) socket_filename) == 0)
637  {
638  /* Silently accept identical "add". */
639  return 0;
640  }
641 
642  /* But don't allow a direct add of a different filename. */
643  return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
644  }
645 
646  pool_get (mm->socket_files, msf);
647  clib_memset (msf, 0, sizeof (memif_socket_file_t));
648 
649  msf->filename = socket_filename;
650  msf->socket_id = sock_id;
651 
653  msf - mm->socket_files);
654 
655  return 0;
656 }
657 
658 static int
660 {
661  memif_main_t *mm = &memif_main;
662  uword *p;
663  memif_socket_file_t *msf;
664 
665  p = hash_get (mm->socket_file_index_by_sock_id, sock_id);
666  if (!p)
667  {
668  /* Don't delete non-existent entries. */
669  return VNET_API_ERROR_INVALID_ARGUMENT;
670  }
671 
672  msf = pool_elt_at_index (mm->socket_files, *p);
673  if (msf->ref_cnt > 0)
674  {
675  return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
676  }
677 
678  vec_free (msf->filename);
679  pool_put (mm->socket_files, msf);
680 
682 
683  return 0;
684 }
685 
686 int
687 memif_socket_filename_add_del (u8 is_add, u32 sock_id, u8 * sock_filename)
688 {
689  char *dir = 0, *tmp;
690  u32 idx = 0;
691 
692  /* allow adding socket id 0 */
693  if ((sock_id == 0 && is_add == 0) || sock_id == ~0)
694  {
695  return VNET_API_ERROR_INVALID_ARGUMENT;
696  }
697 
698  if (is_add == 0)
699  {
700  return memif_delete_socket_file (sock_id);
701  }
702 
703  if (sock_filename == 0 || sock_filename[0] == 0)
704  {
705  return VNET_API_ERROR_INVALID_ARGUMENT;
706  }
707 
708  if (sock_filename[0] != '/')
709  {
711 
712  /* copy runtime dir path */
714  strlen (vlib_unix_get_runtime_dir ()));
715  vec_add1 (dir, '/');
716 
717  /* if sock_filename contains dirs, add them to path */
718  tmp = strrchr ((char *) sock_filename, '/');
719  if (tmp)
720  {
721  idx = tmp - (char *) sock_filename;
722  vec_add (dir, sock_filename, idx);
723  }
724 
725  vec_add1 (dir, '\0');
726  /* create socket dir */
727  error = vlib_unix_recursive_mkdir (dir);
728  if (error)
729  {
730  clib_error_free (error);
731  return VNET_API_ERROR_SYSCALL_ERROR_1;
732  }
733 
734  sock_filename = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
735  sock_filename, 0);
736  }
737  else
738  {
739  sock_filename = vec_dup (sock_filename);
740 
741  /* check if directory exists */
742  tmp = strrchr ((char *) sock_filename, '/');
743  if (tmp)
744  {
745  idx = tmp - (char *) sock_filename;
746  vec_add (dir, sock_filename, idx);
747  vec_add1 (dir, '\0');
748  }
749 
750  /* check dir existance and access rights for effective user/group IDs */
751  if ((dir == NULL)
752  ||
753  (faccessat ( /* ignored */ -1, dir, F_OK | R_OK | W_OK, AT_EACCESS)
754  < 0))
755  {
756  vec_free (dir);
757  return VNET_API_ERROR_INVALID_ARGUMENT;
758  }
759  }
760  vec_free (dir);
761 
762  return memif_add_socket_file (sock_id, sock_filename);
763 }
764 
765 int
767 {
768  vnet_main_t *vnm = vnet_get_main ();
769  memif_main_t *mm = &memif_main;
770  memif_socket_file_t *msf =
772  clib_error_t *err;
773 
774  mif->flags |= MEMIF_IF_FLAG_DELETING;
777 
778  /* bring down the interface */
781 
782  err = clib_error_return (0, "interface deleted");
783  memif_disconnect (mif, err);
784  clib_error_free (err);
785 
786  if (mif->hw_if_index != ~0)
787  {
788  /* remove the interface */
789  if (mif->mode == MEMIF_INTERFACE_MODE_IP)
791  else
793  mif->hw_if_index = ~0;
794  }
795 
796  /* free interface data structures */
797  clib_spinlock_free (&mif->lockp);
798  mhash_unset (&msf->dev_instance_by_id, &mif->id, 0);
799 
800  /* remove socket file */
801  if (--(msf->ref_cnt) == 0)
802  {
803  if (msf->is_listener)
804  {
805  int i;
806  /* *INDENT-OFF* */
809  /* *INDENT-ON* */
810  memif_socket_close (&msf->sock);
811  vec_free (msf->pending_clients);
812  }
815  if (msf->sock)
816  {
817  err = clib_socket_close (msf->sock);
818  if (err)
819  {
820  memif_log_err (mif, "%U", format_clib_error, err);
821  clib_error_free (err);
822  }
823  clib_mem_free (msf->sock);
824  }
825  }
826 
827  clib_memset (mif, 0, sizeof (*mif));
828  pool_put (mm->interfaces, mif);
829 
830  if (pool_elts (mm->interfaces) == 0)
833 
834  return 0;
835 }
836 
837 /* *INDENT-OFF* */
838 VNET_HW_INTERFACE_CLASS (memif_ip_hw_if_class, static) =
839 {
840  .name = "memif-ip",
842 };
843 /* *INDENT-ON* */
844 
845 int
847 {
848  memif_main_t *mm = &memif_main;
850  vnet_main_t *vnm = vnet_get_main ();
851  memif_if_t *mif = 0;
853  clib_error_t *error = 0;
854  int ret = 0;
855  uword *p;
857  memif_socket_file_t *msf = 0;
858  int rv = 0;
859 
861  if (p == 0)
862  {
863  rv = VNET_API_ERROR_INVALID_ARGUMENT;
864  goto done;
865  }
866 
867  msf = vec_elt_at_index (mm->socket_files, p[0]);
868 
869  /* existing socket file can be either master or slave but cannot be both */
870  if (msf->ref_cnt > 0)
871  {
872  if ((!msf->is_listener != !args->is_master))
873  {
874  rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
875  goto done;
876  }
877 
878  p = mhash_get (&msf->dev_instance_by_id, &args->id);
879  if (p)
880  {
881  rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
882  goto done;
883  }
884  }
885 
886  /* Create new socket file */
887  if (msf->ref_cnt == 0)
888  {
889  struct stat file_stat;
890 
891  /* If we are creating listener make sure file doesn't exist or if it
892  * exists thn delete it if it is old socket file */
893  if (args->is_master && (stat ((char *) msf->filename, &file_stat) == 0))
894  {
895  if (S_ISSOCK (file_stat.st_mode))
896  {
897  unlink ((char *) msf->filename);
898  }
899  else
900  {
901  error = clib_error_return (0, "File exists for %s",
902  msf->filename);
903  rv = VNET_API_ERROR_VALUE_EXIST;
904  goto done;
905  }
906  }
907 
908  mhash_init (&msf->dev_instance_by_id, sizeof (uword),
909  sizeof (memif_interface_id_t));
910  msf->dev_instance_by_fd = hash_create (0, sizeof (uword));
911  msf->is_listener = (args->is_master != 0);
912 
913  memif_log_debug (0, "initializing socket file %s", msf->filename);
914  }
915 
916  if (mm->per_thread_data == 0)
917  {
918  int i;
919 
922 
923  for (i = 0; i < tm->n_vlib_mains; i++)
924  {
927  vlib_buffer_t *bt = &ptd->buffer_template;
928  clib_memset (bt, 0, sizeof (vlib_buffer_t));
929  bt->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
931  vnet_buffer (bt)->sw_if_index[VLIB_TX] = (u32) ~ 0;
932 
933  /* initially prealloc copy_ops so we can use
934  _vec_len instead of vec_elen */
936  vec_reset_length (ptd->copy_ops);
938  vec_reset_length (ptd->buffers);
939  }
940  }
941 
942  pool_get (mm->interfaces, mif);
943  clib_memset (mif, 0, sizeof (*mif));
944  mif->dev_instance = mif - mm->interfaces;
945  mif->socket_file_index = msf - mm->socket_files;
946  mif->id = args->id;
947  mif->sw_if_index = mif->hw_if_index = mif->per_interface_next_index = ~0;
948  mif->mode = args->mode;
949  if (args->secret)
950  mif->secret = vec_dup (args->secret);
951 
952  if (tm->n_vlib_mains > 1)
953  clib_spinlock_init (&mif->lockp);
954 
956  {
957 
958  if (!args->hw_addr_set)
959  {
960  f64 now = vlib_time_now (vm);
961  u32 rnd;
962  rnd = (u32) (now * 1e6);
963  rnd = random_u32 (&rnd);
964 
965  memcpy (args->hw_addr + 2, &rnd, sizeof (rnd));
966  args->hw_addr[0] = 2;
967  args->hw_addr[1] = 0xfe;
968  }
970  mif->dev_instance, args->hw_addr,
971  &mif->hw_if_index,
973  }
974  else if (mif->mode == MEMIF_INTERFACE_MODE_IP)
975  {
976  mif->hw_if_index =
978  mif->dev_instance,
979  memif_ip_hw_if_class.index,
980  mif->dev_instance);
981  }
982  else
983  error = clib_error_return (0, "unsupported interface mode");
984 
985  if (error)
986  {
987  ret = VNET_API_ERROR_SYSCALL_ERROR_2;
988  goto error;
989  }
990 
991  sw = vnet_get_hw_sw_interface (vnm, mif->hw_if_index);
992  mif->sw_if_index = sw->sw_if_index;
993 
994  mif->cfg.log2_ring_size = args->log2_ring_size;
995  mif->cfg.buffer_size = args->buffer_size;
996  mif->cfg.num_s2m_rings =
997  args->is_master ? args->rx_queues : args->tx_queues;
998  mif->cfg.num_m2s_rings =
999  args->is_master ? args->tx_queues : args->rx_queues;
1000 
1001  args->sw_if_index = mif->sw_if_index;
1002 
1003  /* If this is new one, start listening */
1004  if (msf->is_listener && msf->ref_cnt == 0)
1005  {
1006  struct stat file_stat;
1007  clib_socket_t *s = clib_mem_alloc (sizeof (clib_socket_t));
1008 
1009  ASSERT (msf->sock == 0);
1010  msf->sock = s;
1011 
1012  clib_memset (s, 0, sizeof (clib_socket_t));
1013  s->config = (char *) msf->filename;
1014  s->flags = CLIB_SOCKET_F_IS_SERVER |
1017 
1018  if ((error = clib_socket_init (s)))
1019  {
1020  ret = VNET_API_ERROR_SYSCALL_ERROR_4;
1021  goto error;
1022  }
1023 
1024  if (stat ((char *) msf->filename, &file_stat) == -1)
1025  {
1026  ret = VNET_API_ERROR_SYSCALL_ERROR_8;
1027  goto error;
1028  }
1029 
1030  clib_file_t template = { 0 };
1032  template.file_descriptor = msf->sock->fd;
1033  template.private_data = mif->socket_file_index;
1034  template.description = format (0, "memif listener %s", msf->filename);
1035  memif_file_add (&msf->sock->private_data, &template);
1036  }
1037 
1038  msf->ref_cnt++;
1039 
1040  if (args->is_master == 0)
1041  {
1042  mif->flags |= MEMIF_IF_FLAG_IS_SLAVE;
1043  if (args->is_zero_copy)
1044  mif->flags |= MEMIF_IF_FLAG_ZERO_COPY;
1045  }
1046 
1047  hw = vnet_get_hw_interface (vnm, mif->hw_if_index);
1050  memif_input_node.index);
1051 
1052  mhash_set (&msf->dev_instance_by_id, &mif->id, mif->dev_instance, 0);
1053 
1054  if (pool_elts (mm->interfaces) == 1)
1055  {
1058  }
1059  goto done;
1060 
1061 error:
1062  if (mif->hw_if_index != ~0)
1063  {
1064  if (mif->mode == MEMIF_INTERFACE_MODE_IP)
1066  else
1068  mif->hw_if_index = ~0;
1069  }
1070  memif_delete_if (vm, mif);
1071  if (error)
1072  {
1073  memif_log_err (mif, "%U", format_clib_error, error);
1074  clib_error_free (error);
1075  }
1076  return ret;
1077 
1078 done:
1079  return rv;
1080 }
1081 
1082 static clib_error_t *
1084 {
1085  memif_main_t *mm = &memif_main;
1086 
1087  clib_memset (mm, 0, sizeof (memif_main_t));
1088 
1089  mm->log_class = vlib_log_register_class ("memif_plugin", 0);
1090  memif_log_debug (0, "initialized");
1091 
1092  /* initialize binary API */
1094 
1095  /*
1096  * Pre-stuff socket filename pool with a non-modifieable mapping
1097  * for socket-id 0 to MEMIF_DEFAULT_SOCKET_FILENAME in the
1098  * default run-time directory.
1099  */
1101 
1102  return 0;
1103 }
1104 
1106 
1107 /* *INDENT-OFF* */
1108 VLIB_PLUGIN_REGISTER () = {
1109  .version = VPP_BUILD_VER,
1110  .description = "Packet Memory Interface (memif) -- Experimental",
1111 };
1112 /* *INDENT-ON* */
1113 
1114 /*
1115  * fd.io coding-style-patch-verification: ON
1116  *
1117  * Local Variables:
1118  * eval: (c-set-style "gnu")
1119  * End:
1120  */
memif_if_t * interfaces
Definition: private.h:241
#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:338
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:124
vlib_log_class_t log_class
Definition: private.h:250
__clib_export int clib_mem_vm_create_fd(clib_mem_page_sz_t log2_page_size, char *fmt,...)
Definition: mem.c:264
#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
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:751
#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:170
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:519
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:656
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
clib_socket_t ** pending_clients
Definition: private.h:87
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
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:527
unsigned long u64
Definition: types.h:89
memif_socket_file_t * socket_files
Definition: private.h:244
__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:183
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
#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:642
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:434
u32 file_descriptor
Definition: file.h:54
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
static clib_error_t * memif_init(vlib_main_t *vm)
Definition: memif.c:1083
vlib_buffer_main_t * buffer_main
Definition: main.h:182
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:271
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:794
vlib_main_t * vm
Definition: in2out_ed.c:1580
vlib_physmem_map_t * vlib_physmem_get_map(vlib_main_t *vm, u32 index)
Definition: physmem.c:87
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:520
u32 * buffers
Definition: private.h:125
u16 mask
Definition: flow_types.api:52
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:509
u8 num_m2s_rings
Definition: private.h:185
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
vlib_main_t ** vlib_mains
Definition: buffer.c:332
unsigned char u8
Definition: types.h:56
__clib_export clib_error_t * clib_socket_init(clib_socket_t *s)
Definition: socket.c:384
#define memif_file_del_by_index(a)
Definition: private.h:77
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)
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:668
#define CLIB_SOCKET_F_IS_SERVER
Definition: socket.h:58
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:482
#define static_always_inline
Definition: clib.h:109
u8 * remote_name
Definition: private.h:178
static int memif_add_socket_file(u32 sock_id, u8 *socket_filename)
Definition: memif.c:626
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
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:579
clib_error_t * memif_plugin_api_hookup(vlib_main_t *vm)
Definition: memif_api.c:354
uword socket_file_index
Definition: private.h:168
static char * vlib_unix_get_runtime_dir(void)
Definition: unix.h:143
uint32_t cookie
Definition: memif.h:168
u8 buffer_pool_index
Definition: private.h:126
clib_error_t * memif_init_regions_and_queues(memif_if_t *mif)
Definition: memif.c:356
static_always_inline void vnet_device_input_set_interrupt_pending(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:127
u16 buffer_size
Definition: private.h:186
description fragment has unexpected format
Definition: map.api:433
memif_log2_ring_size_t log2_ring_size
Definition: private.h:272
vnet_hw_interface_flags_t flags
Definition: interface.h:538
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:164
static int memif_delete_socket_file(u32 sock_id)
Definition: memif.c:659
#define clib_error_return(e, args...)
Definition: error.h:99
memif_region_offset_t offset
Definition: private.h:121
const cJSON *const b
Definition: cJSON.h:255
vlib_node_registration_t memif_input_node
(constructor) VLIB_REGISTER_NODE (memif_input_node)
Definition: node.c:929
struct memif_if_t::@699 run
#define memif_file_add(a, b)
Definition: private.h:66
unsigned int u32
Definition: types.h:88
void * shm
Definition: private.h:102
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:92
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.
Definition: buffer_funcs.h:984
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:123
Definition: cJSON.c:84
u8 * description
Definition: file.h:70
#define hash_get(h, key)
Definition: hash.h:249
memif_copy_op_t * copy_ops
Definition: private.h:225
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
static_always_inline uword vnet_get_device_input_thread_index(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:118
memif_desc_t desc[0]
Definition: memif.h:175
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1015
int memif_delete_if(vlib_main_t *vm, memif_if_t *mif)
Definition: memif.c:766
uword dev_instance
Definition: private.h:161
static clib_error_t * clib_socket_close(clib_socket_t *sock)
Definition: socket.h:175
clib_spinlock_t lockp
Definition: private.h:156
unsigned short u16
Definition: types.h:57
#define clib_error_return_unix(e, args...)
Definition: error.h:102
int vnet_hw_interface_set_rx_mode(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, vnet_hw_if_rx_mode mode)
Definition: devices.c:253
u32 size
Definition: vhost_user.h:106
#define hash_free(h)
Definition: hash.h:310
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:429
vlib_buffer_pool_t * buffer_pools
Definition: buffer.h:458
memif_interface_id_t id
Definition: private.h:266
int memif_create_if(vlib_main_t *vm, memif_create_if_args_t *args)
Definition: memif.c:846
uword int_clib_file_index
Definition: private.h:130
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:197
__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:175
clib_error_t * memif_connect(memif_if_t *mif)
Definition: memif.c:233
u8 slot
Definition: pci_types.api:22
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
u8 * local_disc_string
Definition: private.h:198
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
int memif_socket_filename_add_del(u8 is_add, u32 sock_id, u8 *sock_filename)
Definition: memif.c:687
uint32_t memif_interface_id_t
Definition: memif.h:66
u16 last_tail
Definition: private.h:124
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:134
memif_region_t * regions
Definition: private.h:172
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define ASSERT(truth)
void vnet_hw_interface_assign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, uword thread_index)
Definition: devices.c:139
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:1011
static clib_error_t * memif_int_fd_read_ready(clib_file_t *uf)
Definition: memif.c:208
u32 flags
Definition: private.h:157
memif_ring_t * ring
Definition: private.h:118
static void clib_mem_free(void *p)
Definition: mem.h:311
#define CLIB_SOCKET_F_IS_CLIENT
Definition: socket.h:59
vlib_buffer_t buffer_template
Definition: private.h:230
u32 hw_if_index
Definition: private.h:159
struct _socket_t clib_socket_t
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:23
vl_api_ip4_address_t hi
Definition: arp.api:37
u64 int_count
Definition: private.h:131
memif_region_offset_t offset
Definition: memif.h:155
uword * dev_instance_by_fd
Definition: private.h:95
u8 num_s2m_rings
Definition: private.h:184
__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()
Definition: defs.h:47
clib_error_t * vlib_unix_recursive_mkdir(char *path)
Definition: util.c:103
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:102
u64 uword
Definition: types.h:112
a point 2 point interface
Definition: interface.h:387
struct memif_if_t::@698 cfg
void memif_socket_close(clib_socket_t **sock)
Definition: socket.c:43
#define clib_error_free(e)
Definition: error.h:86
u8 * remote_if_name
Definition: private.h:179
clib_file_function_t * error_function
Definition: file.h:67
memif_interface_id_t id
Definition: private.h:158
memif_log2_ring_size_t log2_ring_size
Definition: private.h:119
int vnet_hw_interface_unassign_rx_thread(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.c:188
#define vnet_buffer(b)
Definition: buffer.h:417
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:32
memif_per_thread_data_t * per_thread_data
Definition: private.h:248
static vlib_node_registration_t memif_process_node
(constructor) VLIB_REGISTER_NODE (memif_process_node)
Definition: memif.c:618
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:199
memif_ring_type_t
Definition: memif.h:49
#define vec_foreach(var, vec)
Vector iterator.
volatile uint16_t head
Definition: memif.h:171
Definition: file.h:51
clib_socket_t * sock
Definition: private.h:167
memif_queue_t * rx_queues
Definition: private.h:174
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:245
#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:167
#define CLIB_SOCKET_F_ALLOW_GROUP_WRITE
Definition: socket.h:62
memif_msg_fifo_elt_t * msg_queue
Definition: private.h:169
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:199
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:120
clib_socket_t * sock
Definition: private.h:86
#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:160
static void vnet_hw_interface_set_input_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: devices.h:79
volatile uint16_t tail
Definition: memif.h:173
memif_interface_mode_t mode
Definition: private.h:162
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:103
int vnet_hw_interface_get_rx_mode(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, vnet_hw_if_rx_mode *mode)
Definition: devices.c:313
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127