Commit 8cb26b02 authored by Andrei Vagin's avatar Andrei Vagin

net: split restore_links on read and restore parts

It's a preparation for enumirating links a few times.
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 6aa4a9c2
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "common/compiler.h" #include "common/compiler.h"
#include "files.h" #include "files.h"
#include "common/list.h" #include "common/list.h"
#include "images/netdev.pb-c.h"
#ifndef CLONE_NEWNS #ifndef CLONE_NEWNS
#define CLONE_NEWNS 0x00020000 #define CLONE_NEWNS 0x00020000
...@@ -78,7 +79,7 @@ struct netns_id { ...@@ -78,7 +79,7 @@ struct netns_id {
}; };
struct net_link { struct net_link {
unsigned int ifindex; NetDeviceEntry *nde;
bool created; bool created;
struct list_head node; struct list_head node;
}; };
...@@ -127,6 +128,7 @@ struct ns_id { ...@@ -127,6 +128,7 @@ struct ns_id {
int seqsk; /* to talk to parasite daemons */ int seqsk; /* to talk to parasite daemons */
struct list_head ids; struct list_head ids;
struct list_head links; struct list_head links;
NetnsEntry *netns;
} net; } net;
}; };
}; };
......
...@@ -303,6 +303,7 @@ struct ns_id *rst_new_ns_id(unsigned int id, pid_t pid, ...@@ -303,6 +303,7 @@ struct ns_id *rst_new_ns_id(unsigned int id, pid_t pid,
if (nd == &net_ns_desc) { if (nd == &net_ns_desc) {
INIT_LIST_HEAD(&nsid->net.ids); INIT_LIST_HEAD(&nsid->net.ids);
INIT_LIST_HEAD(&nsid->net.links); INIT_LIST_HEAD(&nsid->net.links);
nsid->net.netns = NULL;
} }
} }
......
...@@ -1241,7 +1241,7 @@ static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req, ...@@ -1241,7 +1241,7 @@ static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req,
struct net_link *link; struct net_link *link;
list_for_each_entry(link, &ns->net.links, node) list_for_each_entry(link, &ns->net.links, node)
if (link->ifindex == nde->peer_ifindex && link->created) { if (link->nde->ifindex == nde->peer_ifindex && link->created) {
pr_err("%d\n", nde->peer_ifindex); pr_err("%d\n", nde->peer_ifindex);
req->h.nlmsg_type = RTM_SETLINK; req->h.nlmsg_type = RTM_SETLINK;
return 0; return 0;
...@@ -1262,7 +1262,6 @@ static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req, ...@@ -1262,7 +1262,6 @@ static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req,
if (link == NULL) if (link == NULL)
return -1; return -1;
link->ifindex = nde->ifindex;
link->created = true; link->created = true;
list_add(&link->node, &ns->net.links); list_add(&link->node, &ns->net.links);
} }
...@@ -1394,7 +1393,7 @@ out: ...@@ -1394,7 +1393,7 @@ out:
return ret; return ret;
} }
static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int criu_nlsk) static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk)
{ {
struct newlink_extras extras = { struct newlink_extras extras = {
.link = -1, .link = -1,
...@@ -1533,7 +1532,7 @@ skip:; ...@@ -1533,7 +1532,7 @@ skip:;
return 0; return 0;
} }
static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int criu_nlsk) static int __restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk)
{ {
pr_info("Restoring link %s type %d\n", nde->name, nde->type); pr_info("Restoring link %s type %d\n", nde->name, nde->type);
...@@ -1550,7 +1549,7 @@ static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int cri ...@@ -1550,7 +1549,7 @@ static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int cri
case ND_TYPE__BRIDGE: case ND_TYPE__BRIDGE:
return restore_one_link(ns, nde, nlsk, bridge_link_info, NULL); return restore_one_link(ns, nde, nlsk, bridge_link_info, NULL);
case ND_TYPE__MACVLAN: case ND_TYPE__MACVLAN:
return restore_one_macvlan(ns, nde, nlsk, criu_nlsk); return restore_one_macvlan(ns, nde, nlsk);
case ND_TYPE__SIT: case ND_TYPE__SIT:
return restore_one_link(ns, nde, nlsk, sit_link_info, NULL); return restore_one_link(ns, nde, nlsk, sit_link_info, NULL);
default: default:
...@@ -1561,9 +1560,9 @@ static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int cri ...@@ -1561,9 +1560,9 @@ static int restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, int cri
return -1; return -1;
} }
static int restore_links(struct ns_id *ns, NetnsEntry **netns) static int read_links(struct ns_id *ns)
{ {
int nlsk, criu_nlsk = -1, ret = -1, id = ns->id; int ret = -1, id = ns->id;
struct cr_img *img; struct cr_img *img;
NetDeviceEntry *nde; NetDeviceEntry *nde;
...@@ -1571,54 +1570,87 @@ static int restore_links(struct ns_id *ns, NetnsEntry **netns) ...@@ -1571,54 +1570,87 @@ static int restore_links(struct ns_id *ns, NetnsEntry **netns)
if (!img) if (!img)
return -1; return -1;
nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlsk < 0) {
pr_perror("Can't create nlk socket");
close_image(img);
return -1;
}
while (1) { while (1) {
NetnsEntry **def_netns = netns; struct net_link *link;
ret = pb_read_one_eof(img, &nde, PB_NETDEV); ret = pb_read_one_eof(img, &nde, PB_NETDEV);
if (ret <= 0) if (ret <= 0)
break; break;
ret = restore_link(ns, nde, nlsk, criu_nlsk); link = xmalloc(sizeof(*link));
if (ret) { if (link == NULL) {
pr_err("Can't restore link: %d\n", ret); ret = -1;
goto exit; net_device_entry__free_unpacked(nde, NULL);
break;
} }
/* link->nde = nde;
* optimize restore of devices configuration except lo link->created = 0;
* lo is created with namespace and before default is set list_add(&link->node, &ns->net.links);
* so we can't optimize its restore }
*/ close_image(img);
if (nde->type == ND_TYPE__LOOPBACK)
def_netns = NULL;
if (nde->conf4) return 0;
ret = ipv4_conf_op(nde->name, nde->conf4, nde->n_conf4, CTL_WRITE, def_netns ? (*def_netns)->def_conf4 : NULL); }
else if (nde->conf)
ret = ipv4_conf_op_old(nde->name, nde->conf, nde->n_conf, CTL_WRITE, def_netns ? (*def_netns)->def_conf : NULL); static int restore_link(int nlsk, struct ns_id *ns, struct net_link *link)
if (ret) {
goto exit; NetDeviceEntry *nde = link->nde;
NetnsEntry **def_netns = &ns->net.netns;
int ret;
ret = __restore_link(ns, nde, nlsk);
if (ret) {
pr_err("Can't restore link: %d\n", ret);
goto exit;
}
/*
* optimize restore of devices configuration except lo
* lo is created with namespace and before default is set
* so we can't optimize its restore
*/
if (nde->type == ND_TYPE__LOOPBACK)
def_netns = NULL;
if (nde->conf6) if (nde->conf4)
ret = ipv6_conf_op(nde->name, nde->conf6, nde->n_conf6, CTL_WRITE, def_netns ? (*def_netns)->def_conf6 : NULL); ret = ipv4_conf_op(nde->name, nde->conf4, nde->n_conf4, CTL_WRITE, def_netns ? (*def_netns)->def_conf4 : NULL);
else if (nde->conf)
ret = ipv4_conf_op_old(nde->name, nde->conf, nde->n_conf, CTL_WRITE, def_netns ? (*def_netns)->def_conf : NULL);
if (ret)
goto exit;
if (nde->conf6)
ret = ipv6_conf_op(nde->name, nde->conf6, nde->n_conf6, CTL_WRITE, def_netns ? (*def_netns)->def_conf6 : NULL);
exit: exit:
net_device_entry__free_unpacked(nde, NULL); return ret;
if (ret) }
break;
static int restore_links(struct ns_id *ns)
{
struct net_link *link, *t;
int exit_code = -1, nlsk;
nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlsk < 0) {
pr_perror("Can't create nlk socket");
return -1;
} }
list_for_each_entry_safe(link, t, &ns->net.links, node) {
if (restore_link(nlsk, ns, link))
goto out;
xfree(link);
}
exit_code = 0;
out:
close(nlsk); close(nlsk);
close_image(img);
return ret; return exit_code;
} }
static int run_ip_tool(char *arg1, char *arg2, char *arg3, char *arg4, int fdin, int fdout, unsigned flags) static int run_ip_tool(char *arg1, char *arg2, char *arg3, char *arg4, int fdin, int fdout, unsigned flags)
{ {
char *ip_tool_cmd; char *ip_tool_cmd;
...@@ -1913,12 +1945,13 @@ out: ...@@ -1913,12 +1945,13 @@ out:
return ret; return ret;
} }
static int restore_netns_conf(int pid, NetnsEntry **netns) static int restore_netns_conf(struct ns_id *ns)
{ {
NetnsEntry *netns;
int ret = 0; int ret = 0;
struct cr_img *img; struct cr_img *img;
img = open_image(CR_FD_NETNS, O_RSTR, pid); img = open_image(CR_FD_NETNS, O_RSTR, ns->id);
if (!img) if (!img)
return -1; return -1;
...@@ -1926,35 +1959,37 @@ static int restore_netns_conf(int pid, NetnsEntry **netns) ...@@ -1926,35 +1959,37 @@ static int restore_netns_conf(int pid, NetnsEntry **netns)
/* Backward compatibility */ /* Backward compatibility */
goto out; goto out;
ret = pb_read_one(img, netns, PB_NETNS); ret = pb_read_one(img, &netns, PB_NETNS);
if (ret < 0) { if (ret < 0) {
pr_err("Can not read netns object\n"); pr_err("Can not read netns object\n");
return -1; return -1;
} }
if ((*netns)->def_conf4) { if ((netns)->def_conf4) {
ret = ipv4_conf_op("all", (*netns)->all_conf4, (*netns)->n_all_conf4, CTL_WRITE, NULL); ret = ipv4_conf_op("all", (netns)->all_conf4, (netns)->n_all_conf4, CTL_WRITE, NULL);
if (ret) if (ret)
goto out; goto out;
ret = ipv4_conf_op("default", (*netns)->def_conf4, (*netns)->n_def_conf4, CTL_WRITE, NULL); ret = ipv4_conf_op("default", (netns)->def_conf4, (netns)->n_def_conf4, CTL_WRITE, NULL);
if (ret) if (ret)
goto out; goto out;
} else if ((*netns)->def_conf) { } else if ((netns)->def_conf) {
/* Backward compatibility */ /* Backward compatibility */
ret = ipv4_conf_op_old("all", (*netns)->all_conf, (*netns)->n_all_conf, CTL_WRITE, NULL); ret = ipv4_conf_op_old("all", (netns)->all_conf, (netns)->n_all_conf, CTL_WRITE, NULL);
if (ret) if (ret)
goto out; goto out;
ret = ipv4_conf_op_old("default", (*netns)->def_conf, (*netns)->n_def_conf, CTL_WRITE, NULL); ret = ipv4_conf_op_old("default", (netns)->def_conf, (netns)->n_def_conf, CTL_WRITE, NULL);
if (ret) if (ret)
goto out; goto out;
} }
if ((*netns)->def_conf6) { if ((netns)->def_conf6) {
ret = ipv6_conf_op("all", (*netns)->all_conf6, (*netns)->n_all_conf6, CTL_WRITE, NULL); ret = ipv6_conf_op("all", (netns)->all_conf6, (netns)->n_all_conf6, CTL_WRITE, NULL);
if (ret) if (ret)
goto out; goto out;
ret = ipv6_conf_op("default", (*netns)->def_conf6, (*netns)->n_def_conf6, CTL_WRITE, NULL); ret = ipv6_conf_op("default", (netns)->def_conf6, (netns)->n_def_conf6, CTL_WRITE, NULL);
} }
ns->net.netns = netns;
out: out:
close_image(img); close_image(img);
return ret; return ret;
...@@ -2099,7 +2134,7 @@ int dump_net_ns(struct ns_id *ns) ...@@ -2099,7 +2134,7 @@ int dump_net_ns(struct ns_id *ns)
} }
static int net_set_nsid(int rtsk, int fd, int nsid); static int net_set_nsid(int rtsk, int fd, int nsid);
static int restore_netns_ids(struct ns_id *ns, NetnsEntry *netns) static int restore_netns_ids(struct ns_id *ns)
{ {
int i, sk, exit_code = -1; int i, sk, exit_code = -1;
...@@ -2109,15 +2144,15 @@ static int restore_netns_ids(struct ns_id *ns, NetnsEntry *netns) ...@@ -2109,15 +2144,15 @@ static int restore_netns_ids(struct ns_id *ns, NetnsEntry *netns)
return -1; return -1;
} }
for (i = 0; i < netns->n_nsids; i++) { for (i = 0; i < ns->net.netns->n_nsids; i++) {
struct ns_id *tg_ns; struct ns_id *tg_ns;
struct netns_id *id; struct netns_id *id;
id = xmalloc(sizeof(*id)); id = xmalloc(sizeof(*id));
if (!id) if (!id)
goto out; goto out;
id->target_ns_id = netns->nsids[i]->target_ns_id; id->target_ns_id = ns->net.netns->nsids[i]->target_ns_id;
id->netnsid_value = netns->nsids[i]->netnsid_value; id->netnsid_value = ns->net.netns->nsids[i]->netnsid_value;
list_add(&id->node, &ns->net.ids); list_add(&id->node, &ns->net.ids);
tg_ns = lookup_ns_by_id(id->target_ns_id, &net_ns_desc); tg_ns = lookup_ns_by_id(id->target_ns_id, &net_ns_desc);
...@@ -2140,16 +2175,18 @@ out: ...@@ -2140,16 +2175,18 @@ out:
static int prepare_net_ns(struct ns_id *ns) static int prepare_net_ns(struct ns_id *ns)
{ {
int ret = 0, nsid = ns->id; int ret = 0, nsid = ns->id;
NetnsEntry *netns = NULL;
if (!(opts.empty_ns & CLONE_NEWNET)) { if (!(opts.empty_ns & CLONE_NEWNET)) {
ret = restore_netns_conf(nsid, &netns); ret = restore_netns_conf(ns);
if (!ret)
ret = restore_netns_ids(ns);
if (!ret) if (!ret)
ret = restore_netns_ids(ns, netns); ret = read_links(ns);
if (!ret) if (!ret)
ret = restore_links(ns, &netns); ret = restore_links(ns);
if (netns)
netns_entry__free_unpacked(netns, NULL); if (ns->net.netns)
netns_entry__free_unpacked(ns->net.netns, NULL);
if (!ret) if (!ret)
ret = restore_ifaddr(nsid); ret = restore_ifaddr(nsid);
......
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