Line data Source code
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 <sys/eventfd.h>
25 :
26 : #include <vlib/vlib.h>
27 : #include <vlib/pci/pci.h>
28 : #include <vlib/unix/unix.h>
29 : #include <vnet/ethernet/ethernet.h>
30 : #include <vnet/ip/ip4_packet.h>
31 : #include <vnet/ip/ip6_packet.h>
32 : #include <vnet/devices/virtio/virtio.h>
33 : #include <vnet/devices/virtio/virtio_inline.h>
34 : #include <vnet/devices/virtio/pci.h>
35 : #include <vnet/interface/rx_queue_funcs.h>
36 : #include <vnet/interface/tx_queue_funcs.h>
37 :
38 : virtio_main_t virtio_main;
39 :
40 : #define _IOCTL(fd,a,...) \
41 : if (ioctl (fd, a, __VA_ARGS__) < 0) \
42 : { \
43 : err = clib_error_return_unix (0, "ioctl(" #a ")"); \
44 : goto error; \
45 : }
46 :
47 : static clib_error_t *
48 0 : call_read_ready (clib_file_t * uf)
49 : {
50 0 : vnet_main_t *vnm = vnet_get_main ();
51 : u64 b;
52 :
53 0 : CLIB_UNUSED (ssize_t size) = read (uf->file_descriptor, &b, sizeof (b));
54 0 : vnet_hw_if_rx_queue_set_int_pending (vnm, uf->private_data);
55 :
56 0 : return 0;
57 : }
58 :
59 :
60 : clib_error_t *
61 600 : virtio_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 idx, u16 sz)
62 : {
63 : vnet_virtio_vring_t *vring;
64 : int i;
65 :
66 600 : if (!is_pow2 (sz))
67 0 : return clib_error_return (0, "ring size must be power of 2");
68 :
69 600 : if (sz > 32768)
70 0 : return clib_error_return (0, "ring size must be 32768 or lower");
71 :
72 600 : if (sz == 0)
73 0 : sz = 256;
74 :
75 600 : if (idx % 2)
76 : {
77 300 : vec_validate_aligned (vif->txq_vrings, TX_QUEUE_ACCESS (idx),
78 : CLIB_CACHE_LINE_BYTES);
79 300 : vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
80 300 : clib_spinlock_init (&vring->lockp);
81 : }
82 : else
83 : {
84 300 : vec_validate_aligned (vif->rxq_vrings, RX_QUEUE_ACCESS (idx),
85 : CLIB_CACHE_LINE_BYTES);
86 300 : vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
87 : }
88 600 : i = sizeof (vnet_virtio_vring_desc_t) * sz;
89 600 : i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
90 600 : vring->desc = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
91 600 : clib_memset (vring->desc, 0, i);
92 :
93 600 : i = sizeof (vnet_virtio_vring_avail_t) + sz * sizeof (vring->avail->ring[0]);
94 600 : i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
95 600 : vring->avail = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
96 600 : clib_memset (vring->avail, 0, i);
97 : // tell kernel that we don't need interrupt
98 600 : vring->avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
99 :
100 600 : i = sizeof (vnet_virtio_vring_used_t) +
101 600 : sz * sizeof (vnet_virtio_vring_used_elem_t);
102 600 : i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
103 600 : vring->used = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
104 600 : clib_memset (vring->used, 0, i);
105 :
106 600 : vring->queue_id = idx;
107 600 : ASSERT (vring->buffers == 0);
108 600 : vec_validate_aligned (vring->buffers, sz, CLIB_CACHE_LINE_BYTES);
109 :
110 600 : if (idx & 1)
111 : {
112 300 : clib_memset_u32 (vring->buffers, ~0, sz);
113 : // tx path: suppress the interrupts from kernel
114 300 : vring->call_fd = -1;
115 : }
116 : else
117 300 : vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
118 :
119 600 : vring->total_packets = 0;
120 600 : vring->queue_size = sz;
121 600 : vring->kick_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
122 600 : virtio_log_debug (vif, "vring %u size %u call_fd %d kick_fd %d", idx,
123 : vring->queue_size, vring->call_fd, vring->kick_fd);
124 :
125 600 : return 0;
126 : }
127 :
128 : inline void
129 600 : virtio_free_buffers (vlib_main_t *vm, vnet_virtio_vring_t *vring)
130 : {
131 600 : u16 used = vring->desc_in_use;
132 600 : u16 last = vring->last_used_idx;
133 600 : u16 mask = vring->queue_size - 1;
134 :
135 74231 : while (used)
136 : {
137 73631 : vlib_buffer_free (vm, &vring->buffers[last & mask], 1);
138 73631 : last++;
139 73631 : used--;
140 : }
141 600 : }
142 :
143 : clib_error_t *
144 300 : virtio_vring_free_rx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
145 : {
146 300 : vnet_virtio_vring_t *vring =
147 300 : vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
148 :
149 300 : clib_file_del_by_index (&file_main, vring->call_file_index);
150 300 : close (vring->kick_fd);
151 300 : close (vring->call_fd);
152 300 : if (vring->used)
153 : {
154 300 : virtio_free_buffers (vm, vring);
155 300 : clib_mem_free (vring->used);
156 : }
157 300 : if (vring->desc)
158 300 : clib_mem_free (vring->desc);
159 300 : if (vring->avail)
160 300 : clib_mem_free (vring->avail);
161 300 : vec_free (vring->buffers);
162 300 : return 0;
163 : }
164 :
165 : clib_error_t *
166 300 : virtio_vring_free_tx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
167 : {
168 300 : vnet_virtio_vring_t *vring =
169 300 : vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
170 :
171 300 : close (vring->kick_fd);
172 300 : if (vring->used)
173 : {
174 300 : virtio_free_buffers (vm, vring);
175 300 : clib_mem_free (vring->used);
176 : }
177 300 : if (vring->desc)
178 300 : clib_mem_free (vring->desc);
179 300 : if (vring->avail)
180 300 : clib_mem_free (vring->avail);
181 300 : vec_free (vring->buffers);
182 300 : gro_flow_table_free (vring->flow_table);
183 300 : virtio_vring_buffering_free (vm, vring->buffering);
184 300 : clib_spinlock_free (&vring->lockp);
185 300 : return 0;
186 : }
187 :
188 : void
189 108 : virtio_set_packet_coalesce (virtio_if_t * vif)
190 : {
191 108 : vnet_main_t *vnm = vnet_get_main ();
192 108 : vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
193 : vnet_virtio_vring_t *vring;
194 108 : vif->packet_coalesce = 1;
195 216 : vec_foreach (vring, vif->txq_vrings)
196 : {
197 108 : gro_flow_table_init (&vring->flow_table,
198 108 : vif->type & (VIRTIO_IF_TYPE_TAP |
199 : VIRTIO_IF_TYPE_PCI), hw->tx_node_index);
200 : }
201 108 : }
202 :
203 : clib_error_t *
204 0 : virtio_set_packet_buffering (virtio_if_t * vif, u16 buffering_size)
205 : {
206 0 : vnet_main_t *vnm = vnet_get_main ();
207 0 : vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
208 : vnet_virtio_vring_t *vring;
209 0 : clib_error_t *error = 0;
210 :
211 0 : vec_foreach (vring, vif->txq_vrings)
212 : {
213 0 : if ((error =
214 0 : virtio_vring_buffering_init (&vring->buffering, hw->tx_node_index,
215 : buffering_size)))
216 : {
217 0 : break;
218 : }
219 : }
220 :
221 0 : return error;
222 : }
223 :
224 : static void
225 300 : virtio_vring_fill (vlib_main_t *vm, virtio_if_t *vif,
226 : vnet_virtio_vring_t *vring)
227 : {
228 300 : if (vif->is_packed)
229 0 : virtio_refill_vring_packed (vm, vif, vif->type, vring,
230 0 : vif->virtio_net_hdr_sz,
231 : virtio_input_node.index);
232 : else
233 300 : virtio_refill_vring_split (vm, vif, vif->type, vring,
234 300 : vif->virtio_net_hdr_sz,
235 : virtio_input_node.index);
236 300 : }
237 :
238 : void
239 300 : virtio_vring_set_rx_queues (vlib_main_t *vm, virtio_if_t *vif)
240 : {
241 300 : vnet_main_t *vnm = vnet_get_main ();
242 : vnet_virtio_vring_t *vring;
243 300 : u32 i = 0;
244 :
245 300 : vnet_hw_if_set_input_node (vnm, vif->hw_if_index, virtio_input_node.index);
246 :
247 600 : vec_foreach (vring, vif->rxq_vrings)
248 : {
249 600 : vring->queue_index = vnet_hw_if_register_rx_queue (
250 300 : vnm, vif->hw_if_index, RX_QUEUE_ACCESS (vring->queue_id),
251 : VNET_HW_IF_RXQ_THREAD_ANY);
252 300 : vring->buffer_pool_index = vlib_buffer_pool_get_default_for_numa (
253 300 : vm, vnet_hw_if_get_rx_queue_numa_node (vnm, vring->queue_index));
254 300 : if (vif->type == VIRTIO_IF_TYPE_TAP || vif->type == VIRTIO_IF_TYPE_TUN)
255 300 : {
256 :
257 600 : clib_file_t f = {
258 : .read_function = call_read_ready,
259 : .flags = UNIX_FILE_EVENT_EDGE_TRIGGERED,
260 300 : .file_descriptor = vring->call_fd,
261 300 : .private_data = vring->queue_index,
262 300 : .description = format (0, "%U vring %u", format_virtio_device_name,
263 300 : vif->dev_instance, vring->queue_id),
264 : };
265 :
266 300 : vring->call_file_index = clib_file_add (&file_main, &f);
267 300 : vnet_hw_if_set_rx_queue_file_index (vnm, vring->queue_index,
268 : vring->call_file_index);
269 : }
270 0 : else if ((vif->type == VIRTIO_IF_TYPE_PCI) && (vif->support_int_mode) &&
271 0 : (vif->msix_enabled == VIRTIO_MSIX_ENABLED))
272 : {
273 : u32 file_index;
274 0 : file_index =
275 0 : vlib_pci_get_msix_file_index (vm, vif->pci_dev_handle, i + 1);
276 0 : vnet_hw_if_set_rx_queue_file_index (vnm, vring->queue_index,
277 : file_index);
278 0 : i++;
279 : }
280 300 : vnet_hw_if_set_rx_queue_mode (vnm, vring->queue_index,
281 : VNET_HW_IF_RX_MODE_POLLING);
282 300 : vring->mode = VNET_HW_IF_RX_MODE_POLLING;
283 300 : virtio_vring_fill (vm, vif, vring);
284 : }
285 300 : vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index);
286 300 : }
287 :
288 : void
289 300 : virtio_vring_set_tx_queues (vlib_main_t *vm, virtio_if_t *vif)
290 : {
291 300 : vnet_main_t *vnm = vnet_get_main ();
292 : vnet_virtio_vring_t *vring;
293 :
294 600 : vec_foreach (vring, vif->txq_vrings)
295 : {
296 300 : vring->queue_index = vnet_hw_if_register_tx_queue (
297 300 : vnm, vif->hw_if_index, TX_QUEUE_ACCESS (vring->queue_id));
298 : }
299 :
300 300 : if (vif->num_txqs == 0)
301 : {
302 0 : virtio_log_error (vif, "Interface %U has 0 txq",
303 : format_vnet_hw_if_index_name, vnm, vif->hw_if_index);
304 0 : return;
305 : }
306 :
307 600 : for (u32 j = 0; j < vlib_get_n_threads (); j++)
308 : {
309 300 : u32 qi = vif->txq_vrings[j % vif->num_txqs].queue_index;
310 300 : vnet_hw_if_tx_queue_assign_thread (vnm, qi, j);
311 : }
312 :
313 300 : vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index);
314 : }
315 :
316 : inline void
317 300 : virtio_set_net_hdr_size (virtio_if_t * vif)
318 : {
319 300 : if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) ||
320 0 : vif->features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1))
321 300 : vif->virtio_net_hdr_sz = sizeof (vnet_virtio_net_hdr_v1_t);
322 : else
323 0 : vif->virtio_net_hdr_sz = sizeof (vnet_virtio_net_hdr_t);
324 300 : }
325 :
326 : inline void
327 0 : virtio_show (vlib_main_t *vm, u32 *hw_if_indices, u8 show_descr,
328 : virtio_if_type_t type)
329 : {
330 : u32 i, j, hw_if_index;
331 : virtio_if_t *vif;
332 0 : vnet_main_t *vnm = &vnet_main;
333 0 : virtio_main_t *mm = &virtio_main;
334 : vnet_virtio_vring_t *vring;
335 : struct feat_struct
336 : {
337 : u8 bit;
338 : char *str;
339 : };
340 : struct feat_struct *feat_entry;
341 :
342 : static struct feat_struct feat_array[] = {
343 : #define _(s,b) { .str = #s, .bit = b, },
344 : foreach_virtio_net_features
345 : #undef _
346 : {.str = NULL}
347 : };
348 :
349 : struct feat_struct *flag_entry;
350 : static struct feat_struct flags_array[] = {
351 : #define _(b,e,s) { .bit = b, .str = s, },
352 : foreach_virtio_if_flag
353 : #undef _
354 : {.str = NULL}
355 : };
356 :
357 0 : if (!hw_if_indices)
358 0 : return;
359 :
360 0 : for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
361 : {
362 : vnet_hw_interface_t *hi =
363 0 : vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
364 0 : vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
365 0 : if (vif->type != type)
366 0 : continue;
367 0 : vlib_cli_output (vm, "Interface: %U (ifindex %d)",
368 : format_vnet_hw_if_index_name, vnm,
369 0 : hw_if_indices[hw_if_index], vif->hw_if_index);
370 0 : if (type == VIRTIO_IF_TYPE_PCI)
371 : {
372 0 : vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
373 : &vif->pci_addr);
374 : }
375 0 : if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
376 : {
377 0 : u8 *str = 0;
378 0 : if (vif->host_if_name)
379 0 : vlib_cli_output (vm, " name \"%s\"", vif->host_if_name);
380 0 : if (vif->net_ns)
381 0 : vlib_cli_output (vm, " host-ns \"%s\"", vif->net_ns);
382 0 : if (vif->host_mtu_size)
383 0 : vlib_cli_output (vm, " host-mtu-size \"%d\"",
384 : vif->host_mtu_size);
385 0 : if (type == VIRTIO_IF_TYPE_TAP)
386 0 : vlib_cli_output (vm, " host-mac-addr: %U",
387 0 : format_ethernet_address, vif->host_mac_addr);
388 0 : vlib_cli_output (vm, " host-carrier-up: %u", vif->host_carrier_up);
389 :
390 0 : vec_foreach_index (i, vif->vhost_fds)
391 0 : str = format (str, " %d", vif->vhost_fds[i]);
392 0 : vlib_cli_output (vm, " vhost-fds%v", str);
393 0 : vec_free (str);
394 0 : vec_foreach_index (i, vif->tap_fds)
395 0 : str = format (str, " %d", vif->tap_fds[i]);
396 0 : vlib_cli_output (vm, " tap-fds%v", str);
397 0 : vec_free (str);
398 : }
399 0 : vlib_cli_output (vm, " gso-enabled %d", vif->gso_enabled);
400 0 : vlib_cli_output (vm, " csum-enabled %d", vif->csum_offload_enabled);
401 0 : vlib_cli_output (vm, " packet-coalesce %d", vif->packet_coalesce);
402 0 : vlib_cli_output (vm, " packet-buffering %d", vif->packet_buffering);
403 0 : if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_PCI))
404 0 : vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
405 0 : vif->mac_addr);
406 0 : vlib_cli_output (vm, " Device instance: %u", vif->dev_instance);
407 0 : vlib_cli_output (vm, " flags 0x%x", vif->flags);
408 0 : flag_entry = (struct feat_struct *) &flags_array;
409 0 : while (flag_entry->str)
410 : {
411 0 : if (vif->flags & (1ULL << flag_entry->bit))
412 0 : vlib_cli_output (vm, " %s (%d)", flag_entry->str,
413 0 : flag_entry->bit);
414 0 : flag_entry++;
415 : }
416 0 : if (type == VIRTIO_IF_TYPE_PCI)
417 : {
418 0 : device_status (vm, vif);
419 : }
420 0 : vlib_cli_output (vm, " features 0x%lx", vif->features);
421 0 : feat_entry = (struct feat_struct *) &feat_array;
422 0 : while (feat_entry->str)
423 : {
424 0 : if (vif->features & (1ULL << feat_entry->bit))
425 0 : vlib_cli_output (vm, " %s (%d)", feat_entry->str,
426 0 : feat_entry->bit);
427 0 : feat_entry++;
428 : }
429 0 : vlib_cli_output (vm, " remote-features 0x%lx", vif->remote_features);
430 0 : feat_entry = (struct feat_struct *) &feat_array;
431 0 : while (feat_entry->str)
432 : {
433 0 : if (vif->remote_features & (1ULL << feat_entry->bit))
434 0 : vlib_cli_output (vm, " %s (%d)", feat_entry->str,
435 0 : feat_entry->bit);
436 0 : feat_entry++;
437 : }
438 0 : vlib_cli_output (vm, " Number of RX Virtqueue %u", vif->num_rxqs);
439 0 : vlib_cli_output (vm, " Number of TX Virtqueue %u", vif->num_txqs);
440 0 : if (type == VIRTIO_IF_TYPE_PCI && vif->cxq_vring != NULL &&
441 0 : vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
442 0 : vlib_cli_output (vm, " Number of CTRL Virtqueue 1");
443 0 : vec_foreach_index (i, vif->rxq_vrings)
444 : {
445 0 : vring = vec_elt_at_index (vif->rxq_vrings, i);
446 0 : vlib_cli_output (vm, " Virtqueue (RX) %d", vring->queue_id);
447 0 : vlib_cli_output (
448 : vm, " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
449 0 : vring->queue_size, vring->last_used_idx, vring->desc_next,
450 0 : vring->desc_in_use);
451 0 : if (vif->is_packed)
452 : {
453 0 : vlib_cli_output (vm,
454 : " driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
455 0 : vring->driver_event->flags,
456 0 : vring->driver_event->off_wrap,
457 0 : vring->device_event->flags,
458 0 : vring->device_event->off_wrap);
459 0 : vlib_cli_output (vm,
460 : " avail wrap counter %d, used wrap counter %d",
461 0 : vring->avail_wrap_counter,
462 0 : vring->used_wrap_counter);
463 : }
464 : else
465 0 : vlib_cli_output (vm,
466 : " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
467 0 : vring->avail->flags, vring->avail->idx,
468 0 : vring->used->flags, vring->used->idx);
469 0 : if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
470 : {
471 0 : vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
472 : vring->call_fd);
473 : }
474 0 : if (show_descr)
475 : {
476 0 : vlib_cli_output (vm, "\n descriptor table:\n");
477 0 : vlib_cli_output (vm,
478 : " id addr len flags next/id user_addr\n");
479 0 : vlib_cli_output (vm,
480 : " ===== ================== ===== ====== ======= ==================\n");
481 0 : for (j = 0; j < vring->queue_size; j++)
482 : {
483 0 : if (vif->is_packed)
484 : {
485 0 : vnet_virtio_vring_packed_desc_t *desc =
486 0 : &vring->packed_desc[j];
487 0 : vlib_cli_output (vm,
488 : " %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
489 : j, desc->addr,
490 : desc->len,
491 0 : desc->flags, desc->id, desc->addr);
492 : }
493 : else
494 : {
495 0 : vnet_virtio_vring_desc_t *desc = &vring->desc[j];
496 0 : vlib_cli_output (vm,
497 : " %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
498 : j, desc->addr,
499 : desc->len,
500 0 : desc->flags, desc->next, desc->addr);
501 : }
502 : }
503 : }
504 : }
505 0 : vec_foreach_index (i, vif->txq_vrings)
506 : {
507 0 : vring = vec_elt_at_index (vif->txq_vrings, i);
508 0 : vlib_cli_output (vm, " Virtqueue (TX) %d", vring->queue_id);
509 0 : vlib_cli_output (
510 : vm, " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
511 0 : vring->queue_size, vring->last_used_idx, vring->desc_next,
512 0 : vring->desc_in_use);
513 0 : if (vif->is_packed)
514 : {
515 0 : vlib_cli_output (vm,
516 : " driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
517 0 : vring->driver_event->flags,
518 0 : vring->driver_event->off_wrap,
519 0 : vring->device_event->flags,
520 0 : vring->device_event->off_wrap);
521 0 : vlib_cli_output (vm,
522 : " avail wrap counter %d, used wrap counter %d",
523 0 : vring->avail_wrap_counter,
524 0 : vring->used_wrap_counter);
525 : }
526 : else
527 0 : vlib_cli_output (vm,
528 : " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
529 0 : vring->avail->flags, vring->avail->idx,
530 0 : vring->used->flags, vring->used->idx);
531 0 : if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
532 : {
533 0 : vlib_cli_output (vm, " kickfd %d, callfd %d", vring->kick_fd,
534 : vring->call_fd);
535 : }
536 0 : if (vring->flow_table)
537 : {
538 0 : vlib_cli_output (vm, " %U", gro_flow_table_format,
539 : vring->flow_table);
540 : }
541 0 : if (vif->packet_buffering)
542 : {
543 0 : vlib_cli_output (vm, " %U", virtio_vring_buffering_format,
544 : vring->buffering);
545 : }
546 0 : if (show_descr)
547 : {
548 0 : vlib_cli_output (vm, "\n descriptor table:\n");
549 0 : vlib_cli_output (vm,
550 : " id addr len flags next/id user_addr\n");
551 0 : vlib_cli_output (vm,
552 : " ===== ================== ===== ====== ======== ==================\n");
553 0 : for (j = 0; j < vring->queue_size; j++)
554 : {
555 0 : if (vif->is_packed)
556 : {
557 0 : vnet_virtio_vring_packed_desc_t *desc =
558 0 : &vring->packed_desc[j];
559 0 : vlib_cli_output (vm,
560 : " %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
561 : j, desc->addr,
562 : desc->len,
563 0 : desc->flags, desc->id, desc->addr);
564 : }
565 : else
566 : {
567 0 : vnet_virtio_vring_desc_t *desc = &vring->desc[j];
568 0 : vlib_cli_output (vm,
569 : " %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
570 : j, desc->addr,
571 : desc->len,
572 0 : desc->flags, desc->next, desc->addr);
573 : }
574 : }
575 : }
576 : }
577 0 : if (type == VIRTIO_IF_TYPE_PCI && vif->cxq_vring != NULL &&
578 0 : vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
579 : {
580 0 : vring = vif->cxq_vring;
581 0 : vlib_cli_output (vm, " Virtqueue (CTRL) %d", vring->queue_id);
582 0 : vlib_cli_output (
583 : vm, " qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
584 0 : vring->queue_size, vring->last_used_idx, vring->desc_next,
585 0 : vring->desc_in_use);
586 0 : if (vif->is_packed)
587 : {
588 0 : vlib_cli_output (vm,
589 : " driver_event.flags 0x%x driver_event.off_wrap %d device_event.flags 0x%x device_event.off_wrap %d",
590 0 : vring->driver_event->flags,
591 0 : vring->driver_event->off_wrap,
592 0 : vring->device_event->flags,
593 0 : vring->device_event->off_wrap);
594 0 : vlib_cli_output (vm,
595 : " avail wrap counter %d, used wrap counter %d",
596 0 : vring->avail_wrap_counter,
597 0 : vring->used_wrap_counter);
598 : }
599 : else
600 : {
601 0 : vlib_cli_output (vm,
602 : " avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
603 0 : vring->avail->flags, vring->avail->idx,
604 0 : vring->used->flags, vring->used->idx);
605 : }
606 0 : if (show_descr)
607 : {
608 0 : vlib_cli_output (vm, "\n descriptor table:\n");
609 0 : vlib_cli_output (vm,
610 : " id addr len flags next/id user_addr\n");
611 0 : vlib_cli_output (vm,
612 : " ===== ================== ===== ====== ======== ==================\n");
613 0 : for (j = 0; j < vring->queue_size; j++)
614 : {
615 0 : if (vif->is_packed)
616 : {
617 0 : vnet_virtio_vring_packed_desc_t *desc =
618 0 : &vring->packed_desc[j];
619 0 : vlib_cli_output (vm,
620 : " %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
621 : j, desc->addr,
622 : desc->len,
623 0 : desc->flags, desc->id, desc->addr);
624 : }
625 : else
626 : {
627 0 : vnet_virtio_vring_desc_t *desc = &vring->desc[j];
628 0 : vlib_cli_output (vm,
629 : " %-5d 0x%016lx %-5d 0x%04x %-8d 0x%016lx\n",
630 : j, desc->addr,
631 : desc->len,
632 0 : desc->flags, desc->next, desc->addr);
633 : }
634 : }
635 : }
636 : }
637 : }
638 :
639 : }
640 :
641 : static clib_error_t *
642 559 : virtio_init (vlib_main_t * vm)
643 : {
644 559 : virtio_main_t *vim = &virtio_main;
645 559 : clib_error_t *error = 0;
646 :
647 559 : vim->log_default = vlib_log_register_class ("virtio", 0);
648 559 : vlib_log_debug (vim->log_default, "initialized");
649 :
650 559 : return error;
651 : }
652 :
653 74479 : VLIB_INIT_FUNCTION (virtio_init);
654 :
655 : /*
656 : * fd.io coding-style-patch-verification: ON
657 : *
658 : * Local Variables:
659 : * eval: (c-set-style "gnu")
660 : * End:
661 : */
|