net: dgram: move mcast specific code from net_socket_fd_init_dgram()

It is less complex to manage special cases directly in
net_dgram_mcast_init() and net_dgram_udp_init().

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Laurent Vivier 2022-10-21 11:09:16 +02:00 committed by Jason Wang
parent 7c1f0c33cc
commit 8ecc7f40bc

View File

@ -259,52 +259,11 @@ static NetClientInfo net_dgram_socket_info = {
static NetDgramState *net_dgram_fd_init(NetClientState *peer, static NetDgramState *net_dgram_fd_init(NetClientState *peer,
const char *model, const char *model,
const char *name, const char *name,
int fd, int is_fd, int fd,
SocketAddress *mcast,
Error **errp) Error **errp)
{ {
struct sockaddr_in *saddr = NULL;
int newfd;
NetClientState *nc; NetClientState *nc;
NetDgramState *s; NetDgramState *s;
SocketAddress *sa;
SocketAddressType sa_type;
sa = socket_local_address(fd, errp);
if (!sa) {
return NULL;
}
sa_type = sa->type;
qapi_free_SocketAddress(sa);
/*
* fd passed: multicast: "learn" dest_addr address from bound address and
* save it. Because this may be "shared" socket from a "master" process,
* datagrams would be recv() by ONLY ONE process: we must "clone" this
* dgram socket --jjo
*/
if (is_fd && mcast != NULL) {
saddr = g_new(struct sockaddr_in, 1);
if (convert_host_port(saddr, mcast->u.inet.host, mcast->u.inet.port,
errp) < 0) {
goto err;
}
/* must be bound */
if (saddr->sin_addr.s_addr == 0) {
error_setg(errp, "can't setup multicast destination address");
goto err;
}
/* clone dgram socket */
newfd = net_dgram_mcast_create(saddr, NULL, errp);
if (newfd < 0) {
goto err;
}
/* clone newfd to fd, close newfd */
dup2(newfd, fd);
close(newfd);
}
nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name); nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
@ -314,23 +273,7 @@ static NetDgramState *net_dgram_fd_init(NetClientState *peer,
net_socket_rs_init(&s->rs, net_dgram_rs_finalize, false); net_socket_rs_init(&s->rs, net_dgram_rs_finalize, false);
net_dgram_read_poll(s, true); net_dgram_read_poll(s, true);
/* mcast: save bound address as dst */
if (saddr) {
g_assert(s->dest_addr == NULL);
s->dest_addr = (struct sockaddr *)saddr;
s->dest_len = sizeof(*saddr);
qemu_set_info_str(nc, "fd=%d (cloned mcast=%s:%d)", fd,
inet_ntoa(saddr->sin_addr), ntohs(saddr->sin_port));
} else {
qemu_set_info_str(nc, "fd=%d %s", fd, SocketAddressType_str(sa_type));
}
return s; return s;
err:
g_free(saddr);
closesocket(fd);
return NULL;
} }
static int net_dgram_mcast_init(NetClientState *peer, static int net_dgram_mcast_init(NetClientState *peer,
@ -381,7 +324,9 @@ static int net_dgram_mcast_init(NetClientState *peer,
} }
break; break;
} }
case SOCKET_ADDRESS_TYPE_FD: case SOCKET_ADDRESS_TYPE_FD: {
int newfd;
fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp); fd = monitor_fd_param(monitor_cur(), local->u.fd.str, errp);
if (fd == -1) { if (fd == -1) {
g_free(saddr); g_free(saddr);
@ -394,7 +339,42 @@ static int net_dgram_mcast_init(NetClientState *peer,
name, fd); name, fd);
return -1; return -1;
} }
/*
* fd passed: multicast: "learn" dest_addr address from bound
* address and save it. Because this may be "shared" socket from a
* "master" process, datagrams would be recv() by ONLY ONE process:
* we must "clone" this dgram socket --jjo
*/
saddr = g_new(struct sockaddr_in, 1);
if (convert_host_port(saddr, local->u.inet.host, local->u.inet.port,
errp) < 0) {
g_free(saddr);
closesocket(fd);
return -1;
}
/* must be bound */
if (saddr->sin_addr.s_addr == 0) {
error_setg(errp, "can't setup multicast destination address");
g_free(saddr);
closesocket(fd);
return -1;
}
/* clone dgram socket */
newfd = net_dgram_mcast_create(saddr, NULL, errp);
if (newfd < 0) {
g_free(saddr);
closesocket(fd);
return -1;
}
/* clone newfd to fd, close newfd */
dup2(newfd, fd);
close(newfd);
break; break;
}
default: default:
g_free(saddr); g_free(saddr);
error_setg(errp, "only support inet or fd type for local"); error_setg(errp, "only support inet or fd type for local");
@ -402,9 +382,7 @@ static int net_dgram_mcast_init(NetClientState *peer,
} }
} }
s = net_dgram_fd_init(peer, model, name, fd, s = net_dgram_fd_init(peer, model, name, fd, errp);
local->type == SOCKET_ADDRESS_TYPE_FD,
remote, errp);
if (!s) { if (!s) {
g_free(saddr); g_free(saddr);
return -1; return -1;
@ -414,8 +392,26 @@ static int net_dgram_mcast_init(NetClientState *peer,
s->dest_addr = (struct sockaddr *)saddr; s->dest_addr = (struct sockaddr *)saddr;
s->dest_len = sizeof(*saddr); s->dest_len = sizeof(*saddr);
qemu_set_info_str(&s->nc, "mcast=%s:%d", inet_ntoa(saddr->sin_addr), if (!local) {
qemu_set_info_str(&s->nc, "mcast=%s:%d",
inet_ntoa(saddr->sin_addr),
ntohs(saddr->sin_port)); ntohs(saddr->sin_port));
} else {
switch (local->type) {
case SOCKET_ADDRESS_TYPE_INET:
qemu_set_info_str(&s->nc, "mcast=%s:%d",
inet_ntoa(saddr->sin_addr),
ntohs(saddr->sin_port));
break;
case SOCKET_ADDRESS_TYPE_FD:
qemu_set_info_str(&s->nc, "fd=%d (cloned mcast=%s:%d)",
fd, inet_ntoa(saddr->sin_addr),
ntohs(saddr->sin_port));
break;
default:
g_assert_not_reached();
}
}
return 0; return 0;
@ -531,7 +527,7 @@ int net_init_dgram(const Netdev *netdev, const char *name,
return -1; return -1;
} }
s = net_dgram_fd_init(peer, "dgram", name, fd, 0, NULL, errp); s = net_dgram_fd_init(peer, "dgram", name, fd, errp);
if (!s) { if (!s) {
return -1; return -1;
} }
@ -550,9 +546,22 @@ int net_init_dgram(const Netdev *netdev, const char *name,
inet_ntoa(raddr_in.sin_addr), inet_ntoa(raddr_in.sin_addr),
ntohs(raddr_in.sin_port)); ntohs(raddr_in.sin_port));
break; break;
case SOCKET_ADDRESS_TYPE_FD: case SOCKET_ADDRESS_TYPE_FD: {
SocketAddress *sa;
SocketAddressType sa_type;
sa = socket_local_address(fd, errp);
if (sa) {
sa_type = sa->type;
qapi_free_SocketAddress(sa);
qemu_set_info_str(&s->nc, "fd=%d %s", fd,
SocketAddressType_str(sa_type));
} else {
qemu_set_info_str(&s->nc, "fd=%d", fd); qemu_set_info_str(&s->nc, "fd=%d", fd);
}
break; break;
}
default: default:
g_assert_not_reached(); g_assert_not_reached();
} }