dbf560688b82d70eaff8e66e210cc40218c48d21
[vpp.git] / src / vnet / devices / virtio / device.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2016 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
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/ip/ip4_packet.h>
26 #include <vnet/ip/ip6_packet.h>
27 #include <vnet/devices/virtio/virtio.h>
28
29 #define foreach_virtio_tx_func_error           \
30 _(NO_FREE_SLOTS, "no free tx slots")           \
31 _(TRUNC_PACKET, "packet > buffer size -- truncated in tx ring") \
32 _(PENDING_MSGS, "pending msgs in tx ring") \
33 _(NO_TX_QUEUES, "no tx queues")
34
35 typedef enum
36 {
37 #define _(f,s) VIRTIO_TX_ERROR_##f,
38   foreach_virtio_tx_func_error
39 #undef _
40     VIRTIO_TX_N_ERROR,
41 } virtio_tx_func_error_t;
42
43 static char *virtio_tx_func_error_strings[] = {
44 #define _(n,s) s,
45   foreach_virtio_tx_func_error
46 #undef _
47 };
48
49 #ifndef CLIB_MARCH_VARIANT
50 u8 *
51 format_virtio_device_name (u8 * s, va_list * args)
52 {
53   u32 dev_instance = va_arg (*args, u32);
54   virtio_main_t *mm = &virtio_main;
55   virtio_if_t *vif = pool_elt_at_index (mm->interfaces, dev_instance);
56
57   if (vif->type == VIRTIO_IF_TYPE_TAP)
58     s = format (s, "tap%u", vif->id);
59   else if (vif->type == VIRTIO_IF_TYPE_PCI)
60     s = format (s, "virtio-%x/%x/%x/%x", vif->pci_addr.domain,
61                 vif->pci_addr.bus, vif->pci_addr.slot,
62                 vif->pci_addr.function);
63   else
64     s = format (s, "virtio-%lu", vif->dev_instance);
65
66   return s;
67 }
68 #endif /* CLIB_MARCH_VARIANT */
69
70 static u8 *
71 format_virtio_device (u8 * s, va_list * args)
72 {
73   u32 dev_instance = va_arg (*args, u32);
74   int verbose = va_arg (*args, int);
75   u32 indent = format_get_indent (s);
76
77   s = format (s, "VIRTIO interface");
78   if (verbose)
79     {
80       s = format (s, "\n%U instance %u", format_white_space, indent + 2,
81                   dev_instance);
82     }
83   return s;
84 }
85
86 static u8 *
87 format_virtio_tx_trace (u8 * s, va_list * args)
88 {
89   s = format (s, "Unimplemented...");
90   return s;
91 }
92
93 #ifndef CLIB_MARCH_VARIANT
94 inline void
95 virtio_free_used_desc (vlib_main_t * vm, virtio_vring_t * vring)
96 {
97   u16 used = vring->desc_in_use;
98   u16 sz = vring->size;
99   u16 mask = sz - 1;
100   u16 last = vring->last_used_idx;
101   u16 n_left = vring->used->idx - last;
102
103   if (n_left == 0)
104     return;
105
106   while (n_left)
107     {
108       struct vring_used_elem *e = &vring->used->ring[last & mask];
109       u16 slot = e->id;
110
111       vlib_buffer_free (vm, &vring->buffers[slot], 1);
112       used--;
113       last++;
114       n_left--;
115     }
116   vring->desc_in_use = used;
117   vring->last_used_idx = last;
118 }
119 #endif /* CLIB_MARCH_VARIANT */
120
121 static_always_inline u16
122 add_buffer_to_slot (vlib_main_t * vm, virtio_if_t * vif,
123                     virtio_vring_t * vring, u32 bi, u16 avail, u16 next,
124                     u16 mask, int do_gso)
125 {
126   u16 n_added = 0;
127   int hdr_sz = vif->virtio_net_hdr_sz;
128   struct vring_desc *d;
129   d = &vring->desc[next];
130   vlib_buffer_t *b = vlib_get_buffer (vm, bi);
131   struct virtio_net_hdr_v1 *hdr = vlib_buffer_get_current (b) - hdr_sz;
132
133   clib_memset (hdr, 0, hdr_sz);
134   if (do_gso && (b->flags & VNET_BUFFER_F_GSO))
135     {
136       if (b->flags & VNET_BUFFER_F_IS_IP4)
137         {
138           hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
139           hdr->gso_size = vnet_buffer2 (b)->gso_size;
140           hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
141           hdr->csum_start = vnet_buffer (b)->l4_hdr_offset;     // 0x22;
142           hdr->csum_offset = 0x10;
143         }
144       else
145         {
146           hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
147           hdr->gso_size = vnet_buffer2 (b)->gso_size;
148           hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
149           hdr->csum_start = vnet_buffer (b)->l4_hdr_offset;     // 0x36;
150           hdr->csum_offset = 0x10;
151         }
152     }
153
154   if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
155     {
156       d->addr =
157         ((vif->type == VIRTIO_IF_TYPE_PCI) ? vlib_buffer_get_current_pa (vm,
158                                                                          b) :
159          pointer_to_uword (vlib_buffer_get_current (b))) - hdr_sz;
160       d->len = b->current_length + hdr_sz;
161       d->flags = 0;
162     }
163   else
164     {
165       /*
166        * We are using single vlib_buffer_t for indirect descriptor(s)
167        * chain. Single descriptor is 16 bytes and vlib_buffer_t
168        * has 2048 bytes space. So maximum long chain can have 128
169        * (=2048/16) indirect descriptors.
170        * It can easily support 65535 bytes of Jumbo frames with
171        * each data buffer size of 512 bytes minimum.
172        */
173       vlib_buffer_t *indirect_desc =
174         vlib_get_buffer (vm, vring->indirect_buffers[next]);
175       indirect_desc->current_data = 0;
176
177       struct vring_desc *id =
178         (struct vring_desc *) vlib_buffer_get_current (indirect_desc);
179       u32 count = 1;
180       if (vif->type == VIRTIO_IF_TYPE_PCI)
181         {
182           d->addr = vlib_physmem_get_pa (vm, id);
183           id->addr = vlib_buffer_get_current_pa (vm, b) - hdr_sz;
184
185           /*
186            * If VIRTIO_F_ANY_LAYOUT is not negotiated, then virtio_net_hdr
187            * should be presented in separate descriptor and data will start
188            * from next descriptor.
189            */
190           if (PREDICT_TRUE
191               (vif->features & VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)))
192             id->len = b->current_length + hdr_sz;
193           else
194             {
195               id->len = hdr_sz;
196               id->flags = VRING_DESC_F_NEXT;
197               id->next = count;
198               count++;
199               id++;
200               id->addr = vlib_buffer_get_current_pa (vm, b);
201               id->len = b->current_length;
202             }
203           while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
204             {
205               id->flags = VRING_DESC_F_NEXT;
206               id->next = count;
207               count++;
208               id++;
209               b = vlib_get_buffer (vm, b->next_buffer);
210               id->addr = vlib_buffer_get_current_pa (vm, b);
211               id->len = b->current_length;
212             }
213         }
214       else                      /* VIRTIO_IF_TYPE_TAP */
215         {
216           d->addr = pointer_to_uword (id);
217           /* first buffer in chain */
218           id->addr = pointer_to_uword (vlib_buffer_get_current (b)) - hdr_sz;
219           id->len = b->current_length + hdr_sz;
220
221           while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
222             {
223               id->flags = VRING_DESC_F_NEXT;
224               id->next = count;
225               count++;
226               id++;
227               b = vlib_get_buffer (vm, b->next_buffer);
228               id->addr = pointer_to_uword (vlib_buffer_get_current (b));
229               id->len = b->current_length;
230             }
231         }
232       id->flags = 0;
233       id->next = 0;
234       d->len = count * sizeof (struct vring_desc);
235       d->flags = VRING_DESC_F_INDIRECT;
236     }
237   vring->buffers[next] = bi;
238   vring->avail->ring[avail & mask] = next;
239   n_added++;
240   return n_added;
241 }
242
243 static_always_inline uword
244 virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
245                             vlib_frame_t * frame, virtio_if_t * vif,
246                             int do_gso)
247 {
248   u8 qid = 0;
249   u16 n_left = frame->n_vectors;
250   virtio_vring_t *vring = vec_elt_at_index (vif->vrings, (qid << 1) + 1);
251   u16 used, next, avail;
252   u16 sz = vring->size;
253   u16 mask = sz - 1;
254   u32 *buffers = vlib_frame_vector_args (frame);
255
256   clib_spinlock_lock_if_init (&vif->lockp);
257
258   if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 &&
259       (vring->last_kick_avail_idx != vring->avail->idx))
260     virtio_kick (vm, vring, vif);
261
262   /* free consumed buffers */
263   virtio_free_used_desc (vm, vring);
264
265   used = vring->desc_in_use;
266   next = vring->desc_next;
267   avail = vring->avail->idx;
268
269   while (n_left && used < sz)
270     {
271       u16 n_added = 0;
272       n_added =
273         add_buffer_to_slot (vm, vif, vring, buffers[0], avail, next, mask,
274                             do_gso);
275       if (!n_added)
276         break;
277       avail += n_added;
278       next = (next + n_added) & mask;
279       used += n_added;
280       buffers++;
281       n_left--;
282     }
283
284   if (n_left != frame->n_vectors)
285     {
286       CLIB_MEMORY_STORE_BARRIER ();
287       vring->avail->idx = avail;
288       vring->desc_next = next;
289       vring->desc_in_use = used;
290       if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
291         virtio_kick (vm, vring, vif);
292     }
293
294   if (n_left)
295     {
296       vlib_error_count (vm, node->node_index, VIRTIO_TX_ERROR_NO_FREE_SLOTS,
297                         n_left);
298       vlib_buffer_free (vm, buffers, n_left);
299     }
300
301   clib_spinlock_unlock_if_init (&vif->lockp);
302
303   return frame->n_vectors - n_left;
304 }
305
306 VNET_DEVICE_CLASS_TX_FN (virtio_device_class) (vlib_main_t * vm,
307                                                vlib_node_runtime_t * node,
308                                                vlib_frame_t * frame)
309 {
310   virtio_main_t *nm = &virtio_main;
311   vnet_interface_output_runtime_t *rund = (void *) node->runtime_data;
312   virtio_if_t *vif = pool_elt_at_index (nm->interfaces, rund->dev_instance);
313
314   vnet_main_t *vnm = vnet_get_main ();
315   if (vnm->interface_main.gso_interface_count > 0)
316     return virtio_interface_tx_inline (vm, node, frame, vif, 1 /* do_gso */ );
317   else
318     return virtio_interface_tx_inline (vm, node, frame, vif,
319                                        0 /* no do_gso */ );
320 }
321
322 static void
323 virtio_set_interface_next_node (vnet_main_t * vnm, u32 hw_if_index,
324                                 u32 node_index)
325 {
326   virtio_main_t *apm = &virtio_main;
327   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
328   virtio_if_t *vif = pool_elt_at_index (apm->interfaces, hw->dev_instance);
329
330   /* Shut off redirection */
331   if (node_index == ~0)
332     {
333       vif->per_interface_next_index = node_index;
334       return;
335     }
336
337   vif->per_interface_next_index =
338     vlib_node_add_next (vlib_get_main (), virtio_input_node.index,
339                         node_index);
340 }
341
342 static void
343 virtio_clear_hw_interface_counters (u32 instance)
344 {
345   /* Nothing for now */
346 }
347
348 static clib_error_t *
349 virtio_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid,
350                                  vnet_hw_interface_rx_mode mode)
351 {
352   virtio_main_t *mm = &virtio_main;
353   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
354   virtio_if_t *vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
355   virtio_vring_t *vring = vec_elt_at_index (vif->vrings, qid);
356
357   if (vif->type == VIRTIO_IF_TYPE_PCI && !(vif->support_int_mode))
358     {
359       vring->avail->flags |= VIRTIO_RING_FLAG_MASK_INT;
360       return clib_error_return (0, "interrupt mode is not supported");
361     }
362
363   if (mode == VNET_HW_INTERFACE_RX_MODE_POLLING)
364     vring->avail->flags |= VIRTIO_RING_FLAG_MASK_INT;
365   else
366     vring->avail->flags &= ~VIRTIO_RING_FLAG_MASK_INT;
367
368   return 0;
369 }
370
371 static clib_error_t *
372 virtio_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
373 {
374   virtio_main_t *mm = &virtio_main;
375   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
376   virtio_if_t *vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
377
378   if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
379     vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
380   else
381     vif->flags &= ~VIRTIO_IF_FLAG_ADMIN_UP;
382
383   return 0;
384 }
385
386 static clib_error_t *
387 virtio_subif_add_del_function (vnet_main_t * vnm,
388                                u32 hw_if_index,
389                                struct vnet_sw_interface_t *st, int is_add)
390 {
391   /* Nothing for now */
392   return 0;
393 }
394
395 /* *INDENT-OFF* */
396 VNET_DEVICE_CLASS (virtio_device_class) = {
397   .name = "virtio",
398   .format_device_name = format_virtio_device_name,
399   .format_device = format_virtio_device,
400   .format_tx_trace = format_virtio_tx_trace,
401   .tx_function_n_errors = VIRTIO_TX_N_ERROR,
402   .tx_function_error_strings = virtio_tx_func_error_strings,
403   .rx_redirect_to_node = virtio_set_interface_next_node,
404   .clear_counters = virtio_clear_hw_interface_counters,
405   .admin_up_down_function = virtio_interface_admin_up_down,
406   .subif_add_del_function = virtio_subif_add_del_function,
407   .rx_mode_change_function = virtio_interface_rx_mode_change,
408 };
409 /* *INDENT-ON* */
410
411 /*
412  * fd.io coding-style-patch-verification: ON
413  *
414  * Local Variables:
415  * eval: (c-set-style "gnu")
416  * End:
417  */