struct vhost_net *vhost_net_init(VhostNetOptions *options) { int r; bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL; struct vhost_net *net = g_malloc(sizeof *net); if (!options->net_backend) { fprintf(stderr, "vhost-net requires net backend to be setup\n"); goto fail; } net->nc = options->net_backend; net->dev.max_queues = 1; net->dev.nvqs = 2; net->dev.vqs = net->vqs; if (backend_kernel) { r = vhost_net_get_fd(options->net_backend); if (r < 0) { goto fail; } net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend) ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR); net->backend = r; net->dev.protocol_features = 0; } else { net->dev.backend_features = 0; net->dev.protocol_features = 0; net->backend = -1; /* vhost-user needs vq_index to initiate a specific queue pair */ net->dev.vq_index = net->nc->queue_index * net->dev.nvqs; } r = vhost_dev_init(&net->dev, options->opaque, options->backend_type); if (r < 0) { goto fail; } if (backend_kernel) { if (!qemu_has_vnet_hdr_len(options->net_backend, sizeof(struct virtio_net_hdr_mrg_rxbuf))) { net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF); } if (~net->dev.features & net->dev.backend_features) { fprintf(stderr, "vhost lacks feature mask %" PRIu64 " for backend\n", (uint64_t)(~net->dev.features & net->dev.backend_features)); vhost_dev_cleanup(&net->dev); goto fail; } } /* Set sane init value. Override when guest acks. */ vhost_net_ack_features(net, 0); return net; fail: g_free(net); return NULL; }
static void e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr) { DeviceState *dev = DEVICE(pci_dev); NetClientState *nc; int i; s->nic = qemu_new_nic(&net_e1000e_info, &s->conf, object_get_typename(OBJECT(s)), dev->id, s); s->core.max_queue_num = s->conf.peers.queues - 1; trace_e1000e_mac_set_permanent(MAC_ARG(macaddr)); memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac)); qemu_format_nic_info_str(qemu_get_queue(s->nic), macaddr); /* Setup virtio headers */ if (s->disable_vnet) { s->core.has_vnet = false; trace_e1000e_cfg_support_virtio(false); return; } else { s->core.has_vnet = true; } for (i = 0; i < s->conf.peers.queues; i++) { nc = qemu_get_subqueue(s->nic, i); if (!nc->peer || !qemu_has_vnet_hdr(nc->peer)) { s->core.has_vnet = false; trace_e1000e_cfg_support_virtio(false); return; } } trace_e1000e_cfg_support_virtio(true); for (i = 0; i < s->conf.peers.queues; i++) { nc = qemu_get_subqueue(s->nic, i); qemu_set_vnet_hdr_len(nc->peer, sizeof(struct virtio_net_hdr)); qemu_using_vnet_hdr(nc->peer, true); } }