Skip to content

Commit 51d3b56

Browse files
committed
krun: implement support for passt networking
Introduce a new configuration flag (krun.use_passt) that enables users to request the microVM to use passt based networking instead of TSI. Right now, the container needs to configure the network by itself, but the next version of libkrun will embed a DHCP client in init.c Signed-off-by: Sergio Lopez <slp@redhat.com>
1 parent 675d096 commit 51d3b56

1 file changed

Lines changed: 118 additions & 1 deletion

File tree

src/libcrun/handlers/krun.c

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "../linux.h"
2525
#include <unistd.h>
2626
#include <sys/stat.h>
27+
#include <sys/socket.h>
2728
#include <errno.h>
2829
#include <sys/param.h>
2930
#include <sys/types.h>
@@ -68,6 +69,9 @@
6869
#define KRUN_FLAVOR_AWS_NITRO "aws-nitro"
6970
#define KRUN_FLAVOR_SEV "sev"
7071

72+
#define PASST_FD_PARENT 0
73+
#define PASST_FD_CHILD 1
74+
7175
struct krun_config
7276
{
7377
void *handle;
@@ -80,6 +84,7 @@ struct krun_config
8084
int32_t ctx_id_awsnitro;
8185
bool has_kvm;
8286
bool has_awsnitro;
87+
int passt_fds[2];
8388
yajl_val config_tree;
8489
bool use_passt;
8590
};
@@ -221,7 +226,7 @@ libkrun_parse_resource_configuration (yajl_val *config_tree, libcrun_container_t
221226
/* Annotations value is not a valid integer. */
222227
error (EXIT_FAILURE, 0, "krun annotation %s value cannot be converted to an integer", annotation);
223228

224-
if (val <= 0)
229+
if (val < 0)
225230
error (EXIT_FAILURE, 0, "krun annotation %s value must be a positive integer", annotation);
226231

227232
return val;
@@ -244,6 +249,7 @@ libkrun_configure_vm (uint32_t ctx_id, void *handle, struct krun_config *kconf,
244249
{
245250
runtime_spec_schema_config_schema *def = container->container_def;
246251
int32_t (*krun_set_vm_config) (uint32_t ctx_id, uint8_t num_vcpus, uint32_t ram_mib);
252+
int32_t (*krun_add_net_unixstream) (uint32_t ctx_id, const char *c_path, int fd, uint8_t *const c_mac, uint32_t features, uint32_t flags);
247253
int cpus, ram_mib, gpu_flags, ret;
248254
cpu_set_t set;
249255
const char *path_cpus[] = { "cpus", (const char *) 0 };
@@ -293,6 +299,16 @@ libkrun_configure_vm (uint32_t ctx_id, void *handle, struct krun_config *kconf,
293299
return crun_make_error (err, -ret, "could not enable virtio gpu");
294300
}
295301

302+
if (kconf->use_passt)
303+
{
304+
krun_add_net_unixstream = dlsym (handle, "krun_add_net_unixstream");
305+
306+
uint8_t mac[] = { 0x5a, 0x94, 0xef, 0xe4, 0x0c, 0xee };
307+
ret = krun_add_net_unixstream (ctx_id, NULL, kconf->passt_fds[PASST_FD_PARENT], &mac[0], COMPAT_NET_FEATURES, 0);
308+
if (UNLIKELY (ret < 0))
309+
error (EXIT_FAILURE, -ret, "could not set krun net configuration");
310+
}
311+
296312
if (kconf->config_tree != NULL)
297313
{
298314
/* Try to configure an external kernel. If the configuration file doesn't
@@ -502,6 +518,73 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
502518
return ret;
503519
}
504520

521+
static int
522+
libkrun_start_passt (void *cookie, libcrun_container_t *container)
523+
{
524+
struct krun_config *kconf = (struct krun_config *) cookie;
525+
const char *path_use_passt[] = { "use_passt", (const char *) 0 };
526+
pid_t pid;
527+
char fd_as_str[16];
528+
int use_passt;
529+
int status;
530+
int null;
531+
int ret;
532+
533+
use_passt = libkrun_parse_resource_configuration (&kconf->config_tree, container, "krun.use_passt", path_use_passt);
534+
if (use_passt > 0)
535+
kconf->use_passt = 1;
536+
else
537+
return 0;
538+
539+
ret = socketpair (AF_UNIX, SOCK_STREAM, 0, kconf->passt_fds);
540+
if (UNLIKELY (ret < 0))
541+
return ret;
542+
snprintf (fd_as_str, sizeof (fd_as_str), "%d", kconf->passt_fds[PASST_FD_CHILD]);
543+
544+
char *const argv[] = {
545+
(char *) "passt",
546+
(char *) "--no-dhcp-dns",
547+
(char *) "-t",
548+
(char *) "all",
549+
(char *) "-u",
550+
(char *) "all",
551+
(char *) "--fd",
552+
fd_as_str,
553+
NULL
554+
};
555+
556+
pid = fork ();
557+
if (pid < 0)
558+
return pid;
559+
else if (pid == 0)
560+
{
561+
close (kconf->passt_fds[PASST_FD_PARENT]);
562+
563+
null = open ("/dev/null", O_WRONLY);
564+
if (null == -1)
565+
_exit (EXIT_FAILURE);
566+
567+
// Redirect passt's stdout and stderr to /dev/null, as closing them here
568+
// instead will cause passt to exit with an error.
569+
dup2 (null, STDOUT_FILENO);
570+
dup2 (null, STDERR_FILENO);
571+
close (null);
572+
573+
execvp ("passt", argv);
574+
// Only reachable on error.
575+
_exit (EXIT_FAILURE);
576+
}
577+
578+
close (kconf->passt_fds[PASST_FD_CHILD]);
579+
580+
// Wait for passt to daemonize itself.
581+
waitpid (pid, &status, 0);
582+
if (! (WIFEXITED (status)) || WEXITSTATUS (status) != 0)
583+
return -1;
584+
585+
return 0;
586+
}
587+
505588
/* libkrun_create_kvm_device: explicitly adds kvm device. */
506589
static int
507590
libkrun_configure_container (void *cookie, enum handler_configure_phase phase,
@@ -567,6 +650,10 @@ libkrun_configure_container (void *cookie, enum handler_configure_phase phase,
567650
if (phase != HANDLER_CONFIGURE_AFTER_MOUNTS)
568651
return 0;
569652

653+
ret = libkrun_start_passt (cookie, container);
654+
if (UNLIKELY (ret < 0))
655+
return crun_make_error (err, errno, "start passt");
656+
570657
/* Do nothing if /dev/kvm is already present in spec */
571658
for (i = 0; i < def->linux->devices_len; i++)
572659
{
@@ -838,6 +925,35 @@ libkrun_modify_oci_configuration (void *cookie arg_unused, libcrun_context_t *co
838925
return 0;
839926
}
840927

928+
static int
929+
libkrun_close_fds (void *cookie, libcrun_container_t *container, int preserve_fds, libcrun_error_t *err)
930+
{
931+
struct krun_config *kconf = (struct krun_config *) cookie;
932+
int first_fd_to_close = preserve_fds + 3;
933+
int passt_fd;
934+
int i;
935+
936+
if (kconf->use_passt)
937+
{
938+
passt_fd = kconf->passt_fds[PASST_FD_PARENT];
939+
940+
if (first_fd_to_close <= passt_fd)
941+
{
942+
for (i = first_fd_to_close; i < passt_fd; i++)
943+
{
944+
// If we're closing proc_fd, make sure to invalidate it.
945+
if (i == container->proc_fd)
946+
container->proc_fd = -1;
947+
close (i);
948+
}
949+
950+
first_fd_to_close = passt_fd + 1;
951+
}
952+
}
953+
954+
return mark_or_close_fds_ge_than (container, first_fd_to_close, true, err);
955+
}
956+
841957
struct custom_handler_s handler_libkrun = {
842958
.name = "krun",
843959
.alias = NULL,
@@ -847,6 +963,7 @@ struct custom_handler_s handler_libkrun = {
847963
.run_func = libkrun_exec,
848964
.configure_container = libkrun_configure_container,
849965
.modify_oci_configuration = libkrun_modify_oci_configuration,
966+
.close_fds = libkrun_close_fds,
850967
};
851968

852969
#endif

0 commit comments

Comments
 (0)