Skip to content

Commit

Permalink
vsock: add multiple transports support for dgram
Browse files Browse the repository at this point in the history
Currently, only VMCI supports dgram sockets. To supported
nested VM use case, this patch removes transport_dgram and
uses transport_g2h and transport_h2g for dgram too.

The transport is assgined when sending every packet and
receiving every packet on dgram sockets.

Signed-off-by: Jiang Wang <jiang.wang@bytedance.com>
  • Loading branch information
jiang.wang authored and intel-lab-lkp committed Apr 6, 2021
1 parent 0a50438 commit 84be269
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 40 deletions.
2 changes: 0 additions & 2 deletions include/net/af_vsock.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ struct vsock_transport_send_notify_data {
#define VSOCK_TRANSPORT_F_H2G 0x00000001
/* Transport provides guest->host communication */
#define VSOCK_TRANSPORT_F_G2H 0x00000002
/* Transport provides DGRAM communication */
#define VSOCK_TRANSPORT_F_DGRAM 0x00000004
/* Transport provides local (loopback) communication */
#define VSOCK_TRANSPORT_F_LOCAL 0x00000008

Expand Down
63 changes: 32 additions & 31 deletions net/vmw_vsock/af_vsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,6 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)

switch (sk->sk_type) {
case SOCK_DGRAM:
new_transport = transport_dgram;
break;
case SOCK_STREAM:
if (vsock_use_local_transport(remote_cid))
new_transport = transport_local;
Expand Down Expand Up @@ -1096,7 +1094,6 @@ static int vsock_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
struct sock *sk;
struct vsock_sock *vsk;
struct sockaddr_vm *remote_addr;
const struct vsock_transport *transport;

if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP;
Expand All @@ -1108,25 +1105,30 @@ static int vsock_dgram_sendmsg(struct socket *sock, struct msghdr *msg,

lock_sock(sk);

transport = vsk->transport;

err = vsock_auto_bind(vsk);
if (err)
goto out;


/* If the provided message contains an address, use that. Otherwise
* fall back on the socket's remote handle (if it has been connected).
*/
if (msg->msg_name &&
vsock_addr_cast(msg->msg_name, msg->msg_namelen,
&remote_addr) == 0) {
vsock_addr_init(&vsk->remote_addr, remote_addr->svm_cid,
remote_addr->svm_port);

err = vsock_assign_transport(vsk, NULL);
if (err) {
err = -EINVAL;
goto out;
}

/* Ensure this address is of the right type and is a valid
* destination.
*/

if (remote_addr->svm_cid == VMADDR_CID_ANY)
remote_addr->svm_cid = transport->get_local_cid();
remote_addr->svm_cid = vsk->transport->get_local_cid();

if (!vsock_addr_bound(remote_addr)) {
err = -EINVAL;
Expand All @@ -1136,7 +1138,7 @@ static int vsock_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
remote_addr = &vsk->remote_addr;

if (remote_addr->svm_cid == VMADDR_CID_ANY)
remote_addr->svm_cid = transport->get_local_cid();
remote_addr->svm_cid = vsk->transport->get_local_cid();

/* XXX Should connect() or this function ensure remote_addr is
* bound?
Expand All @@ -1150,13 +1152,13 @@ static int vsock_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
goto out;
}

if (!transport->dgram_allow(remote_addr->svm_cid,
if (!vsk->transport->dgram_allow(remote_addr->svm_cid,
remote_addr->svm_port)) {
err = -EINVAL;
goto out;
}

err = transport->dgram_enqueue(vsk, remote_addr, msg, len);
err = vsk->transport->dgram_enqueue(vsk, remote_addr, msg, len);

out:
release_sock(sk);
Expand Down Expand Up @@ -1191,13 +1193,20 @@ static int vsock_dgram_connect(struct socket *sock,
if (err)
goto out;

memcpy(&vsk->remote_addr, remote_addr, sizeof(vsk->remote_addr));

err = vsock_assign_transport(vsk, NULL);
if (err) {
err = -EINVAL;
goto out;
}

if (!vsk->transport->dgram_allow(remote_addr->svm_cid,
remote_addr->svm_port)) {
err = -EINVAL;
goto out;
}

memcpy(&vsk->remote_addr, remote_addr, sizeof(vsk->remote_addr));
sock->state = SS_CONNECTED;

out:
Expand All @@ -1209,6 +1218,16 @@ static int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
size_t len, int flags)
{
struct vsock_sock *vsk = vsock_sk(sock->sk);
long timeo;

timeo = sock_rcvtimeo(sock->sk, flags & MSG_DONTWAIT);
do {
if (vsk->transport)
break;
} while (timeo && !vsk->transport);

if (!vsk->transport)
return -EAGAIN;

return vsk->transport->dgram_dequeue(vsk, msg, len, flags);
}
Expand Down Expand Up @@ -2055,14 +2074,6 @@ static int vsock_create(struct net *net, struct socket *sock,

vsk = vsock_sk(sk);

if (sock->type == SOCK_DGRAM) {
ret = vsock_assign_transport(vsk, NULL);
if (ret < 0) {
sock_put(sk);
return ret;
}
}

vsock_insert_unbound(vsk);

return 0;
Expand Down Expand Up @@ -2182,15 +2193,14 @@ EXPORT_SYMBOL_GPL(vsock_core_get_transport);

int vsock_core_register(const struct vsock_transport *t, int features)
{
const struct vsock_transport *t_h2g, *t_g2h, *t_dgram, *t_local;
const struct vsock_transport *t_h2g, *t_g2h, *t_local;
int err = mutex_lock_interruptible(&vsock_register_mutex);

if (err)
return err;

t_h2g = transport_h2g;
t_g2h = transport_g2h;
t_dgram = transport_dgram;
t_local = transport_local;

if (features & VSOCK_TRANSPORT_F_H2G) {
Expand All @@ -2209,14 +2219,6 @@ int vsock_core_register(const struct vsock_transport *t, int features)
t_g2h = t;
}

if (features & VSOCK_TRANSPORT_F_DGRAM) {
if (t_dgram) {
err = -EBUSY;
goto err_busy;
}
t_dgram = t;
}

if (features & VSOCK_TRANSPORT_F_LOCAL) {
if (t_local) {
err = -EBUSY;
Expand All @@ -2227,7 +2229,6 @@ int vsock_core_register(const struct vsock_transport *t, int features)

transport_h2g = t_h2g;
transport_g2h = t_g2h;
transport_dgram = t_dgram;
transport_local = t_local;

err_busy:
Expand Down
20 changes: 13 additions & 7 deletions net/vmw_vsock/vmci_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg)
size_t size;
struct sk_buff *skb;
struct vsock_sock *vsk;
int err;

sk = (struct sock *)data;

Expand All @@ -629,6 +630,17 @@ static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg)
if (!vmci_transport_allow_dgram(vsk, dg->src.context))
return VMCI_ERROR_NO_ACCESS;

vsock_addr_init(&vsk->remote_addr, dg->src.context,
dg->src.resource);

bh_lock_sock(sk);
if (!sock_owned_by_user(sk)) {
err = vsock_assign_transport(vsk, NULL);
if (err)
return err;
}
bh_unlock_sock(sk);

size = VMCI_DG_SIZE(dg);

/* Attach the packet to the socket's receive queue as an sk_buff. */
Expand Down Expand Up @@ -2093,13 +2105,7 @@ static int __init vmci_transport_init(void)
goto err_destroy_stream_handle;
}

/* Register only with dgram feature, other features (H2G, G2H) will be
* registered when the first host or guest becomes active.
*/
err = vsock_core_register(&vmci_transport, VSOCK_TRANSPORT_F_DGRAM);
if (err < 0)
goto err_unsubscribe;

/* H2G, G2H will be registered when the first host or guest becomes active. */
err = vmci_register_vsock_callback(vmci_vsock_transport_cb);
if (err < 0)
goto err_unregister;
Expand Down

0 comments on commit 84be269

Please sign in to comment.