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