tap: refactor existing flags
[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 | VIRTIO_IF_TYPE_TUN))
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           if (type == VIRTIO_IF_TYPE_TAP)
308             vlib_cli_output (vm, "  host-mac-addr: %U",
309                              format_ethernet_address, vif->host_mac_addr);
310
311           vec_foreach_index (i, vif->vhost_fds)
312             str = format (str, " %d", vif->vhost_fds[i]);
313           vlib_cli_output (vm, "  vhost-fds%v", str);
314           vec_free (str);
315           vec_foreach_index (i, vif->tap_fds)
316             str = format (str, " %d", vif->tap_fds[i]);
317           vlib_cli_output (vm, "  tap-fds%v", str);
318           vec_free (str);
319         }
320       vlib_cli_output (vm, "  gso-enabled %d", vif->gso_enabled);
321       vlib_cli_output (vm, "  csum-enabled %d", vif->csum_offload_enabled);
322       if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_PCI))
323         vlib_cli_output (vm, "  Mac Address: %U", format_ethernet_address,
324                          vif->mac_addr);
325       vlib_cli_output (vm, "  Device instance: %u", vif->dev_instance);
326       vlib_cli_output (vm, "  flags 0x%x", vif->flags);
327       flag_entry = (struct feat_struct *) &flags_array;
328       while (flag_entry->str)
329         {
330           if (vif->flags & (1ULL << flag_entry->bit))
331             vlib_cli_output (vm, "    %s (%d)", flag_entry->str,
332                              flag_entry->bit);
333           flag_entry++;
334         }
335       if (type == VIRTIO_IF_TYPE_PCI)
336         {
337           device_status (vm, vif);
338         }
339       vlib_cli_output (vm, "  features 0x%lx", vif->features);
340       feat_entry = (struct feat_struct *) &feat_array;
341       while (feat_entry->str)
342         {
343           if (vif->features & (1ULL << feat_entry->bit))
344             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
345                              feat_entry->bit);
346           feat_entry++;
347         }
348       vlib_cli_output (vm, "  remote-features 0x%lx", vif->remote_features);
349       feat_entry = (struct feat_struct *) &feat_array;
350       while (feat_entry->str)
351         {
352           if (vif->remote_features & (1ULL << feat_entry->bit))
353             vlib_cli_output (vm, "    %s (%d)", feat_entry->str,
354                              feat_entry->bit);
355           feat_entry++;
356         }
357       vlib_cli_output (vm, "  Number of RX Virtqueue  %u", vif->num_rxqs);
358       vlib_cli_output (vm, "  Number of TX Virtqueue  %u", vif->num_txqs);
359       if (vif->cxq_vring != NULL
360           && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
361         vlib_cli_output (vm, "  Number of CTRL Virtqueue 1");
362       vec_foreach_index (i, vif->rxq_vrings)
363       {
364         vring = vec_elt_at_index (vif->rxq_vrings, i);
365         vlib_cli_output (vm, "  Virtqueue (RX) %d", vring->queue_id);
366         vlib_cli_output (vm,
367                          "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
368                          vring->size, vring->last_used_idx, vring->desc_next,
369                          vring->desc_in_use);
370         vlib_cli_output (vm,
371                          "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
372                          vring->avail->flags, vring->avail->idx,
373                          vring->used->flags, vring->used->idx);
374         if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
375           {
376             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
377                              vring->call_fd);
378           }
379         if (show_descr)
380           {
381             vlib_cli_output (vm, "\n  descriptor table:\n");
382             vlib_cli_output (vm,
383                              "   id          addr         len  flags  next      user_addr\n");
384             vlib_cli_output (vm,
385                              "  ===== ================== ===== ====== ===== ==================\n");
386             for (j = 0; j < vring->size; j++)
387               {
388                 struct vring_desc *desc = &vring->desc[j];
389                 vlib_cli_output (vm,
390                                  "  %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
391                                  j, desc->addr,
392                                  desc->len,
393                                  desc->flags, desc->next, desc->addr);
394               }
395           }
396       }
397       vec_foreach_index (i, vif->txq_vrings)
398       {
399         vring = vec_elt_at_index (vif->txq_vrings, i);
400         vlib_cli_output (vm, "  Virtqueue (TX) %d", vring->queue_id);
401         vlib_cli_output (vm,
402                          "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
403                          vring->size, vring->last_used_idx, vring->desc_next,
404                          vring->desc_in_use);
405         vlib_cli_output (vm,
406                          "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
407                          vring->avail->flags, vring->avail->idx,
408                          vring->used->flags, vring->used->idx);
409         if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
410           {
411             vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
412                              vring->call_fd);
413           }
414         if (show_descr)
415           {
416             vlib_cli_output (vm, "\n  descriptor table:\n");
417             vlib_cli_output (vm,
418                              "   id          addr         len  flags  next      user_addr\n");
419             vlib_cli_output (vm,
420                              "  ===== ================== ===== ====== ===== ==================\n");
421             for (j = 0; j < vring->size; j++)
422               {
423                 struct vring_desc *desc = &vring->desc[j];
424                 vlib_cli_output (vm,
425                                  "  %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
426                                  j, desc->addr,
427                                  desc->len,
428                                  desc->flags, desc->next, desc->addr);
429               }
430           }
431       }
432       if (vif->cxq_vring != NULL
433           && vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
434         {
435           vring = vif->cxq_vring;
436           vlib_cli_output (vm, "  Virtqueue (CTRL) %d", vring->queue_id);
437           vlib_cli_output (vm,
438                            "    qsz %d, last_used_idx %d, desc_next %d, desc_in_use %d",
439                            vring->size, vring->last_used_idx,
440                            vring->desc_next, vring->desc_in_use);
441           vlib_cli_output (vm,
442                            "    avail.flags 0x%x avail.idx %d used.flags 0x%x used.idx %d",
443                            vring->avail->flags, vring->avail->idx,
444                            vring->used->flags, vring->used->idx);
445           if (type & (VIRTIO_IF_TYPE_TAP | VIRTIO_IF_TYPE_TUN))
446             {
447               vlib_cli_output (vm, "    kickfd %d, callfd %d", vring->kick_fd,
448                                vring->call_fd);
449             }
450           if (show_descr)
451             {
452               vlib_cli_output (vm, "\n  descriptor table:\n");
453               vlib_cli_output (vm,
454                                "   id          addr         len  flags  next      user_addr\n");
455               vlib_cli_output (vm,
456                                "  ===== ================== ===== ====== ===== ==================\n");
457               for (j = 0; j < vring->size; j++)
458                 {
459                   struct vring_desc *desc = &vring->desc[j];
460                   vlib_cli_output (vm,
461                                    "  %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
462                                    j, desc->addr,
463                                    desc->len,
464                                    desc->flags, desc->next, desc->addr);
465                 }
466             }
467         }
468
469     }
470
471 }
472
473 static clib_error_t *
474 virtio_init (vlib_main_t * vm)
475 {
476   virtio_main_t *vim = &virtio_main;
477   clib_error_t *error = 0;
478
479   vim->log_default = vlib_log_register_class ("virtio", 0);
480   vlib_log_debug (vim->log_default, "initialized");
481
482   return error;
483 }
484
485 VLIB_INIT_FUNCTION (virtio_init);
486
487 /*
488  * fd.io coding-style-patch-verification: ON
489  *
490  * Local Variables:
491  * eval: (c-set-style "gnu")
492  * End:
493  */