X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=net%2Fsocket.c;h=b1e3b1c8d99d360f893daaed0096f0243c7d709d;hb=2998ffee245e3a141ce1b6fca127744c3e19dc63;hp=c01323d4b0e6d05f6a21a43347558364b4bea462;hpb=4ba79505f43bd0ace35c3fe42197eb02e7e0478e;p=mirror_qemu.git diff --git a/net/socket.c b/net/socket.c index c01323d4b0..b1e3b1c8d9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -23,15 +23,15 @@ */ #include "config-host.h" -#include "net.h" +#include "net/net.h" #include "clients.h" -#include "monitor.h" -#include "qemu-char.h" +#include "monitor/monitor.h" #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu-option.h" -#include "qemu_socket.h" -#include "iov.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" +#include "qemu/main-loop.h" typedef struct NetSocketState { NetClientState nc; @@ -41,7 +41,7 @@ typedef struct NetSocketState { unsigned int index; unsigned int packet_len; unsigned int send_index; /* number of bytes sent (only SOCK_STREAM) */ - uint8_t buf[4096]; + uint8_t buf[NET_BUFSIZE]; struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */ bool read_poll; /* waiting to receive data? */ @@ -51,21 +51,12 @@ typedef struct NetSocketState { static void net_socket_accept(void *opaque); static void net_socket_writable(void *opaque); -/* Only read packets from socket when peer can receive them */ -static int net_socket_can_send(void *opaque) -{ - NetSocketState *s = opaque; - - return qemu_can_send_packet(&s->nc); -} - static void net_socket_update_fd_handler(NetSocketState *s) { - qemu_set_fd_handler2(s->fd, - s->read_poll ? net_socket_can_send : NULL, - s->read_poll ? s->send_fn : NULL, - s->write_poll ? net_socket_writable : NULL, - s); + qemu_set_fd_handler(s->fd, + s->read_poll ? s->send_fn : NULL, + s->write_poll ? net_socket_writable : NULL, + s); } static void net_socket_read_poll(NetSocketState *s, bool enable) @@ -142,12 +133,21 @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, return ret; } +static void net_socket_send_completed(NetClientState *nc, ssize_t len) +{ + NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); + + if (!s->read_poll) { + net_socket_read_poll(s, true); + } +} + static void net_socket_send(void *opaque) { NetSocketState *s = opaque; int size, err; unsigned l; - uint8_t buf1[4096]; + uint8_t buf1[NET_BUFSIZE]; const uint8_t *buf; size = qemu_recv(s->fd, buf1, sizeof(buf1), 0); @@ -211,9 +211,13 @@ static void net_socket_send(void *opaque) buf += l; size -= l; if (s->index >= s->packet_len) { - qemu_send_packet(&s->nc, s->buf, s->packet_len); s->index = 0; s->state = 0; + if (qemu_send_packet_async(&s->nc, s->buf, s->packet_len, + net_socket_send_completed) == 0) { + net_socket_read_poll(s, false); + break; + } } break; } @@ -234,7 +238,10 @@ static void net_socket_send_dgram(void *opaque) net_socket_write_poll(s, false); return; } - qemu_send_packet(&s->nc, s->buf, size); + if (qemu_send_packet_async(&s->nc, s->buf, size, + net_socket_send_completed) == 0) { + net_socket_read_poll(s, false); + } } static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr) @@ -262,9 +269,13 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr return -1; } + /* Allow multiple sockets to bind the same multicast ip and port by setting + * SO_REUSEADDR. This is the only situation where SO_REUSEADDR should be set + * on windows. Use socket_set_fast_reuse otherwise as it sets SO_REUSEADDR + * only on posix systems. + */ val = 1; - ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (const char *)&val, sizeof(val)); + ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); goto fail; @@ -284,8 +295,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr imr.imr_interface.s_addr = htonl(INADDR_ANY); } - ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (const char *)&imr, sizeof(struct ip_mreq)); + ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &imr, sizeof(struct ip_mreq)); if (ret < 0) { perror("setsockopt(IP_ADD_MEMBERSHIP)"); goto fail; @@ -293,8 +304,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr /* Force mcast msgs to loopback (eg. several QEMUs in same host */ loop = 1; - ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - (const char *)&loop, sizeof(loop)); + ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, + &loop, sizeof(loop)); if (ret < 0) { perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); goto fail; @@ -302,15 +313,15 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr /* If a bind address is given, only send packets from that address */ if (localaddr != NULL) { - ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char *)localaddr, sizeof(*localaddr)); + ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + localaddr, sizeof(*localaddr)); if (ret < 0) { perror("setsockopt(IP_MULTICAST_IF)"); goto fail; } } - socket_set_nonblock(fd); + qemu_set_nonblock(fd); return fd; fail: if (fd >= 0) @@ -348,7 +359,7 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, { struct sockaddr_in saddr; int newfd; - socklen_t saddr_len; + socklen_t saddr_len = sizeof(saddr); NetClientState *nc; NetSocketState *s; @@ -385,11 +396,6 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name); - snprintf(nc->info_str, sizeof(nc->info_str), - "socket: fd=%d (%s mcast=%s:%d)", - fd, is_connected ? "cloned" : "", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); - s = DO_UPCAST(NetSocketState, nc, nc); s->fd = fd; @@ -400,6 +406,12 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, /* mcast: save bound address as dst */ if (is_connected) { s->dgram_dst = saddr; + snprintf(nc->info_str, sizeof(nc->info_str), + "socket: fd=%d (cloned mcast=%s:%d)", + fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + } else { + snprintf(nc->info_str, sizeof(nc->info_str), + "socket: fd=%d", fd); } return s; @@ -440,6 +452,9 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, s->fd = fd; s->listen_fd = -1; + /* Disable Nagle algorithm on TCP sockets to reduce latency */ + socket_set_nodelay(fd); + if (is_connected) { net_socket_connect(s); } else { @@ -508,7 +523,7 @@ static int net_socket_listen_init(NetClientState *peer, NetClientState *nc; NetSocketState *s; struct sockaddr_in saddr; - int fd, val, ret; + int fd, ret; if (parse_host_port(&saddr, host_str) < 0) return -1; @@ -518,11 +533,9 @@ static int net_socket_listen_init(NetClientState *peer, perror("socket"); return -1; } - socket_set_nonblock(fd); + qemu_set_nonblock(fd); - /* allow fast reuse */ - val = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); + socket_set_fast_reuse(fd); ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { @@ -564,7 +577,7 @@ static int net_socket_connect_init(NetClientState *peer, perror("socket"); return -1; } - socket_set_nonblock(fd); + qemu_set_nonblock(fd); connected = 0; for(;;) { @@ -643,7 +656,7 @@ static int net_socket_udp_init(NetClientState *peer, const char *lhost) { NetSocketState *s; - int fd, val, ret; + int fd, ret; struct sockaddr_in laddr, raddr; if (parse_host_port(&laddr, lhost) < 0) { @@ -659,11 +672,9 @@ static int net_socket_udp_init(NetClientState *peer, perror("socket(PF_INET, SOCK_DGRAM)"); return -1; } - val = 1; - ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (const char *)&val, sizeof(val)); + + ret = socket_set_fast_reuse(fd); if (ret < 0) { - perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); closesocket(fd); return -1; } @@ -673,6 +684,7 @@ static int net_socket_udp_init(NetClientState *peer, closesocket(fd); return -1; } + qemu_set_nonblock(fd); s = net_socket_fd_init(peer, model, name, fd, 0); if (!s) { @@ -688,8 +700,10 @@ static int net_socket_udp_init(NetClientState *peer, } int net_init_socket(const NetClientOptions *opts, const char *name, - NetClientState *peer) + NetClientState *peer, Error **errp) { + /* FIXME error_setg(errp, ...) on failure */ + Error *err = NULL; const NetdevSocketOptions *sock; assert(opts->kind == NET_CLIENT_OPTIONS_KIND_SOCKET); @@ -710,8 +724,13 @@ int net_init_socket(const NetClientOptions *opts, const char *name, if (sock->has_fd) { int fd; - fd = monitor_handle_fd_param(cur_mon, sock->fd); - if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) { + fd = monitor_fd_param(cur_mon, sock->fd, &err); + if (fd == -1) { + error_report_err(err); + return -1; + } + qemu_set_nonblock(fd); + if (!net_socket_fd_init(peer, "socket", name, fd, 1)) { return -1; } return 0;