Change so that Powerpc & ia64 do not have KVM_EXTRA_PAGES set
[qemu-kvm/fedora.git] / hw / virtio-net.c
blob86f9e5a084c63ac242b55a023becfc5b57ce07dc
1 /*
2 * Virtio Network Device
4 * Copyright IBM, Corp. 2007
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "virtio.h"
15 #include "net.h"
16 #include "pc.h"
17 #include "qemu-timer.h"
19 /* from Linux's virtio_net.h */
21 /* The ID for virtio_net */
22 #define VIRTIO_ID_NET 1
24 /* The feature bitmap for virtio net */
25 #define VIRTIO_NET_F_NO_CSUM 0
26 #define VIRTIO_NET_F_MAC 5
27 #define VIRTIO_NET_F_GS0 6
29 #define TX_TIMER_INTERVAL (1000 / 500)
31 /* The config defining mac address (6 bytes) */
32 struct virtio_net_config
34 uint8_t mac[6];
35 } __attribute__((packed));
37 /* This is the first element of the scatter-gather list. If you don't
38 * specify GSO or CSUM features, you can simply ignore the header. */
39 struct virtio_net_hdr
41 #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
42 uint8_t flags;
43 #define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
44 #define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
45 /* FIXME: Do we need this? If they said they can handle ECN, do they care? */
46 #define VIRTIO_NET_HDR_GSO_TCPV4_ECN 2 // GSO frame, IPv4 TCP w/ ECN
47 #define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
48 #define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
49 #define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
50 uint8_t gso_type;
51 uint16_t hdr_len;
52 uint16_t gso_size;
53 uint16_t csum_start;
54 uint16_t csum_offset;
57 typedef struct VirtIONet
59 VirtIODevice vdev;
60 uint8_t mac[6];
61 VirtQueue *rx_vq;
62 VirtQueue *tx_vq;
63 VLANClientState *vc;
64 int can_receive;
65 int tap_fd;
66 struct VirtIONet *next;
67 int do_notify;
68 QEMUTimer *tx_timer;
69 int tx_timer_active;
70 } VirtIONet;
72 static VirtIONet *VirtIONetHead = NULL;
74 static VirtIONet *to_virtio_net(VirtIODevice *vdev)
76 return (VirtIONet *)vdev;
79 static void virtio_net_update_config(VirtIODevice *vdev, uint8_t *config)
81 VirtIONet *n = to_virtio_net(vdev);
82 struct virtio_net_config netcfg;
84 memcpy(netcfg.mac, n->mac, 6);
85 memcpy(config, &netcfg, sizeof(netcfg));
88 static uint32_t virtio_net_get_features(VirtIODevice *vdev)
90 return (1 << VIRTIO_NET_F_MAC);
93 /* RX */
95 static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
97 VirtIONet *n = to_virtio_net(vdev);
98 n->can_receive = 1;
101 static int virtio_net_can_receive(void *opaque)
103 VirtIONet *n = opaque;
105 return (n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) && n->can_receive;
108 /* -net user receive function */
109 static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
111 VirtIONet *n = opaque;
112 VirtQueueElement elem;
113 struct virtio_net_hdr *hdr;
114 int offset, i;
116 /* FIXME: the drivers really need to set their status better */
117 if (n->rx_vq->vring.avail == NULL) {
118 n->can_receive = 0;
119 return;
122 if (virtqueue_pop(n->rx_vq, &elem) == 0) {
123 /* wait until the guest adds some rx bufs */
124 n->can_receive = 0;
125 return;
128 hdr = (void *)elem.in_sg[0].iov_base;
129 hdr->flags = 0;
130 hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
132 /* copy in packet. ugh */
133 offset = 0;
134 i = 1;
135 while (offset < size && i < elem.in_num) {
136 int len = MIN(elem.in_sg[i].iov_len, size - offset);
137 memcpy(elem.in_sg[i].iov_base, buf + offset, len);
138 offset += len;
139 i++;
142 /* signal other side */
143 virtqueue_push(n->rx_vq, &elem, sizeof(*hdr) + offset);
144 virtio_notify(&n->vdev, n->rx_vq);
147 /* -net tap receive handler */
148 void virtio_net_poll(void)
150 VirtIONet *vnet;
151 int len;
152 fd_set rfds;
153 struct timeval tv;
154 int max_fd = -1;
155 VirtQueueElement elem;
156 struct virtio_net_hdr *hdr;
157 int did_notify;
159 FD_ZERO(&rfds);
160 tv.tv_sec = 0;
161 tv.tv_usec = 0;
163 while (1) {
165 // Prepare the set of device to select from
166 for (vnet = VirtIONetHead; vnet; vnet = vnet->next) {
168 if (vnet->tap_fd == -1)
169 continue;
171 vnet->do_notify = 0;
172 //first check if the driver is ok
173 if (!virtio_net_can_receive(vnet))
174 continue;
176 /* FIXME: the drivers really need to set their status better */
177 if (vnet->rx_vq->vring.avail == NULL) {
178 vnet->can_receive = 0;
179 continue;
182 FD_SET(vnet->tap_fd, &rfds);
183 if (max_fd < vnet->tap_fd) max_fd = vnet->tap_fd;
186 if (select(max_fd + 1, &rfds, NULL, NULL, &tv) <= 0)
187 break;
189 // Now check who has data pending in the tap
190 for (vnet = VirtIONetHead; vnet; vnet = vnet->next) {
192 if (!FD_ISSET(vnet->tap_fd, &rfds))
193 continue;
195 if (virtqueue_pop(vnet->rx_vq, &elem) == 0) {
196 vnet->can_receive = 0;
197 continue;
200 hdr = (void *)elem.in_sg[0].iov_base;
201 hdr->flags = 0;
202 hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
203 again:
204 len = readv(vnet->tap_fd, &elem.in_sg[1], elem.in_num - 1);
205 if (len == -1) {
206 if (errno == EINTR || errno == EAGAIN)
207 goto again;
208 else
209 fprintf(stderr, "reading network error %d", len);
211 virtqueue_push(vnet->rx_vq, &elem, sizeof(*hdr) + len);
212 vnet->do_notify = 1;
215 /* signal other side */
216 did_notify = 0;
217 for (vnet = VirtIONetHead; vnet; vnet = vnet->next)
218 if (vnet->do_notify) {
219 virtio_notify(&vnet->vdev, vnet->rx_vq);
220 did_notify++;
222 if (!did_notify)
223 break;
228 /* TX */
229 static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
231 VirtQueueElement elem;
232 int count = 0;
234 if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
235 return;
237 while (virtqueue_pop(vq, &elem)) {
238 int i;
239 size_t len = 0;
241 /* ignore the header for now */
242 for (i = 1; i < elem.out_num; i++) {
243 qemu_send_packet(n->vc, elem.out_sg[i].iov_base,
244 elem.out_sg[i].iov_len);
245 len += elem.out_sg[i].iov_len;
248 count++;
250 virtqueue_push(vq, &elem, sizeof(struct virtio_net_hdr) + len);
251 virtio_notify(&n->vdev, vq);
255 static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
257 VirtIONet *n = to_virtio_net(vdev);
259 if (n->tx_timer_active &&
260 (vq->vring.avail->idx - vq->last_avail_idx) == 64) {
261 vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
262 qemu_del_timer(n->tx_timer);
263 n->tx_timer_active = 0;
264 virtio_net_flush_tx(n, vq);
265 } else {
266 qemu_mod_timer(n->tx_timer,
267 qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
268 n->tx_timer_active = 1;
269 vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
273 static void virtio_net_tx_timer(void *opaque)
275 VirtIONet *n = opaque;
277 n->tx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
278 n->tx_timer_active = 0;
279 virtio_net_flush_tx(n, n->tx_vq);
282 void *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
284 VirtIONet *n;
286 n = (VirtIONet *)virtio_init_pci(bus, "virtio-net", 6900, 0x1000,
287 0, VIRTIO_ID_NET,
288 0x02, 0x00, 0x00,
289 6, sizeof(VirtIONet));
291 n->vdev.update_config = virtio_net_update_config;
292 n->vdev.get_features = virtio_net_get_features;
293 n->rx_vq = virtio_add_queue(&n->vdev, 512, virtio_net_handle_rx);
294 n->tx_vq = virtio_add_queue(&n->vdev, 128, virtio_net_handle_tx);
295 n->can_receive = 0;
296 memcpy(n->mac, nd->macaddr, 6);
297 n->vc = qemu_new_vlan_client(nd->vlan, virtio_net_receive,
298 virtio_net_can_receive, n);
299 n->tap_fd = hack_around_tap(n->vc->vlan->first_client);
300 if (n->tap_fd != -1) {
301 n->next = VirtIONetHead;
302 //push the device on top of the list
303 VirtIONetHead = n;
306 n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
307 n->tx_timer_active = 0;
309 return &n->vdev;