Remove non-existent -translation option
[qemu-kvm/fedora.git] / hw / virtio-net.c
blob2e57e5a042f3e389d2cf88a342dd96b17d5560ae
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 "qemu-timer.h"
17 #include "qemu-kvm.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 QEMUTimer *tx_timer;
65 int tx_timer_active;
66 } VirtIONet;
68 /* TODO
69 * - we could suppress RX interrupt if we were so inclined.
72 static VirtIONet *to_virtio_net(VirtIODevice *vdev)
74 return (VirtIONet *)vdev;
77 static void virtio_net_update_config(VirtIODevice *vdev, uint8_t *config)
79 VirtIONet *n = to_virtio_net(vdev);
80 struct virtio_net_config netcfg;
82 memcpy(netcfg.mac, n->mac, 6);
83 memcpy(config, &netcfg, sizeof(netcfg));
86 static uint32_t virtio_net_get_features(VirtIODevice *vdev)
88 return (1 << VIRTIO_NET_F_MAC);
91 /* RX */
93 static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
95 /* We now have RX buffers, signal to the IO thread to break out of the
96 select to re-poll the tap file descriptor */
97 if (kvm_enabled())
98 qemu_kvm_notify_work();
101 static int virtio_net_can_receive(void *opaque)
103 VirtIONet *n = opaque;
105 if (n->rx_vq->vring.avail == NULL ||
106 !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
107 return 0;
109 if (n->rx_vq->vring.avail->idx == n->rx_vq->last_avail_idx)
110 return 0;
112 return 1;
115 static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
117 VirtIONet *n = opaque;
118 VirtQueueElement elem;
119 struct virtio_net_hdr *hdr;
120 int offset, i;
122 if (virtqueue_pop(n->rx_vq, &elem) == 0)
123 return;
125 if (elem.in_num < 1 || elem.in_sg[0].iov_len != sizeof(*hdr)) {
126 fprintf(stderr, "virtio-net header not in first element\n");
127 exit(1);
130 hdr = (void *)elem.in_sg[0].iov_base;
131 hdr->flags = 0;
132 hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
134 /* copy in packet. ugh */
135 offset = 0;
136 i = 1;
137 while (offset < size && i < elem.in_num) {
138 int len = MIN(elem.in_sg[i].iov_len, size - offset);
139 memcpy(elem.in_sg[i].iov_base, buf + offset, len);
140 offset += len;
141 i++;
144 /* signal other side */
145 virtqueue_push(n->rx_vq, &elem, sizeof(*hdr) + offset);
146 virtio_notify(&n->vdev, n->rx_vq);
149 /* TX */
150 static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
152 VirtQueueElement elem;
154 if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
155 return;
157 while (virtqueue_pop(vq, &elem)) {
158 ssize_t len = 0;
160 if (elem.out_num < 1 ||
161 elem.out_sg[0].iov_len != sizeof(struct virtio_net_hdr)) {
162 fprintf(stderr, "virtio-net header not in first element\n");
163 exit(1);
166 /* ignore the header for now */
167 len = qemu_sendv_packet(n->vc, &elem.out_sg[1], elem.out_num - 1);
169 virtqueue_push(vq, &elem, sizeof(struct virtio_net_hdr) + len);
170 virtio_notify(&n->vdev, vq);
174 static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
176 VirtIONet *n = to_virtio_net(vdev);
178 if (n->tx_timer_active &&
179 (vq->vring.avail->idx - vq->last_avail_idx) == 64) {
180 vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
181 qemu_del_timer(n->tx_timer);
182 n->tx_timer_active = 0;
183 virtio_net_flush_tx(n, vq);
184 } else {
185 qemu_mod_timer(n->tx_timer,
186 qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
187 n->tx_timer_active = 1;
188 vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
192 static void virtio_net_tx_timer(void *opaque)
194 VirtIONet *n = opaque;
196 n->tx_timer_active = 0;
198 /* Just in case the driver is not ready on more */
199 if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
200 return;
202 n->tx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
203 virtio_net_flush_tx(n, n->tx_vq);
206 static void virtio_net_save(QEMUFile *f, void *opaque)
208 VirtIONet *n = opaque;
210 virtio_save(&n->vdev, f);
212 qemu_put_buffer(f, n->mac, 6);
213 qemu_put_be32(f, n->tx_timer_active);
216 static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
218 VirtIONet *n = opaque;
220 if (version_id != 1)
221 return -EINVAL;
223 virtio_load(&n->vdev, f);
225 qemu_get_buffer(f, n->mac, 6);
226 n->tx_timer_active = qemu_get_be32(f);
228 if (n->tx_timer_active) {
229 qemu_mod_timer(n->tx_timer,
230 qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
233 return 0;
236 PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
238 VirtIONet *n;
239 static int virtio_net_id;
241 n = (VirtIONet *)virtio_init_pci(bus, "virtio-net", 6900, 0x1000,
242 0, VIRTIO_ID_NET,
243 0x02, 0x00, 0x00,
244 6, sizeof(VirtIONet));
245 if (!n)
246 return NULL;
248 n->vdev.update_config = virtio_net_update_config;
249 n->vdev.get_features = virtio_net_get_features;
250 n->rx_vq = virtio_add_queue(&n->vdev, 128, virtio_net_handle_rx);
251 n->tx_vq = virtio_add_queue(&n->vdev, 128, virtio_net_handle_tx);
252 memcpy(n->mac, nd->macaddr, 6);
253 n->vc = qemu_new_vlan_client(nd->vlan, virtio_net_receive,
254 virtio_net_can_receive, n);
256 n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
257 n->tx_timer_active = 0;
259 register_savevm("virtio-net", virtio_net_id++, 1,
260 virtio_net_save, virtio_net_load, n);
262 return (PCIDevice *)n;