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