virtio: virtio: implement packed queues from virtio 1.1
[vpp.git] / src / vnet / devices / virtio / virtio.h
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 #ifndef _VNET_DEVICES_VIRTIO_VIRTIO_H_
19 #define _VNET_DEVICES_VIRTIO_VIRTIO_H_
20
21 #include <vnet/devices/virtio/virtio_std.h>
22 #include <vnet/devices/virtio/vhost_std.h>
23 #include <vnet/devices/virtio/virtio_buffering.h>
24 #include <vnet/gso/gro.h>
25
26 #define foreach_virtio_if_flag          \
27   _(0, ADMIN_UP, "admin-up")            \
28   _(1, DELETING, "deleting")
29
30 typedef enum
31 {
32 #define _(a, b, c) VIRTIO_IF_FLAG_##b = (1 << a),
33   foreach_virtio_if_flag
34 #undef _
35 } virtio_if_flag_t;
36
37 #define TX_QUEUE(X) ((X*2) + 1)
38 #define RX_QUEUE(X) (X*2)
39 #define TX_QUEUE_ACCESS(X) (X/2)
40 #define RX_QUEUE_ACCESS(X) (X/2)
41
42 #define VIRTIO_NUM_RX_DESC 256
43 #define VIRTIO_NUM_TX_DESC 256
44
45 #define foreach_virtio_if_types \
46   _ (TAP, 0)                    \
47   _ (TUN, 1)                    \
48   _ (PCI, 2)
49
50 typedef enum
51 {
52 #define _(a, b) VIRTIO_IF_TYPE_##a = (1 << b),
53   foreach_virtio_if_types
54 #undef _
55     VIRTIO_IF_N_TYPES = (1 << 3),
56 } virtio_if_type_t;
57
58 #define VIRTIO_RING_FLAG_MASK_INT 1
59
60 #define VIRTIO_EVENT_START_TIMER 1
61 #define VIRTIO_EVENT_STOP_TIMER 2
62
63 typedef struct
64 {
65   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
66   clib_spinlock_t lockp;
67   union
68   {
69     struct
70     {
71       vring_desc_t *desc;
72       vring_used_t *used;
73       vring_avail_t *avail;
74     };
75     struct
76     {
77       vring_packed_desc_t *packed_desc;
78       vring_desc_event_t *driver_event;
79       vring_desc_event_t *device_event;
80     };
81   };
82   u32 *buffers;
83   u16 size;
84   u16 queue_id;
85   u16 desc_in_use;
86   u16 desc_next;
87   u16 last_used_idx;
88   u16 last_kick_avail_idx;
89   union
90   {
91     struct
92     {
93       int kick_fd;
94       int call_fd;
95       u32 call_file_index;
96     };
97     struct
98     {
99       u16 avail_wrap_counter;
100       u16 used_wrap_counter;
101       u16 queue_notify_offset;
102     };
103   };
104 #define VRING_TX_OUT_OF_ORDER 1
105   u16 flags;
106   u8 buffer_pool_index;
107   vnet_hw_if_rx_mode mode;
108   virtio_vring_buffering_t *buffering;
109   gro_flow_table_t *flow_table;
110 } virtio_vring_t;
111
112 typedef union
113 {
114   struct
115   {
116     u16 domain;
117     u8 bus;
118     u8 slot:5;
119     u8 function:3;
120   };
121   u32 as_u32;
122 } pci_addr_t;
123
124 /* forward declaration */
125 typedef struct _virtio_pci_func virtio_pci_func_t;
126
127 typedef struct
128 {
129   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
130   u64 features;
131   u32 flags;
132   u32 per_interface_next_index;
133   u16 num_rxqs;
134   u16 num_txqs;
135   virtio_vring_t *rxq_vrings;
136   virtio_vring_t *txq_vrings;
137   int gso_enabled;
138   int csum_offload_enabled;
139   union
140   {
141     int *tap_fds;
142     struct
143     {
144       u32 pci_dev_handle;
145       u32 msix_enabled;
146     };
147   };
148   u16 virtio_net_hdr_sz;
149   virtio_if_type_t type;
150
151   u32 hw_if_index;
152   u32 sw_if_index;
153
154     CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
155   int packet_coalesce;
156   int packet_buffering;
157   u32 dev_instance;
158   u32 numa_node;
159   u64 remote_features;
160
161   /* error */
162   clib_error_t *error;
163   union
164   {
165     struct
166     {
167       u32 mac_addr32;
168       u16 mac_addr16;
169     };
170     u8 mac_addr[6];
171   };
172   union
173   {
174     struct                      /* tun/tap interface */
175     {
176       ip6_address_t host_ip6_addr;
177       int *vhost_fds;
178       u8 *host_if_name;
179       u8 *net_ns;
180       u8 *host_bridge;
181       u8 host_mac_addr[6];
182       u32 id;
183       u32 host_mtu_size;
184       u32 tap_flags;
185       int ifindex;
186       ip4_address_t host_ip4_addr;
187       u8 host_ip4_prefix_len;
188       u8 host_ip6_prefix_len;
189       u8 host_carrier_up;       /* host tun/tap driver link carrier state */
190     };
191     struct                      /* native virtio */
192     {
193       void *bar;
194       virtio_vring_t *cxq_vring;
195       pci_addr_t pci_addr;
196       u32 bar_id;
197       u32 notify_off_multiplier;
198       u32 is_modern;
199       u16 common_offset;
200       u16 notify_offset;
201       u16 device_offset;
202       u16 isr_offset;
203       u16 max_queue_pairs;
204       u16 msix_table_size;
205       u8 support_int_mode;      /* support interrupt mode */
206       u8 status;
207     };
208   };
209   const virtio_pci_func_t *virtio_pci_func;
210   int is_packed;
211 } virtio_if_t;
212
213 typedef struct
214 {
215   u32 interrupt_queues_count;
216   /* logging */
217   vlib_log_class_t log_default;
218
219   virtio_if_t *interfaces;
220 } virtio_main_t;
221
222 extern virtio_main_t virtio_main;
223 extern vnet_device_class_t virtio_device_class;
224 extern vlib_node_registration_t virtio_input_node;
225 extern vlib_node_registration_t virtio_send_interrupt_node;
226
227 clib_error_t *virtio_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 idx,
228                                  u16 sz);
229 clib_error_t *virtio_vring_free_rx (vlib_main_t * vm, virtio_if_t * vif,
230                                     u32 idx);
231 clib_error_t *virtio_vring_free_tx (vlib_main_t * vm, virtio_if_t * vif,
232                                     u32 idx);
233 void virtio_vring_set_numa_node (vlib_main_t * vm, virtio_if_t * vif,
234                                  u32 idx);
235 extern void virtio_free_buffers (vlib_main_t * vm, virtio_vring_t * vring);
236 extern void virtio_set_net_hdr_size (virtio_if_t * vif);
237 extern void virtio_show (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr,
238                          u32 type);
239 extern void virtio_set_packet_coalesce (virtio_if_t * vif);
240 clib_error_t *virtio_set_packet_buffering (virtio_if_t * vif, u16 size);
241 extern void virtio_pci_legacy_notify_queue (vlib_main_t * vm,
242                                             virtio_if_t * vif, u16 queue_id,
243                                             u16 queue_notify_offset);
244 extern void virtio_pci_modern_notify_queue (vlib_main_t * vm,
245                                             virtio_if_t * vif, u16 queue_id,
246                                             u16 queue_notify_offset);
247 format_function_t format_virtio_device_name;
248 format_function_t format_virtio_log_name;
249
250 static_always_inline void
251 virtio_kick (vlib_main_t * vm, virtio_vring_t * vring, virtio_if_t * vif)
252 {
253   if (vif->type == VIRTIO_IF_TYPE_PCI)
254     {
255       if (vif->is_modern)
256         virtio_pci_modern_notify_queue (vm, vif, vring->queue_id,
257                                         vring->queue_notify_offset);
258       else
259         virtio_pci_legacy_notify_queue (vm, vif, vring->queue_id,
260                                         vring->queue_notify_offset);
261     }
262   else
263     {
264       u64 x = 1;
265       int __clib_unused r;
266
267       r = write (vring->kick_fd, &x, sizeof (x));
268       vring->last_kick_avail_idx = vring->avail->idx;
269     }
270 }
271
272 #define virtio_log_debug(vif, f, ...)                           \
273 {                                                               \
274   vlib_log(VLIB_LOG_LEVEL_DEBUG, virtio_main.log_default,       \
275            "%U: " f, format_virtio_log_name, vif,               \
276            ##__VA_ARGS__);                                      \
277 };
278
279 #define virtio_log_warning(vif, f, ...)                         \
280 {                                                               \
281   vlib_log(VLIB_LOG_LEVEL_WARNING, virtio_main.log_default,     \
282            "%U: " f, format_virtio_log_name, vif,               \
283            ##__VA_ARGS__);                                      \
284 };
285
286 #define virtio_log_error(vif, f, ...)                           \
287 {                                                               \
288   vlib_log(VLIB_LOG_LEVEL_ERR, virtio_main.log_default,         \
289            "%U: " f, format_virtio_log_name, vif,               \
290            ##__VA_ARGS__);                                      \
291 };
292
293 #endif /* _VNET_DEVICES_VIRTIO_VIRTIO_H_ */
294
295 /*
296  * fd.io coding-style-patch-verification: ON
297  *
298  * Local Variables:
299  * eval: (c-set-style "gnu")
300  * End:
301  */