Commit f2037e6d authored by Pavel Emelyanov's avatar Pavel Emelyanov

veth: Make --external support --veth-pair

Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent d026a418
...@@ -62,7 +62,6 @@ void init_opts(void) ...@@ -62,7 +62,6 @@ void init_opts(void)
/* Default options */ /* Default options */
opts.final_state = TASK_DEAD; opts.final_state = TASK_DEAD;
INIT_LIST_HEAD(&opts.ext_unixsk_ids); INIT_LIST_HEAD(&opts.ext_unixsk_ids);
INIT_LIST_HEAD(&opts.veth_pairs);
INIT_LIST_HEAD(&opts.ext_mounts); INIT_LIST_HEAD(&opts.ext_mounts);
INIT_LIST_HEAD(&opts.inherit_fds); INIT_LIST_HEAD(&opts.inherit_fds);
INIT_LIST_HEAD(&opts.external); INIT_LIST_HEAD(&opts.external);
...@@ -830,6 +829,7 @@ usage: ...@@ -830,6 +829,7 @@ usage:
" dev[maj:min]:VAL\n" " dev[maj:min]:VAL\n"
" Formats of RES on restore:\n" " Formats of RES on restore:\n"
" dev[VAL]:DEVPATH\n" " dev[VAL]:DEVPATH\n"
" veth[IFNAME]:OUTNAME{@BRIDGE}\n"
"\n" "\n"
"* Special resources support:\n" "* Special resources support:\n"
" -x|--" USK_EXT_PARAM " [inode,...]\n" " -x|--" USK_EXT_PARAM " [inode,...]\n"
...@@ -840,9 +840,6 @@ usage: ...@@ -840,9 +840,6 @@ usage:
" -r|--root PATH change the root filesystem (when run in mount namespace)\n" " -r|--root PATH change the root filesystem (when run in mount namespace)\n"
" --evasive-devices use any path to a device file if the original one\n" " --evasive-devices use any path to a device file if the original one\n"
" is inaccessible\n" " is inaccessible\n"
" --veth-pair IN=OUT map inside veth device name to outside one\n"
" can optionally append @<bridge-name> to OUT for moving\n"
" the outside veth to the named bridge\n"
" --link-remap allow one to link unlinked files back when possible\n" " --link-remap allow one to link unlinked files back when possible\n"
" --ghost-limit size limit max size of deleted file contents inside image\n" " --ghost-limit size limit max size of deleted file contents inside image\n"
" --action-script FILE add an external action script\n" " --action-script FILE add an external action script\n"
......
...@@ -72,7 +72,6 @@ struct cr_options { ...@@ -72,7 +72,6 @@ struct cr_options {
char *root; char *root;
char *pidfile; char *pidfile;
char *freeze_cgroup; char *freeze_cgroup;
struct list_head veth_pairs;
struct list_head ext_mounts; struct list_head ext_mounts;
struct list_head inherit_fds; struct list_head inherit_fds;
struct list_head external; struct list_head external;
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "sysctl.h" #include "sysctl.h"
#include "kerndat.h" #include "kerndat.h"
#include "util.h" #include "util.h"
#include "external.h"
#include "protobuf.h" #include "protobuf.h"
#include "images/netdev.pb-c.h" #include "images/netdev.pb-c.h"
...@@ -904,12 +906,25 @@ enum { ...@@ -904,12 +906,25 @@ enum {
#define IFLA_NET_NS_FD 28 #define IFLA_NET_NS_FD 28
#endif #endif
static void veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req)
{
char key[100], *val;
snprintf(key, sizeof(key), "veth[%s]", nde->name);
val = external_lookup_by_key(key);
if (!IS_ERR_OR_NULL(val)) {
char *aux;
aux = strchrnul(val, '@');
addattr_l(&req->h, sizeof(*req), IFLA_IFNAME, val, aux - val - 1);
}
}
static int veth_link_info(NetDeviceEntry *nde, struct newlink_req *req) static int veth_link_info(NetDeviceEntry *nde, struct newlink_req *req)
{ {
int ns_fd = get_service_fd(NS_FD_OFF); int ns_fd = get_service_fd(NS_FD_OFF);
struct rtattr *veth_data, *peer_data; struct rtattr *veth_data, *peer_data;
struct ifinfomsg ifm; struct ifinfomsg ifm;
struct veth_pair *n;
BUG_ON(ns_fd < 0); BUG_ON(ns_fd < 0);
...@@ -920,12 +935,7 @@ static int veth_link_info(NetDeviceEntry *nde, struct newlink_req *req) ...@@ -920,12 +935,7 @@ static int veth_link_info(NetDeviceEntry *nde, struct newlink_req *req)
peer_data = NLMSG_TAIL(&req->h); peer_data = NLMSG_TAIL(&req->h);
memset(&ifm, 0, sizeof(ifm)); memset(&ifm, 0, sizeof(ifm));
addattr_l(&req->h, sizeof(*req), VETH_INFO_PEER, &ifm, sizeof(ifm)); addattr_l(&req->h, sizeof(*req), VETH_INFO_PEER, &ifm, sizeof(ifm));
list_for_each_entry(n, &opts.veth_pairs, node) { veth_peer_info(nde, req);
if (!strcmp(nde->name, n->inside))
break;
}
if (&n->node != &opts.veth_pairs)
addattr_l(&req->h, sizeof(*req), IFLA_IFNAME, n->outside, strlen(n->outside));
addattr_l(&req->h, sizeof(*req), IFLA_NET_NS_FD, &ns_fd, sizeof(ns_fd)); addattr_l(&req->h, sizeof(*req), IFLA_NET_NS_FD, &ns_fd, sizeof(ns_fd));
peer_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)peer_data; peer_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)peer_data;
veth_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)veth_data; veth_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)veth_data;
...@@ -1620,33 +1630,13 @@ void network_unlock(void) ...@@ -1620,33 +1630,13 @@ void network_unlock(void)
int veth_pair_add(char *in, char *out) int veth_pair_add(char *in, char *out)
{ {
char *aux; char *e_str;
struct veth_pair *n;
n = xmalloc(sizeof(*n)); e_str = xmalloc(200); /* For 3 IFNAMSIZ + 8 service characters */
if (n == NULL) if (!e_str)
return -1; return -1;
snprintf(e_str, 200, "veth[%s]:%s", in, out);
n->inside = in; return add_external(e_str);
n->outside = out;
/*
* Does the out string specify a bridge for
* moving the outside end of the veth pair to?
*/
aux = strrchr(out, '@');
if (aux) {
*aux++ = '\0';
n->bridge = aux;
} else {
n->bridge = NULL;
}
list_add(&n->node, &opts.veth_pairs);
if (n->bridge)
pr_debug("Added %s:%s@%s veth map\n", in, out, aux);
else
pr_debug("Added %s:%s veth map\n", in, out);
return 0;
} }
/* /*
...@@ -1727,20 +1717,26 @@ int collect_net_namespaces(bool for_dump) ...@@ -1727,20 +1717,26 @@ int collect_net_namespaces(bool for_dump)
struct ns_desc net_ns_desc = NS_DESC_ENTRY(CLONE_NEWNET, "net"); struct ns_desc net_ns_desc = NS_DESC_ENTRY(CLONE_NEWNET, "net");
int move_veth_to_bridge(void) static int move_to_bridge(struct external *ext, void *arg)
{ {
int s; int s = *(int *)arg;
int ret; int ret;
struct veth_pair *n; char *out, *br;
struct ifreq ifr; struct ifreq ifr;
s = -1; out = external_val(ext);
ret = 0; if (!out)
list_for_each_entry(n, &opts.veth_pairs, node) { return -1;
if (n->bridge == NULL)
continue; br = strchr(out, '@');
if (!br)
return 0;
pr_debug("\tMoving dev %s to bridge %s\n", n->outside, n->bridge); *br = '\0';
br++;
{
pr_debug("\tMoving dev %s to bridge %s\n", out, br);
if (s == -1) { if (s == -1) {
s = socket(AF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0); s = socket(AF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0);
...@@ -1754,18 +1750,17 @@ int move_veth_to_bridge(void) ...@@ -1754,18 +1750,17 @@ int move_veth_to_bridge(void)
* Add the device to the bridge. This is equivalent to: * Add the device to the bridge. This is equivalent to:
* $ brctl addif <bridge> <device> * $ brctl addif <bridge> <device>
*/ */
ifr.ifr_ifindex = if_nametoindex(n->outside); ifr.ifr_ifindex = if_nametoindex(out);
if (ifr.ifr_ifindex == 0) { if (ifr.ifr_ifindex == 0) {
pr_perror("Can't get index of %s", n->outside); pr_perror("Can't get index of %s", out);
ret = -1; ret = -1;
break; goto out;
} }
strlcpy(ifr.ifr_name, n->bridge, IFNAMSIZ); strlcpy(ifr.ifr_name, br, IFNAMSIZ);
ret = ioctl(s, SIOCBRADDIF, &ifr); ret = ioctl(s, SIOCBRADDIF, &ifr);
if (ret < 0) { if (ret < 0) {
pr_perror("Can't add interface %s to bridge %s", pr_perror("Can't add interface %s to bridge %s", out, br);
n->outside, n->bridge); goto out;
break;
} }
/* /*
...@@ -1773,24 +1768,41 @@ int move_veth_to_bridge(void) ...@@ -1773,24 +1768,41 @@ int move_veth_to_bridge(void)
* $ ip link set dev <device> up * $ ip link set dev <device> up
*/ */
ifr.ifr_ifindex = 0; ifr.ifr_ifindex = 0;
strlcpy(ifr.ifr_name, n->outside, IFNAMSIZ); strlcpy(ifr.ifr_name, out, IFNAMSIZ);
ret = ioctl(s, SIOCGIFFLAGS, &ifr); ret = ioctl(s, SIOCGIFFLAGS, &ifr);
if (ret < 0) { if (ret < 0) {
pr_perror("Can't get flags of interface %s", n->outside); pr_perror("Can't get flags of interface %s", out);
break; goto out;
} }
ret = 0;
if (ifr.ifr_flags & IFF_UP) if (ifr.ifr_flags & IFF_UP)
continue; goto out;
ifr.ifr_flags |= IFF_UP; ifr.ifr_flags |= IFF_UP;
ret = ioctl(s, SIOCSIFFLAGS, &ifr); ret = ioctl(s, SIOCSIFFLAGS, &ifr);
if (ret < 0) { if (ret < 0) {
pr_perror("Can't set flags of interface %s to 0x%x", pr_perror("Can't set flags of interface %s to 0x%x",
n->outside, ifr.ifr_flags); out, ifr.ifr_flags);
break; goto out;
} }
ret = 0;
} }
out:
br--;
*br = '@';
*(int *)arg = s;
return ret;
}
int move_veth_to_bridge(void)
{
int sk = -1, ret;
ret = external_for_each_type("veth", move_to_bridge, &sk);
if (sk >= 0)
close(sk);
if (s >= 0)
close(s);
return ret; return ret;
} }
...@@ -71,7 +71,7 @@ message criu_opts { ...@@ -71,7 +71,7 @@ message criu_opts {
optional int32 work_dir_fd = 17; optional int32 work_dir_fd = 17;
optional bool link_remap = 18; optional bool link_remap = 18;
repeated criu_veth_pair veths = 19; repeated criu_veth_pair veths = 19; /* DEPRECATED, use external instead */
optional uint32 cpu_cap = 20 [default = 0xffffffff]; optional uint32 cpu_cap = 20 [default = 0xffffffff];
optional bool force_irmap = 21; optional bool force_irmap = 21;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment