Commit f06369b9 authored by Andrei Vagin's avatar Andrei Vagin

net: dump and restore connected to a bridge links

A network device, which is connected to a bridge, is restored
after the bridge. In this case we can set the master attribute and
the device will be connected to the bridge automatically.
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 5b617ecd
...@@ -467,6 +467,11 @@ static int dump_one_netdev(int type, struct ifinfomsg *ifi, ...@@ -467,6 +467,11 @@ static int dump_one_netdev(int type, struct ifinfomsg *ifi,
(int)netdev.address.len, netdev.name); (int)netdev.address.len, netdev.name);
} }
if (tb[IFLA_MASTER]) {
netdev.has_master = true;
netdev.master = nla_get_u32(tb[IFLA_MASTER]);
}
netdev.n_conf4 = size4; netdev.n_conf4 = size4;
netdev.conf4 = xmalloc(sizeof(SysctlEntry *) * size4); netdev.conf4 = xmalloc(sizeof(SysctlEntry *) * size4);
if (!netdev.conf4) if (!netdev.conf4)
...@@ -566,36 +571,6 @@ static int dump_unknown_device(struct ifinfomsg *ifi, char *kind, ...@@ -566,36 +571,6 @@ static int dump_unknown_device(struct ifinfomsg *ifi, char *kind,
static int dump_bridge(NetDeviceEntry *nde, struct cr_imgset *imgset, struct nlattr **info) static int dump_bridge(NetDeviceEntry *nde, struct cr_imgset *imgset, struct nlattr **info)
{ {
char spath[IFNAMSIZ + 16]; /* len("class/net//brif") + 1 for null */
int ret, fd;
ret = snprintf(spath, sizeof(spath), "class/net/%s/brif", nde->name);
if (ret < 0 || ret >= sizeof(spath))
return -1;
/* Let's only allow dumping empty bridges for now. To do a full bridge
* restore, we need to make sure the bridge and slaves are restored in
* the right order and attached correctly. It looks like the veth code
* supports this, but we need some way to do ordering.
*/
fd = openat(ns_sysfs_fd, spath, O_DIRECTORY, 0);
if (fd < 0) {
pr_perror("opening %s failed", spath);
return -1;
}
ret = is_empty_dir(fd);
close(fd);
if (ret < 0) {
pr_perror("problem testing %s for emptiness", spath);
return -1;
}
if (!ret) {
pr_err("dumping bridges with attached slaves not supported currently\n");
return -1;
}
return write_netdev_img(nde, imgset, info); return write_netdev_img(nde, imgset, info);
} }
...@@ -1621,37 +1596,110 @@ exit: ...@@ -1621,37 +1596,110 @@ exit:
return ret; return ret;
} }
static int restore_links() static int restore_master_link(int nlsk, struct ns_id *ns, struct net_link *link)
{
struct newlink_req req;
memset(&req, 0, sizeof(req));
req.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
req.h.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE;
req.h.nlmsg_type = RTM_SETLINK;
req.h.nlmsg_seq = CR_NLMSG_SEQ;
req.i.ifi_family = AF_PACKET;
req.i.ifi_index = link->nde->ifindex;
req.i.ifi_flags = link->nde->flags;
addattr_l(&req.h, sizeof(req), IFLA_MASTER,
&link->nde->master, sizeof(link->nde->master));
return do_rtnl_req(nlsk, &req, req.h.nlmsg_len, restore_link_cb, NULL, NULL, NULL);
}
struct net_link *lookup_net_link(struct ns_id *ns, uint32_t ifindex)
{
struct net_link *link;
list_for_each_entry(link, &ns->net.links, node)
if (link->nde->ifindex == ifindex)
return link;
return NULL;
}
static int __restore_links(struct ns_id *nsid, int *nrlinks, int *nrcreated)
{ {
struct net_link *link, *t; struct net_link *link, *t;
int exit_code = -1, nlsk = -1; int ret;
struct ns_id *nsid;
for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) { list_for_each_entry_safe(link, t, &nsid->net.links, node) {
if (nsid->nd != &net_ns_desc) struct net_link *mlink = NULL;
if (link->created)
continue; continue;
if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL)) (*nrlinks)++;
goto out;
nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); pr_debug("Try to restore a link %d:%d:%s",
if (nlsk < 0) { nsid->id, link->nde->ifindex, link->nde->name);
pr_perror("Can't create nlk socket"); if (link->nde->has_master) {
return -1; mlink = lookup_net_link(nsid, link->nde->master);
if (mlink == NULL) {
pr_err("Unable to find the %d master\n", link->nde->master);
return -1;
}
if (!mlink->created) {
pr_debug("The master %d:%d:%s isn't created yet",
nsid->id, mlink->nde->ifindex, mlink->nde->name);
continue;
}
} }
list_for_each_entry_safe(link, t, &nsid->net.links, node) { ret = restore_link(nsid->net.nlsk, nsid, link);
if (restore_link(nlsk, nsid, link)) if (ret < 0)
goto out; return -1;
if (ret == 0) {
(*nrcreated)++;
link->created = true;
if (mlink && restore_master_link(nsid->net.nlsk, nsid, link))
return -1;
} }
close_safe(&nlsk);
} }
exit_code = 0; return 0;
out: }
close_safe(&nlsk);
return exit_code; static int restore_links()
{
int nrcreated, nrlinks;
struct ns_id *nsid;
while (true) {
nrcreated = 0;
nrlinks = 0;
for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
if (nsid->nd != &net_ns_desc)
continue;
if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL))
return -1;
if (__restore_links(nsid, &nrlinks, &nrcreated))
return -1;
}
if (nrcreated == nrlinks)
break;
if (nrcreated == 0) {
pr_err("Unable to restore network links");
return -1;
}
}
return 0;
} }
...@@ -2277,6 +2325,13 @@ int prepare_net_namespaces() ...@@ -2277,6 +2325,13 @@ int prepare_net_namespaces()
if (prepare_net_ns_first_stage(nsid)) if (prepare_net_ns_first_stage(nsid))
goto err; goto err;
nsid->net.nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nsid->net.nlsk < 0) {
pr_perror("Can't create nlk socket");
goto err;
}
} }
if (restore_links()) if (restore_links())
...@@ -2291,6 +2346,8 @@ int prepare_net_namespaces() ...@@ -2291,6 +2346,8 @@ int prepare_net_namespaces()
if (prepare_net_ns_second_stage(nsid)) if (prepare_net_ns_second_stage(nsid))
goto err; goto err;
close_safe(&nsid->net.nlsk);
} }
close_service_fd(NS_FD_OFF); close_service_fd(NS_FD_OFF);
......
...@@ -44,6 +44,7 @@ message net_device_entry { ...@@ -44,6 +44,7 @@ message net_device_entry {
optional uint32 peer_ifindex = 12; optional uint32 peer_ifindex = 12;
optional uint32 peer_nsid = 13; optional uint32 peer_nsid = 13;
optional uint32 master = 14;
optional sit_entry sit = 15; optional sit_entry sit = 15;
} }
......
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