FD.io VPP  v19.04-6-g6f05f72
Vector Packet Processing
virtio.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 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <net/if.h>
22 #include <linux/if_tun.h>
23 #include <sys/ioctl.h>
24 #include <linux/virtio_net.h>
25 #include <linux/vhost.h>
26 #include <sys/eventfd.h>
27 
28 #include <vlib/vlib.h>
29 #include <vlib/pci/pci.h>
30 #include <vlib/unix/unix.h>
31 #include <vnet/ethernet/ethernet.h>
32 #include <vnet/ip/ip4_packet.h>
33 #include <vnet/ip/ip6_packet.h>
36 
38 
39 #define _IOCTL(fd,a,...) \
40  if (ioctl (fd, a, __VA_ARGS__) < 0) \
41  { \
42  err = clib_error_return_unix (0, "ioctl(" #a ")"); \
43  goto error; \
44  }
45 
46 static clib_error_t *
48 {
50  vnet_main_t *vnm = vnet_get_main ();
51  u16 qid = uf->private_data & 0xFFFF;
52  virtio_if_t *vif =
53  vec_elt_at_index (nm->interfaces, uf->private_data >> 16);
54  u64 b;
55 
56  CLIB_UNUSED (ssize_t size) = read (uf->file_descriptor, &b, sizeof (b));
57  if ((qid & 1) == 0)
59 
60  return 0;
61 }
62 
63 
66 {
67  clib_error_t *err = 0;
68  virtio_vring_t *vring;
69  struct vhost_vring_state state = { 0 };
70  struct vhost_vring_addr addr = { 0 };
71  struct vhost_vring_file file = { 0 };
72  clib_file_t t = { 0 };
73  int i;
74 
75  if (!is_pow2 (sz))
76  return clib_error_return (0, "ring size must be power of 2");
77 
78  if (sz > 32768)
79  return clib_error_return (0, "ring size must be 32768 or lower");
80 
81  if (sz == 0)
82  sz = 256;
83 
84  if (idx % 2)
85  {
88  vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
89  }
90  else
91  {
94  vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
95  }
96  i = sizeof (struct vring_desc) * sz;
99  clib_memset (vring->desc, 0, i);
100 
101  i = sizeof (struct vring_avail) + sz * sizeof (vring->avail->ring[0]);
104  clib_memset (vring->avail, 0, i);
105  // tell kernel that we don't need interrupt
106  vring->avail->flags = VIRTIO_RING_FLAG_MASK_INT;
107 
108  i = sizeof (struct vring_used) + sz * sizeof (struct vring_used_elem);
111  clib_memset (vring->used, 0, i);
112 
113  vring->queue_id = idx;
114  ASSERT (vring->buffers == 0);
116  ASSERT (vring->indirect_buffers == 0);
118  if (idx % 2)
119  {
120  u32 n_alloc = 0;
121  do
122  {
123  if (n_alloc < sz)
124  n_alloc +=
125  vlib_buffer_alloc (vm, vring->indirect_buffers + n_alloc,
126  sz - n_alloc);
127  }
128  while (n_alloc != sz);
129  }
130 
131  vring->size = sz;
132  vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
133  vring->kick_fd = eventfd (0, EFD_CLOEXEC);
134 
136  t.file_descriptor = vring->call_fd;
137  t.private_data = vif->dev_instance << 16 | idx;
138  t.description = format (0, "%U vring %u", format_virtio_device_name,
139  vif->dev_instance, idx);
140  vring->call_file_index = clib_file_add (&file_main, &t);
141 
142  state.index = idx;
143  state.num = sz;
144  _IOCTL (vif->fd, VHOST_SET_VRING_NUM, &state);
145 
146  addr.index = idx;
147  addr.flags = 0;
148  addr.desc_user_addr = pointer_to_uword (vring->desc);
149  addr.avail_user_addr = pointer_to_uword (vring->avail);
150  addr.used_user_addr = pointer_to_uword (vring->used);
151  _IOCTL (vif->fd, VHOST_SET_VRING_ADDR, &addr);
152 
153  file.index = idx;
154  file.fd = vring->kick_fd;
155  _IOCTL (vif->fd, VHOST_SET_VRING_KICK, &file);
156  file.fd = vring->call_fd;
157  _IOCTL (vif->fd, VHOST_SET_VRING_CALL, &file);
158  file.fd = vif->tap_fd;
159  _IOCTL (vif->fd, VHOST_NET_SET_BACKEND, &file);
160 
161 error:
162  return err;
163 }
164 
165 inline void
167 {
168  u16 used = vring->desc_in_use;
169  u16 last = vring->last_used_idx;
170  u16 mask = vring->size - 1;
171 
172  while (used)
173  {
174  vlib_buffer_free (vm, &vring->buffers[last & mask], 1);
175  last++;
176  used--;
177  }
178 }
179 
180 clib_error_t *
182 {
183  virtio_vring_t *vring =
185 
187  close (vring->kick_fd);
188  close (vring->call_fd);
189  if (vring->used)
190  {
191  virtio_free_rx_buffers (vm, vring);
192  clib_mem_free (vring->used);
193  }
194  if (vring->desc)
195  clib_mem_free (vring->desc);
196  if (vring->avail)
197  clib_mem_free (vring->avail);
198  vec_free (vring->buffers);
199  vec_free (vring->indirect_buffers);
200  return 0;
201 }
202 
203 clib_error_t *
205 {
206  virtio_vring_t *vring =
208 
210  close (vring->kick_fd);
211  close (vring->call_fd);
212  if (vring->used)
213  {
214  virtio_free_used_desc (vm, vring);
215  clib_mem_free (vring->used);
216  }
217  if (vring->desc)
218  clib_mem_free (vring->desc);
219  if (vring->avail)
220  clib_mem_free (vring->avail);
221  vlib_buffer_free_no_next (vm, vring->indirect_buffers, vring->size);
222  vec_free (vring->buffers);
223  vec_free (vring->indirect_buffers);
224  return 0;
225 }
226 
227 void
229 {
230  vnet_main_t *vnm = vnet_get_main ();
231  u32 thread_index;
232  virtio_vring_t *vring =
234  thread_index =
236  RX_QUEUE_ACCESS (idx));
237  vring->buffer_pool_index =
239  vlib_mains
240  [thread_index]->numa_node);
241 }
242 
243 inline void
245 {
246  if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) ||
247  vif->features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1))
248  vif->virtio_net_hdr_sz = sizeof (struct virtio_net_hdr_v1);
249  else
250  vif->virtio_net_hdr_sz = sizeof (struct virtio_net_hdr);
251 }
252 
253 inline void
254 virtio_show (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr, u32 type)
255 {
256  u32 i, j, hw_if_index;
257  virtio_if_t *vif;
258  vnet_main_t *vnm = &vnet_main;
259  virtio_main_t *mm = &virtio_main;
260  virtio_vring_t *vring;
261  struct feat_struct
262  {
263  u8 bit;
264  char *str;
265  };
266  struct feat_struct *feat_entry;
267 
268  static struct feat_struct feat_array[] = {
269 #define _(s,b) { .str = #s, .bit = b, },
271 #undef _
272  {.str = NULL}
273  };
274 
275  struct feat_struct *flag_entry;
276  static struct feat_struct flags_array[] = {
277 #define _(b,e,s) { .bit = b, .str = s, },
279 #undef _
280  {.str = NULL}
281  };
282 
283  if (!hw_if_indices)
284  return;
285 
286  for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
287  {
289  vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
290  vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
291  if (vif->type != type)
292  continue;
293  vlib_cli_output (vm, "Interface: %U (ifindex %d)",
295  hw_if_indices[hw_if_index], vif->hw_if_index);
296  if (type == VIRTIO_IF_TYPE_PCI)
297  {
298  vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
299  &vif->pci_addr);
300  }
301  if (type == VIRTIO_IF_TYPE_TAP)
302  {
303  if (vif->host_if_name)
304  vlib_cli_output (vm, " name \"%s\"", vif->host_if_name);
305  if (vif->net_ns)
306  vlib_cli_output (vm, " host-ns \"%s\"", vif->net_ns);
307  vlib_cli_output (vm, " fd %d", vif->fd);
308  vlib_cli_output (vm, " tap-fd %d", vif->tap_fd);
309  vlib_cli_output (vm, " gso-enabled %d", vif->gso_enabled);
310  }
311  vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
312  vif->mac_addr);
313  vlib_cli_output (vm, " Device instance: %u", vif->dev_instance);
314  vlib_cli_output (vm, " flags 0x%x", vif->flags);
315  flag_entry = (struct feat_struct *) &flags_array;
316  while (flag_entry->str)
317  {
318  if (vif->flags & (1ULL << flag_entry->bit))
319  vlib_cli_output (vm, " %s (%d)", flag_entry->str,
320  flag_entry->bit);
321  flag_entry++;
322  }
323  if (type == VIRTIO_IF_TYPE_PCI)
324  {
325  device_status (vm, vif);
326  }
327  vlib_cli_output (vm, " features 0x%lx", vif->features);
328  feat_entry = (struct feat_struct *) &feat_array;
329  while (feat_entry->str)
330  {
331  if (vif->features & (1ULL << feat_entry->bit))
332  vlib_cli_output (vm, " %s (%d)", feat_entry->str,
333  feat_entry->bit);
334  feat_entry++;
335  }
336  vlib_cli_output (vm, " remote-features 0x%lx", vif->remote_features);
337  feat_entry = (struct feat_struct *) &feat_array;
338  while (feat_entry->str)
339  {
340  if (vif->remote_features & (1ULL << feat_entry->bit))
341  vlib_cli_output (vm, " %s (%d)", feat_entry->str,
342  feat_entry->bit);
343  feat_entry++;
344  }
345  vlib_cli_output (vm, " Number of RX Virtqueue %u", vif->num_rxqs);
346  vlib_cli_output (vm, " Number of TX Virtqueue %u", vif->num_txqs);
347  if (vif->cxq_vring != NULL
348  && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
349  vlib_cli_output (vm, " Number of CTRL Virtqueue 1");
350  vec_foreach_index (i, vif->rxq_vrings)
351  {
352  vring = vec_elt_at_index (vif->rxq_vrings, i);
353  vlib_cli_output (vm, " Virtqueue (RX) %d", vring->queue_id);
354  vlib_cli_output (vm,
355  " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
356  vring->size, vring->last_used_idx, vring->desc_next,
357  vring->desc_in_use);
358  vlib_cli_output (vm,
359  " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
360  vring->avail->flags, vring->avail->idx,
361  vring->used->flags, vring->used->idx);
362  if (type == VIRTIO_IF_TYPE_TAP)
363  {
364  vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
365  vring->call_fd);
366  }
367  if (show_descr)
368  {
369  vlib_cli_output (vm, "\n descriptor table:\n");
370  vlib_cli_output (vm,
371  " id addr len flags next user_addr\n");
372  vlib_cli_output (vm,
373  " ===== ================== ===== ====== ===== ==================\n");
374  for (j = 0; j < vring->size; j++)
375  {
376  struct vring_desc *desc = &vring->desc[j];
377  vlib_cli_output (vm,
378  " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
379  j, desc->addr,
380  desc->len,
381  desc->flags, desc->next, desc->addr);
382  }
383  }
384  }
385  vec_foreach_index (i, vif->txq_vrings)
386  {
387  vring = vec_elt_at_index (vif->txq_vrings, i);
388  vlib_cli_output (vm, " Virtqueue (TX) %d", vring->queue_id);
389  vlib_cli_output (vm,
390  " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
391  vring->size, vring->last_used_idx, vring->desc_next,
392  vring->desc_in_use);
393  vlib_cli_output (vm,
394  " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
395  vring->avail->flags, vring->avail->idx,
396  vring->used->flags, vring->used->idx);
397  if (type == VIRTIO_IF_TYPE_TAP)
398  {
399  vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
400  vring->call_fd);
401  }
402  if (show_descr)
403  {
404  vlib_cli_output (vm, "\n descriptor table:\n");
405  vlib_cli_output (vm,
406  " id addr len flags next user_addr\n");
407  vlib_cli_output (vm,
408  " ===== ================== ===== ====== ===== ==================\n");
409  for (j = 0; j < vring->size; j++)
410  {
411  struct vring_desc *desc = &vring->desc[j];
412  vlib_cli_output (vm,
413  " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
414  j, desc->addr,
415  desc->len,
416  desc->flags, desc->next, desc->addr);
417  }
418  }
419  }
420  if (vif->cxq_vring != NULL
421  && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
422  {
423  vring = vif->cxq_vring;
424  vlib_cli_output (vm, " Virtqueue (CTRL) %d", vring->queue_id);
425  vlib_cli_output (vm,
426  " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
427  vring->size, vring->last_used_idx,
428  vring->desc_next, vring->desc_in_use);
429  vlib_cli_output (vm,
430  " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
431  vring->avail->flags, vring->avail->idx,
432  vring->used->flags, vring->used->idx);
433  if (type == VIRTIO_IF_TYPE_TAP)
434  {
435  vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
436  vring->call_fd);
437  }
438  if (show_descr)
439  {
440  vlib_cli_output (vm, "\n descriptor table:\n");
441  vlib_cli_output (vm,
442  " id addr len flags next user_addr\n");
443  vlib_cli_output (vm,
444  " ===== ================== ===== ====== ===== ==================\n");
445  for (j = 0; j < vring->size; j++)
446  {
447  struct vring_desc *desc = &vring->desc[j];
448  vlib_cli_output (vm,
449  " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
450  j, desc->addr,
451  desc->len,
452  desc->flags, desc->next, desc->addr);
453  }
454  }
455  }
456 
457  }
458 
459 }
460 
461 /*
462  * fd.io coding-style-patch-verification: ON
463  *
464  * Local Variables:
465  * eval: (c-set-style "gnu")
466  * End:
467  */
struct vring_used * used
Definition: virtio.h:105
vmrglw vmrglh hi
#define vec_foreach_index(var, v)
Iterate over vector indices.
format_function_t format_vnet_hw_if_index_name
void virtio_set_net_hdr_size(virtio_if_t *vif)
Definition: virtio.c:244
virtio_if_t * interfaces
Definition: virtio.h:193
#define CLIB_UNUSED(x)
Definition: clib.h:82
void virtio_show(vlib_main_t *vm, u32 *hw_if_indices, u8 show_descr, u32 type)
Definition: virtio.c:254
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:865
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
unsigned long u64
Definition: types.h:89
int gso_enabled
Definition: virtio.h:183
u32 dev_instance
Definition: virtio.h:141
#define NULL
Definition: clib.h:58
#define foreach_virtio_net_features
Definition: virtio.h:26
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 file_descriptor
Definition: file.h:54
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
int i
void virtio_vring_set_numa_node(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:228
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:450
vlib_main_t ** vlib_mains
Definition: buffer.c:321
unsigned char u8
Definition: types.h:56
clib_error_t * virtio_vring_free_tx(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:204
clib_file_function_t * read_function
Definition: file.h:67
struct vring_avail * avail
Definition: virtio.h:106
u64 features
Definition: virtio.h:165
u32 hw_if_index
Definition: virtio.h:142
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define TX_QUEUE_ACCESS(X)
Definition: virtio.h:80
void device_status(vlib_main_t *vm, virtio_if_t *vif)
Definition: pci.c:357
static_always_inline void vnet_device_input_set_interrupt_pending(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:136
void virtio_free_rx_buffers(vlib_main_t *vm, virtio_vring_t *vring)
Definition: virtio.c:166
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
clib_file_main_t file_main
Definition: main.c:63
unsigned int u32
Definition: types.h:88
u16 queue_id
Definition: virtio.h:114
u16 num_txqs
Definition: virtio.h:172
u8 * description
Definition: file.h:70
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
uword size
static_always_inline uword vnet_get_device_input_thread_index(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
Definition: devices.h:127
int tap_fd
Definition: virtio.h:160
unsigned short u16
Definition: types.h:57
pci_addr_t pci_addr
Definition: virtio.h:150
vnet_main_t vnet_main
Definition: misc.c:43
u8 buffer_pool_index
Definition: virtio.h:112
u16 desc_next
Definition: virtio.h:109
u16 virtio_net_hdr_sz
Definition: virtio.h:145
u32 * indirect_buffers
Definition: virtio.h:118
u16 num_rxqs
Definition: virtio.h:171
virtio_vring_t * rxq_vrings
Definition: virtio.h:163
format_function_t format_virtio_device_name
Definition: virtio.h:215
u16 last_used_idx
Definition: virtio.h:119
static void vlib_buffer_free_no_next(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers, does not free the buffer chain for each buffer.
Definition: buffer_funcs.h:882
vlib_main_t * vm
Definition: buffer.c:312
#define VIRTIO_RING_FLAG_MASK_INT
Definition: virtio.h:99
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
u32 call_file_index
Definition: virtio.h:116
u8 * net_ns
Definition: virtio.h:176
u8 mac_addr[6]
Definition: virtio.h:174
u32 flags
Definition: virtio.h:138
static uword round_pow2(uword x, uword pow2)
Definition: clib.h:241
virtio_if_type_t type
Definition: virtio.h:146
void virtio_free_used_desc(vlib_main_t *vm, virtio_vring_t *vring)
Definition: device.c:95
#define ASSERT(truth)
u64 remote_features
Definition: virtio.h:165
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
Definition: file.h:96
static void clib_file_del_by_index(clib_file_main_t *um, uword index)
Definition: file.h:119
#define VIRTIO_FEATURE(X)
Definition: virtio.h:76
clib_error_t * virtio_vring_init(vlib_main_t *vm, virtio_if_t *vif, u16 idx, u16 sz)
Definition: virtio.c:65
static void clib_mem_free(void *p)
Definition: mem.h:205
static uword pointer_to_uword(const void *p)
Definition: types.h:131
virtio_main_t virtio_main
Definition: virtio.c:37
static uword is_pow2(uword x)
Definition: clib.h:235
#define RX_QUEUE_ACCESS(X)
Definition: virtio.h:81
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
int fd
Definition: virtio.h:155
u32 * buffers
Definition: virtio.h:117
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:140
virtio_vring_t * cxq_vring
Definition: virtio.h:185
clib_error_t * virtio_vring_free_rx(vlib_main_t *vm, virtio_if_t *vif, u32 idx)
Definition: virtio.c:181
uword private_data
Definition: file.h:64
struct vring_desc * desc
Definition: virtio.h:104
Definition: file.h:51
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:612
static u8 vlib_buffer_pool_get_default_for_numa(vlib_main_t *vm, u32 numa_node)
Definition: buffer_funcs.h:163
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
format_function_t format_vlib_pci_addr
Definition: pci.h:324
u16 desc_in_use
Definition: virtio.h:108
virtio_vring_t * txq_vrings
Definition: virtio.h:164
static clib_error_t * call_read_ready(clib_file_t *uf)
Definition: virtio.c:47
u8 * host_if_name
Definition: virtio.h:175