mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
tun: Restore tun files and tun links
This thing is pretty straightforward -- on netns creation populate it with tun-s, after this collect tun files, open and attach them with regular fd-s engine. One tricky thing -- when populating namespace with tun links make them all persistent and drop this flag (if required) later, when the first alive opened appears. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
@@ -62,6 +62,7 @@
|
||||
#include "sysctl.h"
|
||||
#include "vdso.h"
|
||||
#include "stats.h"
|
||||
#include "tun.h"
|
||||
|
||||
#include "protobuf.h"
|
||||
#include "protobuf/sa.pb-c.h"
|
||||
@@ -129,6 +130,7 @@ static struct collect_image_info *cinfos[] = {
|
||||
&fanotify_mark_cinfo,
|
||||
&tty_info_cinfo,
|
||||
&tty_cinfo,
|
||||
&tunfile_cinfo,
|
||||
};
|
||||
|
||||
static int root_prepare_shared(void)
|
||||
|
@@ -8,4 +8,6 @@
|
||||
|
||||
extern const struct fdtype_ops tunfile_dump_ops;
|
||||
int dump_tun_link(NetDeviceEntry *nde, struct cr_fdset *fds);
|
||||
int restore_one_tun(NetDeviceEntry *nde, int nlsk);
|
||||
extern struct collect_image_info tunfile_cinfo;
|
||||
#endif
|
||||
|
2
net.c
2
net.c
@@ -321,6 +321,8 @@ static int restore_link(NetDeviceEntry *nde, int nlsk)
|
||||
return restore_one_link(nde, nlsk, NULL);
|
||||
case ND_TYPE__VETH:
|
||||
return restore_one_link(nde, nlsk, veth_link_info);
|
||||
case ND_TYPE__TUN:
|
||||
return restore_one_tun(nde, nlsk);
|
||||
default:
|
||||
pr_err("Unsupported link type %d\n", nde->type);
|
||||
break;
|
||||
|
170
tun.c
170
tun.c
@@ -50,6 +50,10 @@ struct tun_link {
|
||||
char name[IFNAMSIZ];
|
||||
struct list_head l;
|
||||
union {
|
||||
struct {
|
||||
unsigned flags;
|
||||
} rst;
|
||||
|
||||
struct {
|
||||
unsigned sndbuf;
|
||||
unsigned vnethdr;
|
||||
@@ -57,6 +61,26 @@ struct tun_link {
|
||||
};
|
||||
};
|
||||
|
||||
static int list_tun_link(NetDeviceEntry *nde)
|
||||
{
|
||||
struct tun_link *tl;
|
||||
|
||||
tl = xmalloc(sizeof(*tl));
|
||||
if (!tl)
|
||||
return -1;
|
||||
|
||||
strcpy(tl->name, nde->name);
|
||||
/*
|
||||
* Keep tun-flags not only for persistency fixup (see
|
||||
* commend below), but also for TUNSETIFF -- we must
|
||||
* open the device with the same flags it should live
|
||||
* with (i.e. -- with which it was created.
|
||||
*/
|
||||
tl->rst.flags = nde->tun->flags;
|
||||
list_add_tail(&tl->l, &tun_links);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tun_link *find_tun_link(char *name)
|
||||
{
|
||||
struct tun_link *tl;
|
||||
@@ -256,6 +280,91 @@ const struct fdtype_ops tunfile_dump_ops = {
|
||||
.dump = dump_tunfile,
|
||||
};
|
||||
|
||||
struct tunfile_info {
|
||||
struct file_desc d;
|
||||
TunfileEntry *tfe;
|
||||
};
|
||||
|
||||
static int tunfile_open(struct file_desc *d)
|
||||
{
|
||||
int fd;
|
||||
struct tunfile_info *ti;
|
||||
struct ifreq ifr;
|
||||
struct tun_link *tl;
|
||||
|
||||
ti = container_of(d, struct tunfile_info, d);
|
||||
fd = open_reg_by_id(ti->tfe->id);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (!ti->tfe->netdev)
|
||||
/* just-opened tun file */
|
||||
return fd;
|
||||
|
||||
tl = find_tun_link(ti->tfe->netdev);
|
||||
if (!tl) {
|
||||
pr_err("No tun device for file %s\n", ti->tfe->netdev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, tl->name);
|
||||
ifr.ifr_flags = tl->rst.flags;
|
||||
|
||||
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
|
||||
pr_perror("Can't attach tunfile to device");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ti->tfe->has_detached && ti->tfe->detached) {
|
||||
pr_info("Detaching from %s queue\n", ti->tfe->netdev);
|
||||
ifr.ifr_flags = IFF_DETACH_QUEUE;
|
||||
if (ioctl(fd, TUNSETQUEUE, &ifr) < 0) {
|
||||
pr_perror("Can't detach queue");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(tl->rst.flags & IFF_PERSIST)) {
|
||||
pr_info("Dropping persistency for %s\n", tl->name);
|
||||
if (ioctl(fd, TUNSETPERSIST, 0) < 0) {
|
||||
pr_perror("Error dropping persistency");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
err:
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct file_desc_ops tunfile_desc_ops = {
|
||||
.type = FD_TYPES__TUN,
|
||||
.open = tunfile_open,
|
||||
};
|
||||
|
||||
static int collect_one_tunfile(void *o, ProtobufCMessage *base)
|
||||
{
|
||||
struct tunfile_info *ti = o;
|
||||
|
||||
ti->tfe = pb_msg(base, TunfileEntry);
|
||||
file_desc_add(&ti->d, ti->tfe->id, &tunfile_desc_ops);
|
||||
|
||||
pr_info("Collected %s tunfile\n", ti->tfe->netdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct collect_image_info tunfile_cinfo = {
|
||||
.fd_type = CR_FD_TUNFILE,
|
||||
.pb_type = PB_TUNFILE,
|
||||
.priv_size = sizeof(struct tunfile_info),
|
||||
.collect = collect_one_tunfile,
|
||||
.flags = COLLECT_OPTIONAL,
|
||||
};
|
||||
|
||||
void show_tunfile(int fd)
|
||||
{
|
||||
pb_show_plain(fd, PB_TUNFILE);
|
||||
@@ -294,3 +403,64 @@ int dump_tun_link(NetDeviceEntry *nde, struct cr_fdset *fds)
|
||||
nde->tun = &tle;
|
||||
return write_netdev_img(nde, fds);
|
||||
}
|
||||
|
||||
int restore_one_tun(NetDeviceEntry *nde, int nlsk)
|
||||
{
|
||||
int fd, ret = -1, aux;
|
||||
|
||||
if (!nde->tun) {
|
||||
pr_err("Corrupted TUN link entry %x\n", nde->ifindex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_info("Restoring tun device %s\n", nde->name);
|
||||
|
||||
fd = open_tun_dev(nde->name, nde->ifindex, nde->tun->flags);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
aux = nde->tun->owner;
|
||||
if ((aux != -1) && ioctl(fd, TUNSETOWNER, aux) < 0) {
|
||||
pr_perror("Can't set owner\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
aux = nde->tun->group;
|
||||
if ((aux != -1) && ioctl(fd, TUNSETGROUP, aux) < 0) {
|
||||
pr_perror("Can't set group\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
aux = nde->tun->sndbuf;
|
||||
if (ioctl(fd, TUNSETSNDBUF, &aux) < 0) {
|
||||
pr_perror("Can't set sndbuf");
|
||||
goto out;
|
||||
}
|
||||
|
||||
aux = nde->tun->vnethdr;
|
||||
if (ioctl(fd, TUNSETVNETHDRSZ, &aux) < 0) {
|
||||
pr_perror("Can't set vnethdr");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set this device persistent anyway and schedule
|
||||
* the persistence drop if it should not be such.
|
||||
* The first _real_ opener will do it.
|
||||
*/
|
||||
|
||||
if (ioctl(fd, TUNSETPERSIST, 1)) {
|
||||
pr_perror("Can't make tun device persistent\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (restore_link_parms(nde, nlsk)) {
|
||||
pr_err("Error restoring %s link params\n", nde->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = list_tun_link(nde);
|
||||
out:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user