Skip to content

Commit 6b8350a

Browse files
committed
Merge branch 'vsock-add-local-transport-support'
Stefano Garzarella says: ==================== vsock: add local transport support v2: - style fixes [Dave] - removed RCU sync and changed 'the_vsock_loopback' in a global static variable [Stefan] - use G2H transport when local transport is not loaded and remote cid is VMADDR_CID_LOCAL [Stefan] - rebased on net-next v1: https://patchwork.kernel.org/cover/11251735/ This series introduces a new transport (vsock_loopback) to handle local communication. This could be useful to test vsock core itself and to allow developers to test their applications without launching a VM. Before this series, vmci and virtio transports allowed this behavior, but only in the guest. We are moving the loopback handling in a new transport, because it might be useful to provide this feature also in the host or when no H2G/G2H transports (hyperv, virtio, vmci) are loaded. The user can use the loopback with the new VMADDR_CID_LOCAL (that replaces VMADDR_CID_RESERVED) in any condition. Otherwise, if the G2H transport is loaded, it can also use the guest local CID as previously supported by vmci and virtio transports. If G2H transport is not loaded, the user can also use VMADDR_CID_HOST for local communication. Patch 1 is a cleanup to build virtio_transport_common without virtio Patch 2 adds the new VMADDR_CID_LOCAL, replacing VMADDR_CID_RESERVED Patch 3 adds a new feature flag to register a loopback transport Patch 4 adds the new vsock_loopback transport based on the loopback implementation of virtio_transport Patch 5 implements the logic to use the local transport for loopback communication Patch 6 removes the loopback from virtio_transport ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents bea0f4a + bf5432b commit 6b8350a

File tree

10 files changed

+243
-72
lines changed

10 files changed

+243
-72
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17480,6 +17480,7 @@ F: net/vmw_vsock/diag.c
1748017480
F: net/vmw_vsock/af_vsock_tap.c
1748117481
F: net/vmw_vsock/virtio_transport_common.c
1748217482
F: net/vmw_vsock/virtio_transport.c
17483+
F: net/vmw_vsock/vsock_loopback.c
1748317484
F: drivers/net/vsockmon.c
1748417485
F: drivers/vhost/vsock.c
1748517486
F: tools/testing/vsock/

include/net/af_vsock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ struct vsock_transport_send_notify_data {
9898
#define VSOCK_TRANSPORT_F_G2H 0x00000002
9999
/* Transport provides DGRAM communication */
100100
#define VSOCK_TRANSPORT_F_DGRAM 0x00000004
101+
/* Transport provides local (loopback) communication */
102+
#define VSOCK_TRANSPORT_F_LOCAL 0x00000008
101103

102104
struct vsock_transport {
103105
struct module *module;

include/uapi/linux/vm_sockets.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,13 @@
9999

100100
#define VMADDR_CID_HYPERVISOR 0
101101

102-
/* This CID is specific to VMCI and can be considered reserved (even VMCI
103-
* doesn't use it anymore, it's a legacy value from an older release).
102+
/* Use this as the destination CID in an address when referring to the
103+
* local communication (loopback).
104+
* (This was VMADDR_CID_RESERVED, but even VMCI doesn't use it anymore,
105+
* it was a legacy value from an older release).
104106
*/
105107

106-
#define VMADDR_CID_RESERVED 1
108+
#define VMADDR_CID_LOCAL 1
107109

108110
/* Use this as the destination CID in an address when referring to the host
109111
* (any process other than the hypervisor). VMCI relies on it being 2, but

net/vmw_vsock/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ config VSOCKETS_DIAG
2626

2727
Enable this module so userspace applications can query open sockets.
2828

29+
config VSOCKETS_LOOPBACK
30+
tristate "Virtual Sockets loopback transport"
31+
depends on VSOCKETS
32+
default y
33+
select VIRTIO_VSOCKETS_COMMON
34+
help
35+
This module implements a loopback transport for Virtual Sockets,
36+
using vmw_vsock_virtio_transport_common.
37+
38+
To compile this driver as a module, choose M here: the module
39+
will be called vsock_loopback. If unsure, say N.
40+
2941
config VMWARE_VMCI_VSOCKETS
3042
tristate "VMware VMCI transport for Virtual Sockets"
3143
depends on VSOCKETS && VMWARE_VMCI

net/vmw_vsock/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ obj-$(CONFIG_VMWARE_VMCI_VSOCKETS) += vmw_vsock_vmci_transport.o
55
obj-$(CONFIG_VIRTIO_VSOCKETS) += vmw_vsock_virtio_transport.o
66
obj-$(CONFIG_VIRTIO_VSOCKETS_COMMON) += vmw_vsock_virtio_transport_common.o
77
obj-$(CONFIG_HYPERV_VSOCKETS) += hv_sock.o
8+
obj-$(CONFIG_VSOCKETS_LOOPBACK) += vsock_loopback.o
89

910
vsock-y += af_vsock.o af_vsock_tap.o vsock_addr.o
1011

net/vmw_vsock/af_vsock.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ static const struct vsock_transport *transport_h2g;
136136
static const struct vsock_transport *transport_g2h;
137137
/* Transport used for DGRAM communication */
138138
static const struct vsock_transport *transport_dgram;
139+
/* Transport used for local communication */
140+
static const struct vsock_transport *transport_local;
139141
static DEFINE_MUTEX(vsock_register_mutex);
140142

141143
/**** UTILS ****/
@@ -386,6 +388,21 @@ void vsock_enqueue_accept(struct sock *listener, struct sock *connected)
386388
}
387389
EXPORT_SYMBOL_GPL(vsock_enqueue_accept);
388390

391+
static bool vsock_use_local_transport(unsigned int remote_cid)
392+
{
393+
if (!transport_local)
394+
return false;
395+
396+
if (remote_cid == VMADDR_CID_LOCAL)
397+
return true;
398+
399+
if (transport_g2h) {
400+
return remote_cid == transport_g2h->get_local_cid();
401+
} else {
402+
return remote_cid == VMADDR_CID_HOST;
403+
}
404+
}
405+
389406
static void vsock_deassign_transport(struct vsock_sock *vsk)
390407
{
391408
if (!vsk->transport)
@@ -402,9 +419,9 @@ static void vsock_deassign_transport(struct vsock_sock *vsk)
402419
* (e.g. during the connect() or when a connection request on a listener
403420
* socket is received).
404421
* The vsk->remote_addr is used to decide which transport to use:
422+
* - remote CID == VMADDR_CID_LOCAL or g2h->local_cid or VMADDR_CID_HOST if
423+
* g2h is not loaded, will use local transport;
405424
* - remote CID <= VMADDR_CID_HOST will use guest->host transport;
406-
* - remote CID == local_cid (guest->host transport) will use guest->host
407-
* transport for loopback (host->guest transports don't support loopback);
408425
* - remote CID > VMADDR_CID_HOST will use host->guest transport;
409426
*/
410427
int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
@@ -419,9 +436,9 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
419436
new_transport = transport_dgram;
420437
break;
421438
case SOCK_STREAM:
422-
if (remote_cid <= VMADDR_CID_HOST ||
423-
(transport_g2h &&
424-
remote_cid == transport_g2h->get_local_cid()))
439+
if (vsock_use_local_transport(remote_cid))
440+
new_transport = transport_local;
441+
else if (remote_cid <= VMADDR_CID_HOST)
425442
new_transport = transport_g2h;
426443
else
427444
new_transport = transport_h2g;
@@ -464,6 +481,9 @@ bool vsock_find_cid(unsigned int cid)
464481
if (transport_h2g && cid == VMADDR_CID_HOST)
465482
return true;
466483

484+
if (transport_local && cid == VMADDR_CID_LOCAL)
485+
return true;
486+
467487
return false;
468488
}
469489
EXPORT_SYMBOL_GPL(vsock_find_cid);
@@ -2137,7 +2157,7 @@ EXPORT_SYMBOL_GPL(vsock_core_get_transport);
21372157

21382158
int vsock_core_register(const struct vsock_transport *t, int features)
21392159
{
2140-
const struct vsock_transport *t_h2g, *t_g2h, *t_dgram;
2160+
const struct vsock_transport *t_h2g, *t_g2h, *t_dgram, *t_local;
21412161
int err = mutex_lock_interruptible(&vsock_register_mutex);
21422162

21432163
if (err)
@@ -2146,6 +2166,7 @@ int vsock_core_register(const struct vsock_transport *t, int features)
21462166
t_h2g = transport_h2g;
21472167
t_g2h = transport_g2h;
21482168
t_dgram = transport_dgram;
2169+
t_local = transport_local;
21492170

21502171
if (features & VSOCK_TRANSPORT_F_H2G) {
21512172
if (t_h2g) {
@@ -2171,9 +2192,18 @@ int vsock_core_register(const struct vsock_transport *t, int features)
21712192
t_dgram = t;
21722193
}
21732194

2195+
if (features & VSOCK_TRANSPORT_F_LOCAL) {
2196+
if (t_local) {
2197+
err = -EBUSY;
2198+
goto err_busy;
2199+
}
2200+
t_local = t;
2201+
}
2202+
21742203
transport_h2g = t_h2g;
21752204
transport_g2h = t_g2h;
21762205
transport_dgram = t_dgram;
2206+
transport_local = t_local;
21772207

21782208
err_busy:
21792209
mutex_unlock(&vsock_register_mutex);
@@ -2194,6 +2224,9 @@ void vsock_core_unregister(const struct vsock_transport *t)
21942224
if (transport_dgram == t)
21952225
transport_dgram = NULL;
21962226

2227+
if (transport_local == t)
2228+
transport_local = NULL;
2229+
21972230
mutex_unlock(&vsock_register_mutex);
21982231
}
21992232
EXPORT_SYMBOL_GPL(vsock_core_unregister);

net/vmw_vsock/virtio_transport.c

Lines changed: 2 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@ struct virtio_vsock {
4444
spinlock_t send_pkt_list_lock;
4545
struct list_head send_pkt_list;
4646

47-
struct work_struct loopback_work;
48-
spinlock_t loopback_list_lock; /* protects loopback_list */
49-
struct list_head loopback_list;
50-
5147
atomic_t queued_replies;
5248

5349
/* The following fields are protected by rx_lock. vqs[VSOCK_VQ_RX]
@@ -86,20 +82,6 @@ static u32 virtio_transport_get_local_cid(void)
8682
return ret;
8783
}
8884

89-
static int virtio_transport_send_pkt_loopback(struct virtio_vsock *vsock,
90-
struct virtio_vsock_pkt *pkt)
91-
{
92-
int len = pkt->len;
93-
94-
spin_lock_bh(&vsock->loopback_list_lock);
95-
list_add_tail(&pkt->list, &vsock->loopback_list);
96-
spin_unlock_bh(&vsock->loopback_list_lock);
97-
98-
queue_work(virtio_vsock_workqueue, &vsock->loopback_work);
99-
100-
return len;
101-
}
102-
10385
static void
10486
virtio_transport_send_pkt_work(struct work_struct *work)
10587
{
@@ -194,7 +176,8 @@ virtio_transport_send_pkt(struct virtio_vsock_pkt *pkt)
194176
}
195177

196178
if (le64_to_cpu(pkt->hdr.dst_cid) == vsock->guest_cid) {
197-
len = virtio_transport_send_pkt_loopback(vsock, pkt);
179+
virtio_transport_free_pkt(pkt);
180+
len = -ENODEV;
198181
goto out_rcu;
199182
}
200183

@@ -502,33 +485,6 @@ static struct virtio_transport virtio_transport = {
502485
.send_pkt = virtio_transport_send_pkt,
503486
};
504487

505-
static void virtio_transport_loopback_work(struct work_struct *work)
506-
{
507-
struct virtio_vsock *vsock =
508-
container_of(work, struct virtio_vsock, loopback_work);
509-
LIST_HEAD(pkts);
510-
511-
spin_lock_bh(&vsock->loopback_list_lock);
512-
list_splice_init(&vsock->loopback_list, &pkts);
513-
spin_unlock_bh(&vsock->loopback_list_lock);
514-
515-
mutex_lock(&vsock->rx_lock);
516-
517-
if (!vsock->rx_run)
518-
goto out;
519-
520-
while (!list_empty(&pkts)) {
521-
struct virtio_vsock_pkt *pkt;
522-
523-
pkt = list_first_entry(&pkts, struct virtio_vsock_pkt, list);
524-
list_del_init(&pkt->list);
525-
526-
virtio_transport_recv_pkt(&virtio_transport, pkt);
527-
}
528-
out:
529-
mutex_unlock(&vsock->rx_lock);
530-
}
531-
532488
static void virtio_transport_rx_work(struct work_struct *work)
533489
{
534490
struct virtio_vsock *vsock =
@@ -633,13 +589,10 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
633589
mutex_init(&vsock->event_lock);
634590
spin_lock_init(&vsock->send_pkt_list_lock);
635591
INIT_LIST_HEAD(&vsock->send_pkt_list);
636-
spin_lock_init(&vsock->loopback_list_lock);
637-
INIT_LIST_HEAD(&vsock->loopback_list);
638592
INIT_WORK(&vsock->rx_work, virtio_transport_rx_work);
639593
INIT_WORK(&vsock->tx_work, virtio_transport_tx_work);
640594
INIT_WORK(&vsock->event_work, virtio_transport_event_work);
641595
INIT_WORK(&vsock->send_pkt_work, virtio_transport_send_pkt_work);
642-
INIT_WORK(&vsock->loopback_work, virtio_transport_loopback_work);
643596

644597
mutex_lock(&vsock->tx_lock);
645598
vsock->tx_run = true;
@@ -720,22 +673,12 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
720673
}
721674
spin_unlock_bh(&vsock->send_pkt_list_lock);
722675

723-
spin_lock_bh(&vsock->loopback_list_lock);
724-
while (!list_empty(&vsock->loopback_list)) {
725-
pkt = list_first_entry(&vsock->loopback_list,
726-
struct virtio_vsock_pkt, list);
727-
list_del(&pkt->list);
728-
virtio_transport_free_pkt(pkt);
729-
}
730-
spin_unlock_bh(&vsock->loopback_list_lock);
731-
732676
/* Delete virtqueues and flush outstanding callbacks if any */
733677
vdev->config->del_vqs(vdev);
734678

735679
/* Other works can be queued before 'config->del_vqs()', so we flush
736680
* all works before to free the vsock object to avoid use after free.
737681
*/
738-
flush_work(&vsock->loopback_work);
739682
flush_work(&vsock->rx_work);
740683
flush_work(&vsock->tx_work);
741684
flush_work(&vsock->event_work);

net/vmw_vsock/virtio_transport_common.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111
#include <linux/sched/signal.h>
1212
#include <linux/ctype.h>
1313
#include <linux/list.h>
14-
#include <linux/virtio.h>
15-
#include <linux/virtio_ids.h>
16-
#include <linux/virtio_config.h>
1714
#include <linux/virtio_vsock.h>
1815
#include <uapi/linux/vsockmon.h>
1916

net/vmw_vsock/vmci_transport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg)
648648
static bool vmci_transport_stream_allow(u32 cid, u32 port)
649649
{
650650
static const u32 non_socket_contexts[] = {
651-
VMADDR_CID_RESERVED,
651+
VMADDR_CID_LOCAL,
652652
};
653653
int i;
654654

0 commit comments

Comments
 (0)