static int vhost_scsi_init(VirtIODevice *vdev) { VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev); VHostSCSI *s = VHOST_SCSI(vdev); int vhostfd = -1; int ret; if (!vs->conf.wwpn) { error_report("vhost-scsi: missing wwpn\n"); return -EINVAL; } if (vs->conf.vhostfd) { vhostfd = monitor_handle_fd_param(cur_mon, vs->conf.vhostfd); if (vhostfd == -1) { error_report("vhost-scsi: unable to parse vhostfd\n"); return -EINVAL; } } ret = virtio_scsi_common_init(vs); if (ret < 0) { return ret; } s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs); s->dev.vq_index = 0; ret = vhost_dev_init(&s->dev, vhostfd, "/dev/vhost-scsi", true); if (ret < 0) { error_report("vhost-scsi: vhost initialization failed: %s\n", strerror(-ret)); return ret; } s->dev.backend_features = 0; error_setg(&s->migration_blocker, "vhost-scsi does not support migration"); migrate_add_blocker(s->migration_blocker); return 0; }
static void vhost_scsi_realize(DeviceState *dev, Error **errp) { VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); VHostSCSI *s = VHOST_SCSI(dev); Error *err = NULL; int vhostfd = -1; int ret; if (!vs->conf.wwpn) { error_setg(errp, "vhost-scsi: missing wwpn"); return; } if (vs->conf.vhostfd) { vhostfd = monitor_handle_fd_param(cur_mon, vs->conf.vhostfd); if (vhostfd == -1) { error_setg(errp, "vhost-scsi: unable to parse vhostfd"); return; } } virtio_scsi_common_realize(dev, &err); if (err != NULL) { error_propagate(errp, err); return; } s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs); s->dev.vq_index = 0; ret = vhost_dev_init(&s->dev, vhostfd, "/dev/vhost-scsi", true); if (ret < 0) { error_setg(errp, "vhost-scsi: vhost initialization failed: %s", strerror(-ret)); return; } s->dev.backend_features = 0; error_setg(&s->migration_blocker, "vhost-scsi does not support migration"); migrate_add_blocker(s->migration_blocker); }
int net_init_tap(const NetClientOptions *opts, const char *name, NetClientState *peer) { const NetdevTapOptions *tap; int fd, vnet_hdr = 0, i = 0, queues; /* for the no-fd, no-helper case */ const char *script = NULL; /* suppress wrong "uninit'd use" gcc warning */ const char *downscript = NULL; const char *vhostfdname; char ifname[128]; assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); tap = opts->tap; queues = tap->has_queues ? tap->queues : 1; vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL; /* QEMU vlans does not support multiqueue tap, in this case peer is set. * For -netdev, peer is always NULL. */ if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) { error_report("Multiqueue tap cannot be used with QEMU vlans"); return -1; } if (tap->has_fd) { if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper || tap->has_queues || tap->has_fds || tap->has_vhostfds) { error_report("ifname=, script=, downscript=, vnet_hdr=, " "helper=, queues=, fds=, and vhostfds= " "are invalid with fd="); return -1; } fd = monitor_handle_fd_param(cur_mon, tap->fd); if (fd == -1) { return -1; } fcntl(fd, F_SETFL, O_NONBLOCK); vnet_hdr = tap_probe_vnet_hdr(fd); if (net_init_tap_one(tap, peer, "tap", name, NULL, script, downscript, vhostfdname, vnet_hdr, fd)) { return -1; } } else if (tap->has_fds) { char *fds[MAX_TAP_QUEUES]; char *vhost_fds[MAX_TAP_QUEUES]; int nfds, nvhosts; if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper || tap->has_queues || tap->has_vhostfd) { error_report("ifname=, script=, downscript=, vnet_hdr=, " "helper=, queues=, and vhostfd= " "are invalid with fds="); return -1; } nfds = get_fds(tap->fds, fds, MAX_TAP_QUEUES); if (tap->has_vhostfds) { nvhosts = get_fds(tap->vhostfds, vhost_fds, MAX_TAP_QUEUES); if (nfds != nvhosts) { error_report("The number of fds passed does not match the " "number of vhostfds passed"); return -1; } } for (i = 0; i < nfds; i++) { fd = monitor_handle_fd_param(cur_mon, fds[i]); if (fd == -1) { return -1; } fcntl(fd, F_SETFL, O_NONBLOCK); if (i == 0) { vnet_hdr = tap_probe_vnet_hdr(fd); } else if (vnet_hdr != tap_probe_vnet_hdr(fd)) { error_report("vnet_hdr not consistent across given tap fds"); return -1; } if (net_init_tap_one(tap, peer, "tap", name, ifname, script, downscript, tap->has_vhostfds ? vhost_fds[i] : NULL, vnet_hdr, fd)) { return -1; } } } else if (tap->has_helper) { if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_queues || tap->has_vhostfds) { error_report("ifname=, script=, downscript=, and vnet_hdr= " "queues=, and vhostfds= are invalid with helper="); return -1; } fd = net_bridge_run_helper(tap->helper, DEFAULT_BRIDGE_INTERFACE); if (fd == -1) { return -1; } fcntl(fd, F_SETFL, O_NONBLOCK); vnet_hdr = tap_probe_vnet_hdr(fd); if (net_init_tap_one(tap, peer, "bridge", name, ifname, script, downscript, vhostfdname, vnet_hdr, fd)) { return -1; } } else { if (tap->has_vhostfds) { error_report("vhostfds= is invalid if fds= wasn't specified"); return -1; } script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT; downscript = tap->has_downscript ? tap->downscript : DEFAULT_NETWORK_DOWN_SCRIPT; if (tap->has_ifname) { pstrcpy(ifname, sizeof ifname, tap->ifname); } else { ifname[0] = '\0'; } for (i = 0; i < queues; i++) { fd = net_tap_init(tap, &vnet_hdr, i >= 1 ? "no" : script, ifname, sizeof ifname, queues > 1); if (fd == -1) { return -1; } if (queues > 1 && i == 0 && !tap->has_ifname) { if (tap_fd_get_ifname(fd, ifname)) { error_report("Fail to get ifname"); return -1; } } if (net_init_tap_one(tap, peer, "tap", name, ifname, i >= 1 ? "no" : script, i >= 1 ? "no" : downscript, vhostfdname, vnet_hdr, fd)) { return -1; } } } return 0; }
static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, const char *model, const char *name, const char *ifname, const char *script, const char *downscript, const char *vhostfdname, int vnet_hdr, int fd) { TAPState *s; s = net_tap_fd_init(peer, model, name, fd, vnet_hdr); if (!s) { close(fd); return -1; } if (tap_set_sndbuf(s->fd, tap) < 0) { return -1; } if (tap->has_fd || tap->has_fds) { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd); } else if (tap->has_helper) { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s", tap->helper); } else { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "ifname=%s,script=%s,downscript=%s", ifname, script, downscript); if (strcmp(downscript, "no") != 0) { snprintf(s->down_script, sizeof(s->down_script), "%s", downscript); snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname); } } if (tap->has_vhost ? tap->vhost : vhostfdname || (tap->has_vhostforce && tap->vhostforce)) { int vhostfd; if (tap->has_vhostfd || tap->has_vhostfds) { vhostfd = monitor_handle_fd_param(cur_mon, vhostfdname); if (vhostfd == -1) { return -1; } } else { vhostfd = -1; } s->vhost_net = vhost_net_init(&s->nc, vhostfd, tap->has_vhostforce && tap->vhostforce); if (!s->vhost_net) { error_report("vhost-net requested but could not be initialized"); return -1; } } else if (tap->has_vhostfd || tap->has_vhostfds) { error_report("vhostfd= is not valid without vhost"); return -1; } return 0; }
int net_init_tap(const NetClientOptions *opts, const char *name, NetClientState *peer) { const NetdevTapOptions *tap; int fd, vnet_hdr = 0; const char *model; TAPState *s; /* for the no-fd, no-helper case */ const char *script = NULL; /* suppress wrong "uninit'd use" gcc warning */ char ifname[128]; assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); tap = opts->tap; if (tap->has_fd) { if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper) { error_report("ifname=, script=, downscript=, vnet_hdr=, " "and helper= are invalid with fd="); return -1; } fd = monitor_handle_fd_param(cur_mon, tap->fd); if (fd == -1) { return -1; } fcntl(fd, F_SETFL, O_NONBLOCK); vnet_hdr = tap_probe_vnet_hdr(fd); model = "tap"; } else if (tap->has_helper) { if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr) { error_report("ifname=, script=, downscript=, and vnet_hdr= " "are invalid with helper="); return -1; } fd = net_bridge_run_helper(tap->helper, DEFAULT_BRIDGE_INTERFACE); if (fd == -1) { return -1; } fcntl(fd, F_SETFL, O_NONBLOCK); vnet_hdr = tap_probe_vnet_hdr(fd); model = "bridge"; } else { script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT; fd = net_tap_init(tap, &vnet_hdr, script, ifname, sizeof ifname); if (fd == -1) { return -1; } model = "tap"; } s = net_tap_fd_init(peer, model, name, fd, vnet_hdr); if (!s) { close(fd); return -1; } if (tap_set_sndbuf(s->fd, tap) < 0) { return -1; } if (tap->has_fd) { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd); } else if (tap->has_helper) { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s", tap->helper); } else { const char *downscript; downscript = tap->has_downscript ? tap->downscript : DEFAULT_NETWORK_DOWN_SCRIPT; snprintf(s->nc.info_str, sizeof(s->nc.info_str), "ifname=%s,script=%s,downscript=%s", ifname, script, downscript); if (strcmp(downscript, "no") != 0) { snprintf(s->down_script, sizeof(s->down_script), "%s", downscript); snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname); } } if (tap->has_vhost ? tap->vhost : tap->has_vhostfd || (tap->has_vhostforce && tap->vhostforce)) { int vhostfd; if (tap->has_vhostfd) { vhostfd = monitor_handle_fd_param(cur_mon, tap->vhostfd); if (vhostfd == -1) { return -1; } } else { vhostfd = -1; } s->vhost_net = vhost_net_init(&s->nc, vhostfd, tap->has_vhostforce && tap->vhostforce); if (!s->vhost_net) { error_report("vhost-net requested but could not be initialized"); return -1; } } else if (tap->has_vhostfd) { error_report("vhostfd= is not valid without vhost"); return -1; } return 0; }