vsock: use local transport when it is loaded
authorStefano Garzarella <sgarzare@redhat.com>
Tue, 10 Dec 2019 10:43:06 +0000 (11:43 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 11 Dec 2019 23:01:23 +0000 (15:01 -0800)
Now that we have a transport that can handle the local communication,
we can use it when it is loaded.

A socket will use the local transport (loopback) when the remote
CID is:
- equal to VMADDR_CID_LOCAL
- or equal to transport_g2h->get_local_cid(), if transport_g2h
  is loaded (this allows us to keep the same behavior implemented
  by virtio and vmci transports)
- or equal to VMADDR_CID_HOST, if transport_g2h is not loaded

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/vmw_vsock/af_vsock.c

index 3da0749a0c9774c23d82c77c9de978726af054bc..9c5b2a91baad60945cd06881c57d1b0c56810a58 100644 (file)
@@ -388,6 +388,21 @@ void vsock_enqueue_accept(struct sock *listener, struct sock *connected)
 }
 EXPORT_SYMBOL_GPL(vsock_enqueue_accept);
 
+static bool vsock_use_local_transport(unsigned int remote_cid)
+{
+       if (!transport_local)
+               return false;
+
+       if (remote_cid == VMADDR_CID_LOCAL)
+               return true;
+
+       if (transport_g2h) {
+               return remote_cid == transport_g2h->get_local_cid();
+       } else {
+               return remote_cid == VMADDR_CID_HOST;
+       }
+}
+
 static void vsock_deassign_transport(struct vsock_sock *vsk)
 {
        if (!vsk->transport)
@@ -404,9 +419,9 @@ static void vsock_deassign_transport(struct vsock_sock *vsk)
  * (e.g. during the connect() or when a connection request on a listener
  * socket is received).
  * The vsk->remote_addr is used to decide which transport to use:
+ *  - remote CID == VMADDR_CID_LOCAL or g2h->local_cid or VMADDR_CID_HOST if
+ *    g2h is not loaded, will use local transport;
  *  - remote CID <= VMADDR_CID_HOST will use guest->host transport;
- *  - remote CID == local_cid (guest->host transport) will use guest->host
- *    transport for loopback (host->guest transports don't support loopback);
  *  - remote CID > VMADDR_CID_HOST will use host->guest transport;
  */
 int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
@@ -421,9 +436,9 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
                new_transport = transport_dgram;
                break;
        case SOCK_STREAM:
-               if (remote_cid <= VMADDR_CID_HOST ||
-                   (transport_g2h &&
-                    remote_cid == transport_g2h->get_local_cid()))
+               if (vsock_use_local_transport(remote_cid))
+                       new_transport = transport_local;
+               else if (remote_cid <= VMADDR_CID_HOST)
                        new_transport = transport_g2h;
                else
                        new_transport = transport_h2g;
@@ -466,6 +481,9 @@ bool vsock_find_cid(unsigned int cid)
        if (transport_h2g && cid == VMADDR_CID_HOST)
                return true;
 
+       if (transport_local && cid == VMADDR_CID_LOCAL)
+               return true;
+
        return false;
 }
 EXPORT_SYMBOL_GPL(vsock_find_cid);