With new enough libnbd, we already support vsock by virtue of uri=;
however, it's also nice to allow direct exposure of the
nbd_connect_vsock() api.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
As with commit 7ce9feef, there is no easy way to add testsuite
coverage for this.
plugins/nbd/nbdkit-nbd-plugin.pod | 30 +++++++++-----
plugins/nbd/nbd.c | 65 ++++++++++++++++++++++++-------
2 files changed, 72 insertions(+), 23 deletions(-)
diff --git a/plugins/nbd/nbdkit-nbd-plugin.pod b/plugins/nbd/nbdkit-nbd-plugin.pod
index 618058ac..151590d2 100644
--- a/plugins/nbd/nbdkit-nbd-plugin.pod
+++ b/plugins/nbd/nbdkit-nbd-plugin.pod
@@ -4,9 +4,9 @@ nbdkit-nbd-plugin - nbdkit nbd plugin
=head1 SYNOPSIS
- nbdkit nbd { socket=SOCKNAME | hostname=HOST [port=PORT] | [uri=]URI }
- [export=NAME] [retry=N] [shared=BOOL] [tls=MODE] [tls-certificates=DIR]
- [tls-verify=BOOL] [tls-username=NAME] [tls-psk=FILE]
+ nbdkit nbd { socket=SOCKNAME | { hostname=HOST | vsock_cid=CID } [port=PORT] |
+ [uri=]URI } [export=NAME] [retry=N] [shared=BOOL] [tls=MODE]
+ [tls-certificates=DIR] [tls-verify=BOOL] [tls-username=NAME] [tls-psk=FILE]
=head1 DESCRIPTION
@@ -27,8 +27,8 @@ TCP and use plaintext only on a Unix socket.
=head1 PARAMETERS
-One of B<socket>, B<hostname> or B<uri> must be provided to designate
-the server. The server can speak either new or old style
+One of B<socket>, B<hostname>, B<vsock_cid> or B<uri> must be
provided
+to designate the server. The server can speak either new or old style
protocol. C<uri=> is a magic config key and may be omitted in most
cases. See L<nbdkit(1)/Magic parameters>.
@@ -47,8 +47,10 @@ Connect to the NBD server at the given remote C<HOST> using a TCP
socket.
=item B<port=>PORT
-When B<hostname> is supplied, use B<PORT> instead of the default port
-10809.
+When B<hostname> or B<vsock_cid> is supplied, use B<PORT> instead of
+the default port 10809. For TCP, the port may be a 16-bit number or a
+non-numeric string used to look up the well-known port for a service
+name; for VSOCK, the port must be a 32-bit number.
=item B<export=>NAME
@@ -84,13 +86,23 @@ against libnbd:
When B<uri> is supplied, decode B<URI> to determine the address to
connect to. A URI can specify a TCP connection (such as
-C<nbd://localhost:10809/export>) or a Unix socket (such as
-C<nbd+unix:///export?socket=/path/to/sock>). Remember to use proper
+C<nbd://localhost:10809/export>), a Unix socket (such as
+C<nbd+unix:///export?socket=/path/to/sock>), or a vsock connection
+(such as C<nbd+vsock:///2:10809/export>). Remember to use proper
shell quoting to prevent B<URI> from accidentally being handled as a
shell glob. The B<uri> parameter is only available when the plugin was
compiled against libnbd with URI support; C<nbdkit --dump-plugin nbd>
will contain C<libnbd_uri=1> if this is the case.
+=item B<vsock_cid=>CID
+
+Connect to the NBD server at the given vsock cid (for example, in a
+guest VM, using the cid 2 will connect to a server in the host). This
+only works for platforms with the C<AF_VSOCK> family of sockets and
+libnbd new enough to use it; C<nbdkit --dump-plugin nbd> will contain
+C<libnbd_vsock=1> if this is the case. For more details on AF_VSOCK,
+see L<nbdkit-service(1)/AF_VSOCK>.
+
=item B<tls=>MODE
Selects which TLS mode to use with the server. If no other tls option
diff --git a/plugins/nbd/nbd.c b/plugins/nbd/nbd.c
index d020beec..0bb5ff9f 100644
--- a/plugins/nbd/nbd.c
+++ b/plugins/nbd/nbd.c
@@ -46,6 +46,7 @@
#include <semaphore.h>
#include <poll.h>
#include <fcntl.h>
+#include <sys/socket.h>
#include <libnbd.h>
@@ -56,6 +57,12 @@
#include "cleanup.h"
#include "utils.h"
+#if !defined AF_VSOCK || !LIBNBD_HAVE_NBD_CONNECT_VSOCK
+#define USE_VSOCK 0
+#else
+#define USE_VSOCK 1
+#endif
+
/* The per-transaction details */
struct transaction {
int64_t cookie;
@@ -80,8 +87,15 @@ static char *sockname;
/* Connect to server via TCP socket */
static const char *hostname;
+
+/* Valid with TCP or VSOCK */
static const char *port;
+/* Connect to server via AF_VSOCK socket */
+static const char *raw_cid;
+static uint32_t cid;
+static uint32_t vport;
+
/* Connect to server via URI */
static const char *uri;
@@ -116,10 +130,10 @@ nbdplug_unload (void)
}
/* Called for each key=value passed on the command line. This plugin
- * accepts socket=<sockname>, hostname=<hostname>/port=<port>, or
- * [uri=]<uri> (exactly one connection required), and optional
- * parameters export=<name>, retry=<n>, shared=<bool> and various
- * tls settings.
+ * accepts socket=<sockname>, hostname=<hostname>/port=<port>,
+ * vsock_cid=<cid>/port=<port>, or [uri=]<uri> (exactly one connection
+ * required), and optional parameters export=<name>, retry=<n>,
+ * shared=<bool> and various tls settings.
*/
static int
nbdplug_config (const char *key, const char *value)
@@ -137,6 +151,10 @@ nbdplug_config (const char *key, const char *value)
hostname = value;
else if (strcmp (key, "port") == 0)
port = value;
+ else if (strcmp (key, "vsock_cid") == 0 ||
+ strcmp (key, "vsock-cid") == 0 ||
+ strcmp (key, "cid") == 0)
+ raw_cid = value;
else if (strcmp (key, "uri") == 0)
uri = value;
else if (strcmp (key, "export") == 0)
@@ -198,12 +216,8 @@ nbdplug_config_complete (void)
if (sockname) {
struct sockaddr_un sock;
- if (hostname || port) {
- nbdkit_error ("cannot mix Unix socket and TCP hostname/port
parameters");
- return -1;
- }
- else if (uri) {
- nbdkit_error ("cannot mix Unix socket and URI parameters");
+ if (hostname || port || raw_cid || uri) {
+ nbdkit_error ("cannot mix Unix socket with other transport parameters");
return -1;
}
if (strlen (sockname) > sizeof sock.sun_path) {
@@ -212,13 +226,27 @@ nbdplug_config_complete (void)
}
}
else if (hostname) {
- if (uri) {
- nbdkit_error ("cannot mix TCP hostname/port and URI parameters");
+ if (uri || raw_cid) {
+ nbdkit_error ("cannot mix TCP hostname with other transport
parameters");
return -1;
}
if (!port)
port = "10809";
}
+ else if (raw_cid) {
+#if !USE_VSOCK
+ nbdkit_error ("libnbd was compiled without vsock support");
+ return -1;
+#else
+ if (uri) {
+ nbdkit_error ("cannot mix VSOCK with other transport parameters");
+ return -1;
+ }
+ if (nbdkit_parse_uint32_t ("vsock_cid", raw_cid, &cid) == -1 ||
+ nbdkit_parse_uint32_t ("port", port, &vport) == -1)
+ return -1;
+#endif
+ }
else if (uri) {
struct nbd_handle *nbd = nbd_create ();
@@ -237,7 +265,8 @@ nbdplug_config_complete (void)
}
nbd_close (nbd);
} else {
- nbdkit_error ("must supply socket=, hostname= or uri= of external NBD
server");
+ nbdkit_error ("must supply socket=, hostname=, vsock_cid= or uri= of "
+ "external NBD server");
return -1;
}
@@ -271,7 +300,8 @@ nbdplug_config_complete (void)
"[uri=]<URI> URI of an NBD socket to connect to (if
supported).\n" \
"socket=<SOCKNAME> The Unix socket to connect to.\n" \
"hostname=<HOST> The hostname for the TCP socket to connect
to.\n" \
- "port=<PORT> TCP port or service name to use (default
10809).\n" \
+ "vhost_cid=<CID> The cid for the VSOCK socket to connect to.\n"
\
+ "port=<PORT> TCP/VHOST port or service name to use (default
10809).\n" \
"export=<NAME> Export name to connect to (default
\"\").\n" \
"retry=<N> Retry connection up to N seconds (default
0).\n" \
"shared=<BOOL> True to share one server connection among all
clients,\n" \
@@ -294,6 +324,7 @@ nbdplug_dump_plugin (void)
printf ("libnbd_version=%s\n", nbd_get_version (nbd));
printf ("libnbd_tls=%d\n", nbd_supports_tls (nbd));
printf ("libnbd_uri=%d\n", nbd_supports_uri (nbd));
+ printf ("libnbd_vsock=%d\n", USE_VSOCK);
nbd_close (nbd);
}
@@ -484,6 +515,12 @@ nbdplug_open_handle (int readonly)
r = nbd_connect_uri (h->nbd, uri);
else if (sockname)
r = nbd_connect_unix (h->nbd, sockname);
+ else if (raw_cid)
+#if !USE_VSOCK
+ abort ();
+#else
+ r = nbd_connect_vsock (h->nbd, cid, vport);
+#endif
else
r = nbd_connect_tcp (h->nbd, hostname, port);
if (r == -1) {
--
2.21.0