xref: /kvmtool/virtio/net.c (revision bb1a32f12288de2afe07aec7af4a6e1cb99bf1e1)
1 #include "kvm/virtio-net.h"
2 #include "kvm/virtio-pci-dev.h"
3 #include "kvm/virtio.h"
4 #include "kvm/ioport.h"
5 #include "kvm/types.h"
6 #include "kvm/mutex.h"
7 #include "kvm/util.h"
8 #include "kvm/kvm.h"
9 #include "kvm/pci.h"
10 #include "kvm/irq.h"
11 #include "kvm/ioeventfd.h"
12 
13 #include <linux/virtio_net.h>
14 #include <linux/if_tun.h>
15 
16 #include <arpa/inet.h>
17 #include <net/if.h>
18 
19 #include <unistd.h>
20 #include <assert.h>
21 #include <fcntl.h>
22 
23 #include <sys/socket.h>
24 #include <sys/ioctl.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 
28 #define VIRTIO_NET_QUEUE_SIZE		128
29 #define VIRTIO_NET_NUM_QUEUES		2
30 #define VIRTIO_NET_RX_QUEUE		0
31 #define VIRTIO_NET_TX_QUEUE		1
32 
33 static struct pci_device_header pci_header = {
34 	.vendor_id			= PCI_VENDOR_ID_REDHAT_QUMRANET,
35 	.device_id			= PCI_DEVICE_ID_VIRTIO_NET,
36 	.header_type			= PCI_HEADER_TYPE_NORMAL,
37 	.revision_id			= 0,
38 	.class				= 0x020000,
39 	.subsys_vendor_id		= PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
40 	.subsys_id			= VIRTIO_ID_NET,
41 };
42 
43 struct net_device {
44 	pthread_mutex_t			mutex;
45 
46 	struct virt_queue		vqs[VIRTIO_NET_NUM_QUEUES];
47 	struct virtio_net_config	config;
48 	u32				host_features;
49 	u32				guest_features;
50 	u16				config_vector;
51 	u8				status;
52 	u8				isr;
53 	u16				queue_selector;
54 	u16				base_addr;
55 
56 	pthread_t			io_rx_thread;
57 	pthread_mutex_t			io_rx_lock;
58 	pthread_cond_t			io_rx_cond;
59 
60 	pthread_t			io_tx_thread;
61 	pthread_mutex_t			io_tx_lock;
62 	pthread_cond_t			io_tx_cond;
63 
64 	int				tap_fd;
65 	char				tap_name[IFNAMSIZ];
66 
67 	int				mode;
68 
69 };
70 
71 static struct net_device ndev = {
72 	.mutex				= PTHREAD_MUTEX_INITIALIZER,
73 
74 	.config = {
75 		.mac			= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
76 		.status			= VIRTIO_NET_S_LINK_UP,
77 	},
78 	.host_features			= 1UL << VIRTIO_NET_F_MAC
79 					| 1UL << VIRTIO_NET_F_CSUM
80 					| 1UL << VIRTIO_NET_F_HOST_UFO
81 					| 1UL << VIRTIO_NET_F_HOST_TSO4
82 					| 1UL << VIRTIO_NET_F_HOST_TSO6
83 					| 1UL << VIRTIO_NET_F_GUEST_UFO
84 					| 1UL << VIRTIO_NET_F_GUEST_TSO4
85 					| 1UL << VIRTIO_NET_F_GUEST_TSO6,
86 };
87 
88 static void *virtio_net_rx_thread(void *p)
89 {
90 	struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
91 	struct virt_queue *vq;
92 	struct kvm *kvm;
93 	u16 out, in;
94 	u16 head;
95 	int len;
96 
97 	kvm	= p;
98 	vq	= &ndev.vqs[VIRTIO_NET_RX_QUEUE];
99 
100 	while (1) {
101 		mutex_lock(&ndev.io_rx_lock);
102 		if (!virt_queue__available(vq))
103 			pthread_cond_wait(&ndev.io_rx_cond, &ndev.io_rx_lock);
104 		mutex_unlock(&ndev.io_rx_lock);
105 
106 		while (virt_queue__available(vq)) {
107 			head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
108 			len  = readv(ndev.tap_fd, iov, in);
109 			virt_queue__set_used_elem(vq, head, len);
110 
111 			/* We should interrupt guest right now, otherwise latency is huge. */
112 			virt_queue__trigger_irq(vq, pci_header.irq_line, &ndev.isr, kvm);
113 		}
114 
115 	}
116 
117 	pthread_exit(NULL);
118 	return NULL;
119 
120 }
121 
122 static void *virtio_net_tx_thread(void *p)
123 {
124 	struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
125 	struct virt_queue *vq;
126 	struct kvm *kvm;
127 	u16 out, in;
128 	u16 head;
129 	int len;
130 
131 	kvm	= p;
132 	vq	= &ndev.vqs[VIRTIO_NET_TX_QUEUE];
133 
134 	while (1) {
135 		mutex_lock(&ndev.io_tx_lock);
136 		if (!virt_queue__available(vq))
137 			pthread_cond_wait(&ndev.io_tx_cond, &ndev.io_tx_lock);
138 		mutex_unlock(&ndev.io_tx_lock);
139 
140 		while (virt_queue__available(vq)) {
141 			head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
142 			len  = writev(ndev.tap_fd, iov, out);
143 			virt_queue__set_used_elem(vq, head, len);
144 		}
145 
146 		virt_queue__trigger_irq(vq, pci_header.irq_line, &ndev.isr, kvm);
147 
148 	}
149 
150 	pthread_exit(NULL);
151 
152 	return NULL;
153 
154 }
155 
156 static bool virtio_net_pci_io_device_specific_in(void *data, unsigned long offset, int size, u32 count)
157 {
158 	u8 *config_space = (u8 *)&ndev.config;
159 
160 	if (size != 1 || count != 1)
161 		return false;
162 
163 	if ((offset - VIRTIO_MSI_CONFIG_VECTOR) > sizeof(struct virtio_net_config))
164 		pr_error("config offset is too big: %li", offset - VIRTIO_MSI_CONFIG_VECTOR);
165 
166 	ioport__write8(data, config_space[offset - VIRTIO_MSI_CONFIG_VECTOR]);
167 
168 	return true;
169 }
170 
171 static bool virtio_net_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
172 {
173 	unsigned long	offset	= port - ndev.base_addr;
174 	bool		ret	= true;
175 
176 	mutex_lock(&ndev.mutex);
177 
178 	switch (offset) {
179 	case VIRTIO_PCI_HOST_FEATURES:
180 		ioport__write32(data, ndev.host_features);
181 		break;
182 	case VIRTIO_PCI_GUEST_FEATURES:
183 		ret = false;
184 		break;
185 	case VIRTIO_PCI_QUEUE_PFN:
186 		ioport__write32(data, ndev.vqs[ndev.queue_selector].pfn);
187 		break;
188 	case VIRTIO_PCI_QUEUE_NUM:
189 		ioport__write16(data, VIRTIO_NET_QUEUE_SIZE);
190 		break;
191 	case VIRTIO_PCI_QUEUE_SEL:
192 	case VIRTIO_PCI_QUEUE_NOTIFY:
193 		ret = false;
194 		break;
195 	case VIRTIO_PCI_STATUS:
196 		ioport__write8(data, ndev.status);
197 		break;
198 	case VIRTIO_PCI_ISR:
199 		ioport__write8(data, ndev.isr);
200 		kvm__irq_line(kvm, pci_header.irq_line, VIRTIO_IRQ_LOW);
201 		ndev.isr = VIRTIO_IRQ_LOW;
202 		break;
203 	case VIRTIO_MSI_CONFIG_VECTOR:
204 		ioport__write16(data, ndev.config_vector);
205 		break;
206 	default:
207 		ret = virtio_net_pci_io_device_specific_in(data, offset, size, count);
208 	};
209 
210 	mutex_unlock(&ndev.mutex);
211 
212 	return ret;
213 }
214 
215 static void virtio_net_handle_callback(struct kvm *kvm, u16 queue_index)
216 {
217 	switch (queue_index) {
218 	case VIRTIO_NET_TX_QUEUE: {
219 		mutex_lock(&ndev.io_tx_lock);
220 		pthread_cond_signal(&ndev.io_tx_cond);
221 		mutex_unlock(&ndev.io_tx_lock);
222 		break;
223 	}
224 	case VIRTIO_NET_RX_QUEUE: {
225 		mutex_lock(&ndev.io_rx_lock);
226 		pthread_cond_signal(&ndev.io_rx_cond);
227 		mutex_unlock(&ndev.io_rx_lock);
228 		break;
229 	}
230 	default:
231 		pr_warning("Unknown queue index %u", queue_index);
232 	}
233 }
234 
235 static bool virtio_net_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
236 {
237 	unsigned long	offset		= port - ndev.base_addr;
238 	bool		ret		= true;
239 
240 	mutex_lock(&ndev.mutex);
241 
242 	switch (offset) {
243 	case VIRTIO_PCI_GUEST_FEATURES:
244 		ndev.guest_features	= ioport__read32(data);
245 		break;
246 	case VIRTIO_PCI_QUEUE_PFN: {
247 		struct virt_queue *queue;
248 		void *p;
249 
250 		assert(ndev.queue_selector < VIRTIO_NET_NUM_QUEUES);
251 
252 		queue			= &ndev.vqs[ndev.queue_selector];
253 		queue->pfn		= ioport__read32(data);
254 		p			= guest_pfn_to_host(kvm, queue->pfn);
255 
256 		vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
257 
258 		break;
259 	}
260 	case VIRTIO_PCI_QUEUE_SEL:
261 		ndev.queue_selector	= ioport__read16(data);
262 		break;
263 	case VIRTIO_PCI_QUEUE_NOTIFY: {
264 		u16 queue_index;
265 
266 		queue_index		= ioport__read16(data);
267 		virtio_net_handle_callback(kvm, queue_index);
268 		break;
269 	}
270 	case VIRTIO_PCI_STATUS:
271 		ndev.status		= ioport__read8(data);
272 		break;
273 	case VIRTIO_MSI_CONFIG_VECTOR:
274 		ndev.config_vector	= VIRTIO_MSI_NO_VECTOR;
275 		break;
276 	case VIRTIO_MSI_QUEUE_VECTOR:
277 		break;
278 	default:
279 		ret			= false;
280 	};
281 
282 	mutex_unlock(&ndev.mutex);
283 
284 	return ret;
285 }
286 
287 static void ioevent_callback(struct kvm *kvm, void *param)
288 {
289 	virtio_net_handle_callback(kvm, (u64)(long)param);
290 }
291 
292 static struct ioport_operations virtio_net_io_ops = {
293 	.io_in	= virtio_net_pci_io_in,
294 	.io_out	= virtio_net_pci_io_out,
295 };
296 
297 static bool virtio_net__tap_init(const struct virtio_net_parameters *params)
298 {
299 	int sock = socket(AF_INET, SOCK_STREAM, 0);
300 	int i, pid, status, offload, hdr_len;
301 	struct sockaddr_in sin = {0};
302 	struct ifreq ifr;
303 
304 	for (i = 0 ; i < 6 ; i++)
305 		ndev.config.mac[i] = params->guest_mac[i];
306 
307 	ndev.tap_fd = open("/dev/net/tun", O_RDWR);
308 	if (ndev.tap_fd < 0) {
309 		pr_warning("Unable to open /dev/net/tun");
310 		goto fail;
311 	}
312 
313 	memset(&ifr, 0, sizeof(ifr));
314 	ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
315 	if (ioctl(ndev.tap_fd, TUNSETIFF, &ifr) < 0) {
316 		pr_warning("Config tap device error. Are you root?");
317 		goto fail;
318 	}
319 
320 	strncpy(ndev.tap_name, ifr.ifr_name, sizeof(ndev.tap_name));
321 
322 	if (ioctl(ndev.tap_fd, TUNSETNOCSUM, 1) < 0) {
323 		pr_warning("Config tap device TUNSETNOCSUM error");
324 		goto fail;
325 	}
326 
327 	hdr_len = sizeof(struct virtio_net_hdr);
328 	if (ioctl(ndev.tap_fd, TUNSETVNETHDRSZ, &hdr_len) < 0) {
329 		pr_warning("Config tap device TUNSETVNETHDRSZ error");
330 		goto fail;
331 	}
332 
333 	offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_UFO;
334 	if (ioctl(ndev.tap_fd, TUNSETOFFLOAD, offload) < 0) {
335 		pr_warning("Config tap device TUNSETOFFLOAD error");
336 		goto fail;
337 	}
338 
339 	if (strcmp(params->script, "none")) {
340 		pid = fork();
341 		if (pid == 0) {
342 			execl(params->script, params->script, ndev.tap_name, NULL);
343 			_exit(1);
344 		} else {
345 			waitpid(pid, &status, 0);
346 			if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
347 				pr_warning("Fail to setup tap by %s", params->script);
348 				goto fail;
349 			}
350 		}
351 	} else {
352 		memset(&ifr, 0, sizeof(ifr));
353 		strncpy(ifr.ifr_name, ndev.tap_name, sizeof(ndev.tap_name));
354 		sin.sin_addr.s_addr = inet_addr(params->host_ip);
355 		memcpy(&(ifr.ifr_addr), &sin, sizeof(ifr.ifr_addr));
356 		ifr.ifr_addr.sa_family = AF_INET;
357 		if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) {
358 			pr_warning("Could not set ip address on tap device");
359 			goto fail;
360 		}
361 	}
362 
363 	memset(&ifr, 0, sizeof(ifr));
364 	strncpy(ifr.ifr_name, ndev.tap_name, sizeof(ndev.tap_name));
365 	ioctl(sock, SIOCGIFFLAGS, &ifr);
366 	ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
367 	if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0)
368 		pr_warning("Could not bring tap device up");
369 
370 	close(sock);
371 
372 	return 1;
373 
374 fail:
375 	if (sock >= 0)
376 		close(sock);
377 	if (ndev.tap_fd >= 0)
378 		close(ndev.tap_fd);
379 
380 	return 0;
381 }
382 
383 static void virtio_net__io_thread_init(struct kvm *kvm)
384 {
385 	pthread_mutex_init(&ndev.io_rx_lock, NULL);
386 	pthread_cond_init(&ndev.io_tx_cond, NULL);
387 
388 	pthread_mutex_init(&ndev.io_rx_lock, NULL);
389 	pthread_cond_init(&ndev.io_tx_cond, NULL);
390 
391 	pthread_create(&ndev.io_rx_thread, NULL, virtio_net_rx_thread, (void *)kvm);
392 	pthread_create(&ndev.io_tx_thread, NULL, virtio_net_tx_thread, (void *)kvm);
393 }
394 
395 void virtio_net__init(const struct virtio_net_parameters *params)
396 {
397 	if (virtio_net__tap_init(params)) {
398 		u8 dev, line, pin;
399 		u16 net_base_addr;
400 		u64 i;
401 		struct ioevent ioevent;
402 
403 		if (irq__register_device(VIRTIO_ID_NET, &dev, &pin, &line) < 0)
404 			return;
405 
406 		pci_header.irq_pin	= pin;
407 		pci_header.irq_line	= line;
408 		net_base_addr		= ioport__register(IOPORT_EMPTY, &virtio_net_io_ops, IOPORT_SIZE, NULL);
409 		pci_header.bar[0]	= net_base_addr | PCI_BASE_ADDRESS_SPACE_IO;
410 		ndev.base_addr		= net_base_addr;
411 
412 		pci__register(&pci_header, dev);
413 
414 		virtio_net__io_thread_init(params->kvm);
415 
416 		for (i = 0; i < VIRTIO_NET_NUM_QUEUES; i++) {
417 			ioevent = (struct ioevent) {
418 				.io_addr		= net_base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
419 				.io_len			= sizeof(u16),
420 				.fn			= ioevent_callback,
421 				.datamatch		= i,
422 				.fn_ptr			= (void *)(long)i,
423 				.fn_kvm			= params->kvm,
424 				.fd			= eventfd(0, 0),
425 			};
426 
427 			ioeventfd__add_event(&ioevent);
428 		}
429 	}
430 }
431