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