X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=net.c;h=66123ad409e53efa3459d30ef022b7d05ce1d2e1;hb=0070f095d9aa216ebe4c06c43d0072275f23c8af;hp=ed74c7f103bceb938c2c2a9336a7ad305b2d060c;hpb=a083a89d7277f3268a251ce635d9aae5559242bd;p=qemu.git diff --git a/net.c b/net.c index ed74c7f10..66123ad40 100644 --- a/net.c +++ b/net.c @@ -32,10 +32,10 @@ #include "net/vde.h" #include "net/util.h" #include "monitor.h" -#include "sysemu.h" #include "qemu-common.h" #include "qemu_socket.h" #include "hw/qdev.h" +#include "iov.h" static QTAILQ_HEAD(, VLANState) vlans; static QTAILQ_HEAD(, VLANClientState) non_vlan_clients; @@ -93,47 +93,6 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) return 0; } -int parse_host_src_port(struct sockaddr_in *haddr, - struct sockaddr_in *saddr, - const char *input_str) -{ - char *str = qemu_strdup(input_str); - char *host_str = str; - char *src_str; - const char *src_str2; - char *ptr; - - /* - * Chop off any extra arguments at the end of the string which - * would start with a comma, then fill in the src port information - * if it was provided else use the "any address" and "any port". - */ - if ((ptr = strchr(str,','))) - *ptr = '\0'; - - if ((src_str = strchr(input_str,'@'))) { - *src_str = '\0'; - src_str++; - } - - if (parse_host_port(haddr, host_str) < 0) - goto fail; - - src_str2 = src_str; - if (!src_str || *src_str == '\0') - src_str2 = ":0"; - - if (parse_host_port(saddr, src_str2) < 0) - goto fail; - - free(str); - return(0); - -fail: - free(str); - return -1; -} - int parse_host_port(struct sockaddr_in *saddr, const char *str) { char buf[512]; @@ -411,11 +370,11 @@ int qemu_can_send_packet(VLANClientState *sender) } /* no can_receive() handler, they can always receive */ - if (!vc->info->can_receive || vc->info->can_receive(vc)) { - return 1; + if (vc->info->can_receive && !vc->info->can_receive(vc)) { + return 0; } } - return 0; + return 1; } static ssize_t qemu_deliver_packet(VLANClientState *sender, @@ -572,30 +531,13 @@ static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, int iovcnt) { uint8_t buffer[4096]; - size_t offset = 0; - int i; - - for (i = 0; i < iovcnt; i++) { - size_t len; + size_t offset; - len = MIN(sizeof(buffer) - offset, iov[i].iov_len); - memcpy(buffer + offset, iov[i].iov_base, len); - offset += len; - } + offset = iov_to_buf(iov, iovcnt, buffer, 0, sizeof(buffer)); return vc->info->receive(vc, buffer, offset); } -static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt) -{ - size_t offset = 0; - int i; - - for (i = 0; i < iovcnt; i++) - offset += iov[i].iov_len; - return offset; -} - static ssize_t qemu_deliver_packet_iov(VLANClientState *sender, unsigned flags, const struct iovec *iov, @@ -605,7 +547,7 @@ static ssize_t qemu_deliver_packet_iov(VLANClientState *sender, VLANClientState *vc = opaque; if (vc->link_down) { - return calc_iov_length(iov, iovcnt); + return iov_size(iov, iovcnt); } if (vc->info->receive_iov) { @@ -633,7 +575,7 @@ static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender, } if (vc->link_down) { - ret = calc_iov_length(iov, iovcnt); + ret = iov_size(iov, iovcnt); continue; } @@ -658,7 +600,7 @@ ssize_t qemu_sendv_packet_async(VLANClientState *sender, NetQueue *queue; if (sender->link_down || (!sender->peer && !sender->vlan)) { - return calc_iov_length(iov, iovcnt); + return iov_size(iov, iovcnt); } if (sender->peer) { @@ -768,25 +710,31 @@ int qemu_find_nic_model(NICInfo *nd, const char * const *models, return i; } - error_report("qemu: Unsupported NIC model: %s", nd->model); + error_report("Unsupported NIC model: %s", nd->model); return -1; } int net_handle_fd_param(Monitor *mon, const char *param) { - if (!qemu_isdigit(param[0])) { - int fd; + int fd; + + if (!qemu_isdigit(param[0]) && mon) { fd = monitor_get_fd(mon, param); if (fd == -1) { error_report("No file descriptor named %s found", param); return -1; } - - return fd; } else { - return strtol(param, NULL, 0); + char *endptr = NULL; + + fd = strtol(param, &endptr, 10); + if (*endptr || (fd == 0 && param == endptr)) { + return -1; + } } + + return fd; } static int net_init_nic(QemuOpts *opts, @@ -1019,7 +967,11 @@ static const struct { .name = "vhostfd", .type = QEMU_OPT_STRING, .help = "file descriptor of an already opened vhost net device", - }, + }, { + .name = "vhostforce", + .type = QEMU_OPT_BOOL, + .help = "force vhost on for non-MSIX virtio guests", + }, #endif /* _WIN32 */ { /* end of list */ } }, @@ -1044,6 +996,10 @@ static const struct { .name = "mcast", .type = QEMU_OPT_STRING, .help = "UDP multicast address and port number", + }, { + .name = "localaddr", + .type = QEMU_OPT_STRING, + .help = "source address for multicast packets", }, { /* end of list */ } }, @@ -1314,6 +1270,17 @@ done: if (vc->info->link_status_changed) { vc->info->link_status_changed(vc); } + + /* Notify peer. Don't update peer link status: this makes it possible to + * disconnect from host network without notifying the guest. + * FIXME: is disconnected link status change operation useful? + * + * Current behaviour is compatible with qemu vlans where there could be + * multiple clients that can still communicate with each other in + * disconnected mode. For now maintain this compatibility. */ + if (vc->peer && vc->peer->info->link_status_changed) { + vc->peer->info->link_status_changed(vc->peer); + } return 0; } @@ -1337,9 +1304,23 @@ void net_check_clients(void) { VLANState *vlan; VLANClientState *vc; - int has_nic = 0, has_host_dev = 0; + int i; + + /* Don't warn about the default network setup that you get if + * no command line -net or -netdev options are specified. There + * are two cases that we would otherwise complain about: + * (1) board doesn't support a NIC but the implicit "-net nic" + * requested one + * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic" + * sets up a nic that isn't connected to anything. + */ + if (default_net) { + return; + } QTAILQ_FOREACH(vlan, &vlans, next) { + int has_nic = 0, has_host_dev = 0; + QTAILQ_FOREACH(vc, &vlan->clients, next) { switch (vc->info->type) { case NET_CLIENT_TYPE_NIC: @@ -1368,6 +1349,20 @@ void net_check_clients(void) vc->name); } } + + /* Check that all NICs requested via -net nic actually got created. + * NICs created via -device don't need to be checked here because + * they are always instantiated. + */ + for (i = 0; i < MAX_NICS; i++) { + NICInfo *nd = &nd_table[i]; + if (nd->used && !nd->instantiated) { + fprintf(stderr, "Warning: requested NIC (%s, model %s) " + "was not created (not supported by this machine?)\n", + nd->name ? nd->name : "anonymous", + nd->model ? nd->model : "unspecified"); + } + } } static int net_init_client(QemuOpts *opts, void *dummy)