kvm tools: MSI-X fixes
[linux-2.6/next.git] / tools / kvm / virtio / net.c
blob4661e0661eb51ed5bbd44ff2525896f8b883bf1c
1 #include "kvm/virtio-pci-dev.h"
2 #include "kvm/virtio-net.h"
3 #include "kvm/virtio.h"
4 #include "kvm/types.h"
5 #include "kvm/mutex.h"
6 #include "kvm/util.h"
7 #include "kvm/kvm.h"
8 #include "kvm/irq.h"
9 #include "kvm/uip.h"
10 #include "kvm/guest_compat.h"
11 #include "kvm/virtio-pci.h"
13 #include <linux/virtio_net.h>
14 #include <linux/if_tun.h>
15 #include <linux/types.h>
17 #include <arpa/inet.h>
18 #include <net/if.h>
20 #include <unistd.h>
21 #include <assert.h>
22 #include <fcntl.h>
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
29 #define VIRTIO_NET_QUEUE_SIZE 128
30 #define VIRTIO_NET_NUM_QUEUES 2
31 #define VIRTIO_NET_RX_QUEUE 0
32 #define VIRTIO_NET_TX_QUEUE 1
34 struct net_dev;
36 extern struct kvm *kvm;
38 struct net_dev_operations {
39 int (*rx)(struct iovec *iov, u16 in, struct net_dev *ndev);
40 int (*tx)(struct iovec *iov, u16 in, struct net_dev *ndev);
43 struct net_dev {
44 pthread_mutex_t mutex;
45 struct virtio_pci vpci;
47 struct virt_queue vqs[VIRTIO_NET_NUM_QUEUES];
48 struct virtio_net_config config;
49 u32 features;
50 int compat_id;
52 pthread_t io_rx_thread;
53 pthread_mutex_t io_rx_lock;
54 pthread_cond_t io_rx_cond;
56 pthread_t io_tx_thread;
57 pthread_mutex_t io_tx_lock;
58 pthread_cond_t io_tx_cond;
60 int tap_fd;
61 char tap_name[IFNAMSIZ];
63 int mode;
65 struct uip_info info;
66 struct net_dev_operations *ops;
69 static struct net_dev ndev = {
70 .mutex = PTHREAD_MUTEX_INITIALIZER,
72 .config = {
73 .status = VIRTIO_NET_S_LINK_UP,
75 .info = {
76 .buf_nr = 20,
80 static void *virtio_net_rx_thread(void *p)
82 struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
83 struct virt_queue *vq;
84 struct kvm *kvm;
85 u16 out, in;
86 u16 head;
87 int len;
89 kvm = p;
90 vq = &ndev.vqs[VIRTIO_NET_RX_QUEUE];
92 while (1) {
94 mutex_lock(&ndev.io_rx_lock);
95 if (!virt_queue__available(vq))
96 pthread_cond_wait(&ndev.io_rx_cond, &ndev.io_rx_lock);
97 mutex_unlock(&ndev.io_rx_lock);
99 while (virt_queue__available(vq)) {
101 head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
103 len = ndev.ops->rx(iov, in, &ndev);
105 virt_queue__set_used_elem(vq, head, len);
107 /* We should interrupt guest right now, otherwise latency is huge. */
108 virtio_pci__signal_vq(kvm, &ndev.vpci, VIRTIO_NET_RX_QUEUE);
113 pthread_exit(NULL);
114 return NULL;
118 static void *virtio_net_tx_thread(void *p)
120 struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
121 struct virt_queue *vq;
122 struct kvm *kvm;
123 u16 out, in;
124 u16 head;
125 int len;
127 kvm = p;
128 vq = &ndev.vqs[VIRTIO_NET_TX_QUEUE];
130 while (1) {
131 mutex_lock(&ndev.io_tx_lock);
132 if (!virt_queue__available(vq))
133 pthread_cond_wait(&ndev.io_tx_cond, &ndev.io_tx_lock);
134 mutex_unlock(&ndev.io_tx_lock);
136 while (virt_queue__available(vq)) {
138 head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
140 len = ndev.ops->tx(iov, out, &ndev);
142 virt_queue__set_used_elem(vq, head, len);
145 virtio_pci__signal_vq(kvm, &ndev.vpci, VIRTIO_NET_TX_QUEUE);
148 pthread_exit(NULL);
150 return NULL;
154 static void virtio_net_handle_callback(struct kvm *kvm, u16 queue_index)
156 switch (queue_index) {
157 case VIRTIO_NET_TX_QUEUE:
158 mutex_lock(&ndev.io_tx_lock);
159 pthread_cond_signal(&ndev.io_tx_cond);
160 mutex_unlock(&ndev.io_tx_lock);
161 break;
162 case VIRTIO_NET_RX_QUEUE:
163 mutex_lock(&ndev.io_rx_lock);
164 pthread_cond_signal(&ndev.io_rx_cond);
165 mutex_unlock(&ndev.io_rx_lock);
166 break;
167 default:
168 pr_warning("Unknown queue index %u", queue_index);
172 static bool virtio_net__tap_init(const struct virtio_net_parameters *params)
174 int sock = socket(AF_INET, SOCK_STREAM, 0);
175 int pid, status, offload, hdr_len;
176 struct sockaddr_in sin = {0};
177 struct ifreq ifr;
179 ndev.tap_fd = open("/dev/net/tun", O_RDWR);
180 if (ndev.tap_fd < 0) {
181 pr_warning("Unable to open /dev/net/tun");
182 goto fail;
185 memset(&ifr, 0, sizeof(ifr));
186 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
187 if (ioctl(ndev.tap_fd, TUNSETIFF, &ifr) < 0) {
188 pr_warning("Config tap device error. Are you root?");
189 goto fail;
192 strncpy(ndev.tap_name, ifr.ifr_name, sizeof(ndev.tap_name));
194 if (ioctl(ndev.tap_fd, TUNSETNOCSUM, 1) < 0) {
195 pr_warning("Config tap device TUNSETNOCSUM error");
196 goto fail;
199 hdr_len = sizeof(struct virtio_net_hdr);
200 if (ioctl(ndev.tap_fd, TUNSETVNETHDRSZ, &hdr_len) < 0) {
201 pr_warning("Config tap device TUNSETVNETHDRSZ error");
204 offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_UFO;
205 if (ioctl(ndev.tap_fd, TUNSETOFFLOAD, offload) < 0) {
206 pr_warning("Config tap device TUNSETOFFLOAD error");
207 goto fail;
210 if (strcmp(params->script, "none")) {
211 pid = fork();
212 if (pid == 0) {
213 execl(params->script, params->script, ndev.tap_name, NULL);
214 _exit(1);
215 } else {
216 waitpid(pid, &status, 0);
217 if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
218 pr_warning("Fail to setup tap by %s", params->script);
219 goto fail;
222 } else {
223 memset(&ifr, 0, sizeof(ifr));
224 strncpy(ifr.ifr_name, ndev.tap_name, sizeof(ndev.tap_name));
225 sin.sin_addr.s_addr = inet_addr(params->host_ip);
226 memcpy(&(ifr.ifr_addr), &sin, sizeof(ifr.ifr_addr));
227 ifr.ifr_addr.sa_family = AF_INET;
228 if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) {
229 pr_warning("Could not set ip address on tap device");
230 goto fail;
234 memset(&ifr, 0, sizeof(ifr));
235 strncpy(ifr.ifr_name, ndev.tap_name, sizeof(ndev.tap_name));
236 ioctl(sock, SIOCGIFFLAGS, &ifr);
237 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
238 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0)
239 pr_warning("Could not bring tap device up");
241 close(sock);
243 return 1;
245 fail:
246 if (sock >= 0)
247 close(sock);
248 if (ndev.tap_fd >= 0)
249 close(ndev.tap_fd);
251 return 0;
254 static void virtio_net__io_thread_init(struct kvm *kvm)
256 pthread_mutex_init(&ndev.io_rx_lock, NULL);
257 pthread_cond_init(&ndev.io_tx_cond, NULL);
259 pthread_mutex_init(&ndev.io_rx_lock, NULL);
260 pthread_cond_init(&ndev.io_tx_cond, NULL);
262 pthread_create(&ndev.io_rx_thread, NULL, virtio_net_rx_thread, (void *)kvm);
263 pthread_create(&ndev.io_tx_thread, NULL, virtio_net_tx_thread, (void *)kvm);
266 static inline int tap_ops_tx(struct iovec *iov, u16 out, struct net_dev *ndev)
268 return writev(ndev->tap_fd, iov, out);
271 static inline int tap_ops_rx(struct iovec *iov, u16 in, struct net_dev *ndev)
273 return readv(ndev->tap_fd, iov, in);
276 static inline int uip_ops_tx(struct iovec *iov, u16 out, struct net_dev *ndev)
278 return uip_tx(iov, out, &ndev->info);
281 static inline int uip_ops_rx(struct iovec *iov, u16 in, struct net_dev *ndev)
283 return uip_rx(iov, in, &ndev->info);
286 static struct net_dev_operations tap_ops = {
287 .rx = tap_ops_rx,
288 .tx = tap_ops_tx,
291 static struct net_dev_operations uip_ops = {
292 .rx = uip_ops_rx,
293 .tx = uip_ops_tx,
296 static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
298 struct net_dev *ndev = dev;
300 ((u8 *)(&ndev->config))[offset] = data;
303 static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
305 struct net_dev *ndev = dev;
307 return ((u8 *)(&ndev->config))[offset];
310 static u32 get_host_features(struct kvm *kvm, void *dev)
312 return 1UL << VIRTIO_NET_F_MAC
313 | 1UL << VIRTIO_NET_F_CSUM
314 | 1UL << VIRTIO_NET_F_HOST_UFO
315 | 1UL << VIRTIO_NET_F_HOST_TSO4
316 | 1UL << VIRTIO_NET_F_HOST_TSO6
317 | 1UL << VIRTIO_NET_F_GUEST_UFO
318 | 1UL << VIRTIO_NET_F_GUEST_TSO4
319 | 1UL << VIRTIO_NET_F_GUEST_TSO6;
322 static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
324 struct net_dev *ndev = dev;
326 ndev->features = features;
329 static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
331 struct net_dev *ndev = dev;
332 struct virt_queue *queue;
333 void *p;
335 compat__remove_message(ndev->compat_id);
337 queue = &ndev->vqs[vq];
338 queue->pfn = pfn;
339 p = guest_pfn_to_host(kvm, queue->pfn);
341 vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
343 return 0;
346 static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
348 virtio_net_handle_callback(kvm, vq);
350 return 0;
353 static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
355 struct net_dev *ndev = dev;
357 return ndev->vqs[vq].pfn;
360 static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
362 return VIRTIO_NET_QUEUE_SIZE;
365 void virtio_net__init(const struct virtio_net_parameters *params)
367 int i;
369 for (i = 0 ; i < 6 ; i++) {
370 ndev.config.mac[i] = params->guest_mac[i];
371 ndev.info.guest_mac.addr[i] = params->guest_mac[i];
372 ndev.info.host_mac.addr[i] = params->host_mac[i];
375 ndev.mode = params->mode;
376 if (ndev.mode == NET_MODE_TAP) {
377 virtio_net__tap_init(params);
378 ndev.ops = &tap_ops;
379 } else {
380 ndev.info.host_ip = ntohl(inet_addr(params->host_ip));
381 ndev.info.guest_ip = ntohl(inet_addr(params->guest_ip));
382 ndev.info.guest_netmask = ntohl(inet_addr("255.255.255.0"));
383 uip_init(&ndev.info);
384 ndev.ops = &uip_ops;
387 virtio_pci__init(kvm, &ndev.vpci, &ndev, PCI_DEVICE_ID_VIRTIO_NET, VIRTIO_ID_NET);
388 ndev.vpci.ops = (struct virtio_pci_ops) {
389 .set_config = set_config,
390 .get_config = get_config,
391 .get_host_features = get_host_features,
392 .set_guest_features = set_guest_features,
393 .init_vq = init_vq,
394 .notify_vq = notify_vq,
395 .get_pfn_vq = get_pfn_vq,
396 .get_size_vq = get_size_vq,
399 virtio_net__io_thread_init(params->kvm);
401 ndev.compat_id = compat__add_message("virtio-net device was not detected",
402 "While you have requested a virtio-net device, "
403 "the guest kernel didn't seem to detect it.\n"
404 "Please make sure that the kernel was compiled"
405 "with CONFIG_VIRTIO_NET.");