virtio: fix the out of order descriptors in tx
[vpp.git] / src / vnet / devices / virtio / virtio.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #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>
34 #include <vnet/devices/virtio/virtio.h>
35 #include <vnet/devices/virtio/pci.h>
36
37 virtio_main_t virtio_main;
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 *
47 call_read_ready (clib_file_t * uf)
48 {
49   virtio_main_t *nm = &virtio_main;
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)
58     vnet_device_input_set_interrupt_pending (vnm, vif->hw_if_index, qid);
59
60   return 0;
61 }
62
63
64 clib_error_t *
65 virtio_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 idx, u16 sz)
66 {
67   virtio_vring_t *vring;
68   clib_file_t t = { 0 };
69   int i;
70
71   if (!is_pow2 (sz))
72     return clib_error_return (0, "ring size must be power of 2");
73
74   if (sz > 32768)
75     return clib_error_return (0, "ring size must be 32768 or lower");
76
77   if (sz == 0)
78     sz = 256;
79
80   if (idx % 2)
81     {
82       vlib_thread_main_t *thm = vlib_get_thread_main ();
83       vec_validate_aligned (vif->txq_vrings, TX_QUEUE_ACCESS (idx),
84                             CLIB_CACHE_LINE_BYTES);
85       vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
86       if (thm->n_vlib_mains > vif->num_txqs)
87         clib_spinlock_init (&vring->lockp);
88     }
89   else
90     {
91       vec_validate_aligned (vif->rxq_vrings, RX_QUEUE_ACCESS (idx),
92                             CLIB_CACHE_LINE_BYTES);
93       vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
94     }
95   i = sizeof (struct vring_desc) * sz;
96   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
97   vring->desc = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
98   clib_memset (vring->desc, 0, i);
99
100   i = sizeof (struct vring_avail) + sz * sizeof (vring->avail->ring[0]);
101   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
102   vring->avail = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
103   clib_memset (vring->avail, 0, i);
104   // tell kernel that we don't need interrupt
105   vring->avail->flags = VIRTIO_RING_FLAG_MASK_INT;
106
107   i = sizeof (struct vring_used) + sz * sizeof (struct vring_used_elem);
108   i = round_pow2 (i, CLIB_CACHE_LINE_BYTES);
109   vring->used = clib_mem_alloc_aligned (i, CLIB_CACHE_LINE_BYTES);
110   clib_memset (vring->used, 0, i);
111
112   vring->queue_id = idx;
113   ASSERT (vring->buffers == 0);
114   vec_validate_aligned (vring->buffers, sz, CLIB_CACHE_LINE_BYTES);
115
116   if (idx & 1)
117     {
118       clib_memset_u32 (vring->buffers, ~0, sz);
119     }
120
121   vring->size = sz;
122   vring->call_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
123   vring->kick_fd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
124   virtio_log_debug (vif, "vring %u size %u call_fd %d kick_fd %d", idx,
125                     vring->size, vring->call_fd, vring->kick_fd);
126
127   t.read_function = call_read_ready;
128   t.file_descriptor = vring->call_fd;
129   t.private_data = vif->dev_instance << 16 | idx;
130   t.description = format (0, "%U vring %u", format_virtio_device_name,
131                           vif->dev_instance, idx);
132   vring->call_file_index = clib_file_add (&file_main, &t);
133
134   return 0;
135 }
136
137 inline void
138 virtio_free_rx_buffers (vlib_main_t * vm, virtio_vring_t * vring)
139 {
140   u16 used = vring->desc_in_use;
141   u16 last = vring->last_used_idx;
142   u16 mask = vring->size - 1;
143
144   while (used)
145     {
146       vlib_buffer_free (vm, &vring->buffers[last & mask], 1);
147       last++;
148       used--;
149     }
150 }
151
152 clib_error_t *
153 virtio_vring_free_rx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
154 {
155   virtio_vring_t *vring =
156     vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
157
158   clib_file_del_by_index (&file_main, vring->call_file_index);
159   close (vring->kick_fd);
160   close (vring->call_fd);
161   if (vring->used)
162     {
163       virtio_free_rx_buffers (vm, vring);
164       clib_mem_free (vring->used);
165     }
166   if (vring->desc)
167     clib_mem_free (vring->desc);
168   if (vring->avail)
169     clib_mem_free (vring->avail);
170   vec_free (vring->buffers);
171   return 0;
172 }
173
174 inline void
175 virtio_free_used_desc (vlib_main_t * vm, virtio_vring_t * vring)
176 {
177   u16 used = vring->desc_in_use;
178   u16 sz = vring->size;
179   u16 mask = sz - 1;
180   u16 last = vring->last_used_idx;
181   u16 n_left = vring->used->idx - last;
182
183   if (n_left == 0)
184     return;
185
186   while (n_left)
187     {
188       struct vring_used_elem *e = &vring->used->ring[last & mask];
189       u16 slot = e->id;
190
191       vlib_buffer_free (vm, &vring->buffers[slot], 1);
192       used--;
193       last++;
194       n_left--;
195     }
196   vring->desc_in_use = used;
197   vring->last_used_idx = last;
198 }
199
200 clib_error_t *
201 virtio_vring_free_tx (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
202 {
203   virtio_vring_t *vring =
204     vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (idx));
205
206   clib_file_del_by_index (&file_main, vring->call_file_index);
207   close (vring->kick_fd);
208   close (vring->call_fd);
209   if (vring->used)
210     {
211       virtio_free_used_desc (vm, vring);
212       clib_mem_free (vring->used);
213     }
214   if (vring->desc)
215     clib_mem_free (vring->desc);
216   if (vring->avail)
217     clib_mem_free (vring->avail);
218   vec_free (vring->buffers);
219   clib_spinlock_free (&vring->lockp);
220   return 0;
221 }
222
223 void
224 virtio_vring_set_numa_node (vlib_main_t * vm, virtio_if_t * vif, u32 idx)
225 {
226   vnet_main_t *vnm = vnet_get_main ();
227   u32 thread_index;
228   virtio_vring_t *vring =
229     vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (idx));
230   thread_index =
231     vnet_get_device_input_thread_index (vnm, vif->hw_if_index,
232                                         RX_QUEUE_ACCESS (idx));
233   vring->buffer_pool_index =
234     vlib_buffer_pool_get_default_for_numa (vm,
235                                            vlib_mains
236                                            [thread_index]->numa_node);
237 }
238
239 inline void
240 virtio_set_net_hdr_size (virtio_if_t * vif)
241 {
242   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) ||
243       vif->features & VIRTIO_FEATURE (VIRTIO_F_VERSION_1))
244     vif->virtio_net_hdr_sz = sizeof (struct virtio_net_hdr_v1);
245   else
246     vif->virtio_net_hdr_sz = sizeof (struct virtio_net_hdr);
247 }
248
249 inline void
250 virtio_show (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr, u32 type)
251 {
252   u32 i, j, hw_if_index;
253   virtio_if_t *vif;
254   vnet_main_t *vnm = &vnet_main;
255   virtio_main_t *mm = &virtio_main;
256   virtio_vring_t *vring;
257   struct feat_struct
258   {
259     u8 bit;
260     char *str;
261   };
262   struct feat_struct *feat_entry;
263
264   static struct feat_struct feat_array[] = {
265 #define _(s,b) { .str = #s, .bit = b, },
266     foreach_virtio_net_features
267 #undef _
268     {.str = NULL}
269   };
270
271   struct feat_struct *flag_entry;
272   static struct feat_struct flags_array[] = {
273 #define _(b,e,s) { .bit = b, .str = s, },
274     foreach_virtio_if_flag
275 #undef _
276     {.str = NULL}
277   };
278
279   if (!hw_if_indices)
280     return;
281
282   for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
283     {
284       vnet_hw_interface_t *hi =
285         vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
286       vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
287       if (vif->type != type)
288         continue;
289       vlib_cli_output (vm, "Interface: %U (ifindex %d)",
290                        format_vnet_hw_if_index_name, vnm,
291                        hw_if_indices[hw_if_index], vif->hw_if_index);
292       if (type == VIRTIO_IF_TYPE_PCI)
293         {
294           vlib_cli_output (vm, "  PCI Address: %U", format_vlib_pci_addr,
295                            &vif->pci_addr);
296         }
297       if (type == VIRTIO_IF_TYPE_TAP)
298         {
299           u8 *str = 0;
300           if (vif->host_if_name)
301             vlib_cli_output (vm, "  name \"%s\"", vif->host_if_name);
302           if (vif->net_ns)
303             vlib_cli_output (vm, "  host-ns \"%s\"", vif->net_ns);
304           if (vif->host_mtu_size)
305             vlib_cli_output (vm, "  host-mtu-size \"%d\"",
306                              vif->host_mtu_size);
307           vlib_cli_output (vm, "  host-mac-addr: %U",
308                            format_ethernet_address, vif->host_mac_addr);
309
310           vec_foreach_index (i, vif->vhost_fds)
311             str = format (str, " %d", vif->vhost_fds[i]);
312           vlib_cli_output (vm, "  vhost-fds%v", str);
313           vec_free (str);
314           vlib_cli_output (vm, "  tap-fd %d", vif->tap_fd);
315         }
316       vlib_cli_output (vm, "  gso-enabled %d", vif->gso_enabled);
317       vlib_cli_output (vm, "  csum-enabled %d", vif->csum_offload_enabled);
318       vlib_cli_output (vm, "  Mac Address: %U", format_ethernet_address,
319                        vif->mac_addr);
320       vlib_cli_output (vm, "  Device instance: %u", vif->dev_instance);
321       vlib_cli_output (vm, "  flags 0x%x", vif->flags);
322       flag_entry = (struct feat_struct *) &flags_array;
323       while (flag_entry->str)
324         {
325           if (vif->flags & (1ULL << flag_entry->bit))
326             vlib_cli_output (vm, "    %s (%d)", flag_entry->str,
327                              flag_entry->bit);
328           flag_entry++;
329         }
330       if (type == VIRTIO_IF_TYPE_PCI)
331         {
332           device_status (vm, vif);
333         }
334       vlib_cli_output (vm, "  features 0x%lx", vif->features);
335       feat_entry = (struct feat_struct *) &feat_array;
336       while (feat_entry->str)
337         {
338           if (vif->features & (1ULL << feat_entry->bit))
339             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
340                              feat_entry->bit);
341           feat_entry++;
342         }
343       vlib_cli_output (vm, "  remote-features 0x%lx", vif->remote_features);
344       feat_entry = (struct feat_struct *) &feat_array;
345       while (feat_entry->str)
346         {
347           if (vif->remote_features & (1ULL << feat_entry->bit))
348             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
349                              feat_entry->bit);
350           feat_entry++;
351         }
352       vlib_cli_output (vm, "  Number of RX Virtqueue  %u", vif->num_rxqs);
353       vlib_cli_output (vm, "  Number of TX Virtqueue  %u", vif->num_txqs);
354       if (vif->cxq_vring != NULL
355           && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
356         vlib_cli_output (vm, "  Number of CTRL Virtqueue 1");
357       vec_foreach_index (i, vif->rxq_vrings)
358       {
359         vring = vec_elt_at_index (vif->rxq_vrings, i);
360         vlib_cli_output (vm, "  Virtqueue (RX) %d", vring->queue_id);
361         vlib_cli_output (vm,
362                          "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
363                          vring->size, vring->last_used_idx, vring->desc_next,
364                          vring->desc_in_use);
365         vlib_cli_output (vm,
366                          "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
367                          vring->avail->flags, vring->avail->idx,
368                          vring->used->flags, vring->used->idx);
369         if (type == VIRTIO_IF_TYPE_TAP)
370           {
371             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
372                              vring->call_fd);
373           }
374         if (show_descr)
375           {
376             vlib_cli_output (vm, "\n  descriptor table:\n");
377             vlib_cli_output (vm,
378                              "   id          addr         len  flags  next      user_addr\n");
379             vlib_cli_output (vm,
380                              "  ===== ================== ===== ====== ===== ==================\n");
381             for (j = 0; j < vring->size; j++)
382               {
383                 struct vring_desc *desc = &vring->desc[j];
384                 vlib_cli_output (vm,
385                                  "  %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
386                                  j, desc->addr,
387                                  desc->len,
388                                  desc->flags, desc->next, desc->addr);
389               }
390           }
391       }
392       vec_foreach_index (i, vif->txq_vrings)
393       {
394         vring = vec_elt_at_index (vif->txq_vrings, i);
395         vlib_cli_output (vm, "  Virtqueue (TX) %d", vring->queue_id);
396         vlib_cli_output (vm,
397                          "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
398                          vring->size, vring->last_used_idx, vring->desc_next,
399                          vring->desc_in_use);
400         vlib_cli_output (vm,
401                          "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
402                          vring->avail->flags, vring->avail->idx,
403                          vring->used->flags, vring->used->idx);
404         if (type == VIRTIO_IF_TYPE_TAP)
405           {
406             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
407                              vring->call_fd);
408           }
409         if (show_descr)
410           {
411             vlib_cli_output (vm, "\n  descriptor table:\n");
412             vlib_cli_output (vm,
413                              "   id          addr         len  flags  next      user_addr\n");
414             vlib_cli_output (vm,
415                              "  ===== ================== ===== ====== ===== ==================\n");
416             for (j = 0; j < vring->size; j++)
417               {
418                 struct vring_desc *desc = &vring->desc[j];
419                 vlib_cli_output (vm,
420                                  "  %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
421                                  j, desc->addr,
422                                  desc->len,
423                                  desc->flags, desc->next, desc->addr);
424               }
425           }
426       }
427       if (vif->cxq_vring != NULL
428           && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
429         {
430           vring = vif->cxq_vring;
431           vlib_cli_output (vm, "  Virtqueue (CTRL) %d", vring->queue_id);
432           vlib_cli_output (vm,
433                            "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
434                            vring->size, vring->last_used_idx,
435                            vring->desc_next, vring->desc_in_use);
436           vlib_cli_output (vm,
437                            "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
438                            vring->avail->flags, vring->avail->idx,
439                            vring->used->flags, vring->used->idx);
440           if (type == VIRTIO_IF_TYPE_TAP)
441             {
442               vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
443                                vring->call_fd);
444             }
445           if (show_descr)
446             {
447               vlib_cli_output (vm, "\n  descriptor table:\n");
448               vlib_cli_output (vm,
449                                "   id          addr         len  flags  next      user_addr\n");
450               vlib_cli_output (vm,
451                                "  ===== ================== ===== ====== ===== ==================\n");
452               for (j = 0; j < vring->size; j++)
453                 {
454                   struct vring_desc *desc = &vring->desc[j];
455                   vlib_cli_output (vm,
456                                    "  %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
457                                    j, desc->addr,
458                                    desc->len,
459                                    desc->flags, desc->next, desc->addr);
460                 }
461             }
462         }
463
464     }
465
466 }
467
468 static clib_error_t *
469 virtio_init (vlib_main_t * vm)
470 {
471   virtio_main_t *vim = &virtio_main;
472   clib_error_t *error = 0;
473
474   vim->log_default = vlib_log_register_class ("virtio", 0);
475   vlib_log_debug (vim->log_default, "initialized");
476
477   return error;
478 }
479
480 VLIB_INIT_FUNCTION (virtio_init);
481
482 /*
483  * fd.io coding-style-patch-verification: ON
484  *
485  * Local Variables:
486  * eval: (c-set-style "gnu")
487  * End:
488  */