virtio-net.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * Virtio Network Device
  3. *
  4. * Copyright IBM, Corp. 2007
  5. *
  6. * Authors:
  7. * Anthony Liguori <aliguori@us.ibm.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2. See
  10. * the COPYING file in the top-level directory.
  11. *
  12. */
  13. #include "virtio.h"
  14. #include "net.h"
  15. #include "qemu-timer.h"
  16. #include "virtio-net.h"
  17. typedef struct VirtIONet
  18. {
  19. VirtIODevice vdev;
  20. uint8_t mac[6];
  21. uint16_t status;
  22. VirtQueue *rx_vq;
  23. VirtQueue *tx_vq;
  24. VLANClientState *vc;
  25. QEMUTimer *tx_timer;
  26. int tx_timer_active;
  27. int mergeable_rx_bufs;
  28. } VirtIONet;
  29. /* TODO
  30. * - we could suppress RX interrupt if we were so inclined.
  31. */
  32. static VirtIONet *to_virtio_net(VirtIODevice *vdev)
  33. {
  34. return (VirtIONet *)vdev;
  35. }
  36. static void virtio_net_update_config(VirtIODevice *vdev, uint8_t *config)
  37. {
  38. VirtIONet *n = to_virtio_net(vdev);
  39. struct virtio_net_config netcfg;
  40. netcfg.status = n->status;
  41. memcpy(netcfg.mac, n->mac, 6);
  42. memcpy(config, &netcfg, sizeof(netcfg));
  43. }
  44. static void virtio_net_set_link_status(VLANClientState *vc)
  45. {
  46. VirtIONet *n = vc->opaque;
  47. uint16_t old_status = n->status;
  48. if (vc->link_down)
  49. n->status &= ~VIRTIO_NET_S_LINK_UP;
  50. else
  51. n->status |= VIRTIO_NET_S_LINK_UP;
  52. if (n->status != old_status)
  53. virtio_notify_config(&n->vdev);
  54. }
  55. static uint32_t virtio_net_get_features(VirtIODevice *vdev)
  56. {
  57. uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_STATUS);
  58. return features;
  59. }
  60. static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
  61. {
  62. VirtIONet *n = to_virtio_net(vdev);
  63. n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
  64. }
  65. /* RX */
  66. static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
  67. {
  68. }
  69. static int do_virtio_net_can_receive(VirtIONet *n, int bufsize)
  70. {
  71. if (!virtio_queue_ready(n->rx_vq) ||
  72. !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
  73. return 0;
  74. if (virtio_queue_empty(n->rx_vq) ||
  75. (n->mergeable_rx_bufs &&
  76. !virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) {
  77. virtio_queue_set_notification(n->rx_vq, 1);
  78. return 0;
  79. }
  80. virtio_queue_set_notification(n->rx_vq, 0);
  81. return 1;
  82. }
  83. static int virtio_net_can_receive(void *opaque)
  84. {
  85. VirtIONet *n = opaque;
  86. return do_virtio_net_can_receive(n, VIRTIO_NET_MAX_BUFSIZE);
  87. }
  88. static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)
  89. {
  90. int offset, i;
  91. offset = i = 0;
  92. while (offset < count && i < iovcnt) {
  93. int len = MIN(iov[i].iov_len, count - offset);
  94. memcpy(iov[i].iov_base, buf + offset, len);
  95. offset += len;
  96. i++;
  97. }
  98. return offset;
  99. }
  100. static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
  101. const void *buf, size_t size, size_t hdr_len)
  102. {
  103. struct virtio_net_hdr *hdr = iov[0].iov_base;
  104. int offset = 0;
  105. hdr->flags = 0;
  106. hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
  107. /* We only ever receive a struct virtio_net_hdr from the tapfd,
  108. * but we may be passing along a larger header to the guest.
  109. */
  110. iov[0].iov_base += hdr_len;
  111. iov[0].iov_len -= hdr_len;
  112. return offset;
  113. }
  114. static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
  115. {
  116. VirtIONet *n = opaque;
  117. struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL;
  118. size_t hdr_len, offset, i;
  119. if (!do_virtio_net_can_receive(n, size))
  120. return;
  121. /* hdr_len refers to the header we supply to the guest */
  122. hdr_len = n->mergeable_rx_bufs ?
  123. sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
  124. offset = i = 0;
  125. while (offset < size) {
  126. VirtQueueElement elem;
  127. int len, total;
  128. struct iovec sg[VIRTQUEUE_MAX_SIZE];
  129. len = total = 0;
  130. if ((i != 0 && !n->mergeable_rx_bufs) ||
  131. virtqueue_pop(n->rx_vq, &elem) == 0) {
  132. if (i == 0)
  133. return;
  134. fprintf(stderr, "virtio-net truncating packet\n");
  135. exit(1);
  136. }
  137. if (elem.in_num < 1) {
  138. fprintf(stderr, "virtio-net receive queue contains no in buffers\n");
  139. exit(1);
  140. }
  141. if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != hdr_len) {
  142. fprintf(stderr, "virtio-net header not in first element\n");
  143. exit(1);
  144. }
  145. memcpy(&sg, &elem.in_sg[0], sizeof(sg[0]) * elem.in_num);
  146. if (i == 0) {
  147. if (n->mergeable_rx_bufs)
  148. mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
  149. offset += receive_header(n, sg, elem.in_num,
  150. buf + offset, size - offset, hdr_len);
  151. total += hdr_len;
  152. }
  153. /* copy in packet. ugh */
  154. len = iov_fill(sg, elem.in_num,
  155. buf + offset, size - offset);
  156. total += len;
  157. /* signal other side */
  158. virtqueue_fill(n->rx_vq, &elem, total, i++);
  159. offset += len;
  160. }
  161. if (mhdr)
  162. mhdr->num_buffers = i;
  163. virtqueue_flush(n->rx_vq, i);
  164. virtio_notify(&n->vdev, n->rx_vq);
  165. }
  166. /* TX */
  167. static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
  168. {
  169. VirtQueueElement elem;
  170. int has_vnet_hdr = 0;
  171. if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
  172. return;
  173. while (virtqueue_pop(vq, &elem)) {
  174. ssize_t len = 0;
  175. unsigned int out_num = elem.out_num;
  176. struct iovec *out_sg = &elem.out_sg[0];
  177. unsigned hdr_len;
  178. /* hdr_len refers to the header received from the guest */
  179. hdr_len = n->mergeable_rx_bufs ?
  180. sizeof(struct virtio_net_hdr_mrg_rxbuf) :
  181. sizeof(struct virtio_net_hdr);
  182. if (out_num < 1 || out_sg->iov_len != hdr_len) {
  183. fprintf(stderr, "virtio-net header not in first element\n");
  184. exit(1);
  185. }
  186. /* ignore the header if GSO is not supported */
  187. if (!has_vnet_hdr) {
  188. out_num--;
  189. out_sg++;
  190. len += hdr_len;
  191. } else if (n->mergeable_rx_bufs) {
  192. /* tapfd expects a struct virtio_net_hdr */
  193. hdr_len -= sizeof(struct virtio_net_hdr);
  194. out_sg->iov_len -= hdr_len;
  195. len += hdr_len;
  196. }
  197. len += qemu_sendv_packet(n->vc, out_sg, out_num);
  198. virtqueue_push(vq, &elem, len);
  199. virtio_notify(&n->vdev, vq);
  200. }
  201. }
  202. static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
  203. {
  204. VirtIONet *n = to_virtio_net(vdev);
  205. if (n->tx_timer_active) {
  206. virtio_queue_set_notification(vq, 1);
  207. qemu_del_timer(n->tx_timer);
  208. n->tx_timer_active = 0;
  209. virtio_net_flush_tx(n, vq);
  210. } else {
  211. qemu_mod_timer(n->tx_timer,
  212. qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
  213. n->tx_timer_active = 1;
  214. virtio_queue_set_notification(vq, 0);
  215. }
  216. }
  217. static void virtio_net_tx_timer(void *opaque)
  218. {
  219. VirtIONet *n = opaque;
  220. n->tx_timer_active = 0;
  221. /* Just in case the driver is not ready on more */
  222. if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
  223. return;
  224. virtio_queue_set_notification(n->tx_vq, 1);
  225. virtio_net_flush_tx(n, n->tx_vq);
  226. }
  227. static void virtio_net_save(QEMUFile *f, void *opaque)
  228. {
  229. VirtIONet *n = opaque;
  230. virtio_save(&n->vdev, f);
  231. qemu_put_buffer(f, n->mac, 6);
  232. qemu_put_be32(f, n->tx_timer_active);
  233. qemu_put_be32(f, n->mergeable_rx_bufs);
  234. }
  235. static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
  236. {
  237. VirtIONet *n = opaque;
  238. if (version_id != 2)
  239. return -EINVAL;
  240. virtio_load(&n->vdev, f);
  241. qemu_get_buffer(f, n->mac, 6);
  242. n->tx_timer_active = qemu_get_be32(f);
  243. n->mergeable_rx_bufs = qemu_get_be32(f);
  244. if (n->tx_timer_active) {
  245. qemu_mod_timer(n->tx_timer,
  246. qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
  247. }
  248. return 0;
  249. }
  250. PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
  251. {
  252. VirtIONet *n;
  253. static int virtio_net_id;
  254. n = (VirtIONet *)virtio_init_pci(bus, "virtio-net", 6900, 0x1000,
  255. 0, VIRTIO_ID_NET,
  256. 0x02, 0x00, 0x00,
  257. sizeof(struct virtio_net_config),
  258. sizeof(VirtIONet));
  259. if (!n)
  260. return NULL;
  261. n->vdev.get_config = virtio_net_update_config;
  262. n->vdev.get_features = virtio_net_get_features;
  263. n->vdev.set_features = virtio_net_set_features;
  264. n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
  265. n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
  266. memcpy(n->mac, nd->macaddr, 6);
  267. n->status = VIRTIO_NET_S_LINK_UP;
  268. n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
  269. virtio_net_receive, virtio_net_can_receive, n);
  270. n->vc->link_status_changed = virtio_net_set_link_status;
  271. qemu_format_nic_info_str(n->vc, n->mac);
  272. n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
  273. n->tx_timer_active = 0;
  274. n->mergeable_rx_bufs = 0;
  275. register_savevm("virtio-net", virtio_net_id++, 2,
  276. virtio_net_save, virtio_net_load, n);
  277. return (PCIDevice *)n;
  278. }