Commit 5b617ecd authored by Andrei Vagin's avatar Andrei Vagin

net: create a list of all links

We will need to enumirate links a few times
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 8cb26b02
...@@ -38,7 +38,8 @@ extern struct ns_desc net_ns_desc; ...@@ -38,7 +38,8 @@ extern struct ns_desc net_ns_desc;
#include "images/netdev.pb-c.h" #include "images/netdev.pb-c.h"
extern int write_netdev_img(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **info); extern int write_netdev_img(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **info);
extern int read_ns_sys_file(char *path, char *buf, int len); extern int read_ns_sys_file(char *path, char *buf, int len);
extern int restore_link_parms(NetDeviceEntry *nde, int nlsk); struct net_link;
extern int restore_link_parms(struct net_link *link, int nlsk);
extern int veth_pair_add(char *in, char *out); extern int veth_pair_add(char *in, char *out);
extern int macvlan_ext_add(struct external *ext); extern int macvlan_ext_add(struct external *ext);
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
extern const struct fdtype_ops tunfile_dump_ops; extern const struct fdtype_ops tunfile_dump_ops;
extern int dump_tun_link(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **info); extern int dump_tun_link(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **info);
extern int restore_one_tun(NetDeviceEntry *nde, int nlsk); struct net_link;
extern int restore_one_tun(struct net_link *link, int nlsk);
extern struct collect_image_info tunfile_cinfo; extern struct collect_image_info tunfile_cinfo;
extern int check_tun_cr(int no_tun_err); extern int check_tun_cr(int no_tun_err);
......
...@@ -1123,12 +1123,14 @@ struct newlink_extras { ...@@ -1123,12 +1123,14 @@ struct newlink_extras {
int target_netns; /* IFLA_NET_NS_FD */ int target_netns; /* IFLA_NET_NS_FD */
}; };
typedef int (*link_info_t)(struct ns_id *ns, NetDeviceEntry *, struct newlink_req *); typedef int (*link_info_t)(struct ns_id *ns, struct net_link *, struct newlink_req *);
static int populate_newlink_req(struct ns_id *ns, struct newlink_req *req, static int populate_newlink_req(struct ns_id *ns, struct newlink_req *req,
int msg_type, NetDeviceEntry *nde, int msg_type, struct net_link * link,
link_info_t link_info, struct newlink_extras *extras) link_info_t link_info, struct newlink_extras *extras)
{ {
NetDeviceEntry *nde = link->nde;
memset(req, 0, sizeof(*req)); memset(req, 0, sizeof(*req));
req->h.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req->h.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
...@@ -1171,7 +1173,7 @@ static int populate_newlink_req(struct ns_id *ns, struct newlink_req *req, ...@@ -1171,7 +1173,7 @@ static int populate_newlink_req(struct ns_id *ns, struct newlink_req *req,
linkinfo = NLMSG_TAIL(&req->h); linkinfo = NLMSG_TAIL(&req->h);
addattr_l(&req->h, sizeof(*req), IFLA_LINKINFO, NULL, 0); addattr_l(&req->h, sizeof(*req), IFLA_LINKINFO, NULL, 0);
ret = link_info(ns, nde, req); ret = link_info(ns, link, req);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1182,27 +1184,27 @@ static int populate_newlink_req(struct ns_id *ns, struct newlink_req *req, ...@@ -1182,27 +1184,27 @@ static int populate_newlink_req(struct ns_id *ns, struct newlink_req *req,
} }
static int do_rtm_link_req(int msg_type, static int do_rtm_link_req(int msg_type,
NetDeviceEntry *nde, int nlsk, struct ns_id *ns, struct net_link *link, int nlsk, struct ns_id *ns,
link_info_t link_info, struct newlink_extras *extras) link_info_t link_info, struct newlink_extras *extras)
{ {
struct newlink_req req; struct newlink_req req;
if (populate_newlink_req(ns, &req, msg_type, nde, link_info, extras) < 0) if (populate_newlink_req(ns, &req, msg_type, link, link_info, extras) < 0)
return -1; return -1;
return do_rtnl_req(nlsk, &req, req.h.nlmsg_len, restore_link_cb, NULL, NULL, NULL); return do_rtnl_req(nlsk, &req, req.h.nlmsg_len, restore_link_cb, NULL, NULL, NULL);
} }
int restore_link_parms(NetDeviceEntry *nde, int nlsk) int restore_link_parms(struct net_link *link, int nlsk)
{ {
return do_rtm_link_req(RTM_SETLINK, nde, nlsk, NULL, NULL, NULL); return do_rtm_link_req(RTM_SETLINK, link, nlsk, NULL, NULL, NULL);
} }
static int restore_one_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk, static int restore_one_link(struct ns_id *ns, struct net_link *link, int nlsk,
link_info_t link_info, struct newlink_extras *extras) link_info_t link_info, struct newlink_extras *extras)
{ {
pr_info("Restoring netdev %s idx %d\n", nde->name, nde->ifindex); pr_info("Restoring netdev %s idx %d\n", link->nde->name, link->nde->ifindex);
return do_rtm_link_req(RTM_NEWLINK, nde, nlsk, ns, link_info, extras); return do_rtm_link_req(RTM_NEWLINK, link, nlsk, ns, link_info, extras);
} }
#ifndef VETH_INFO_MAX #ifndef VETH_INFO_MAX
...@@ -1219,9 +1221,10 @@ enum { ...@@ -1219,9 +1221,10 @@ enum {
#define IFLA_NET_NS_FD 28 #define IFLA_NET_NS_FD 28
#endif #endif
static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req, static int veth_peer_info(struct net_link *link, struct newlink_req *req,
struct ns_id *ns, int ns_fd) struct ns_id *ns, int ns_fd)
{ {
NetDeviceEntry *nde = link->nde;
char key[100], *val; char key[100], *val;
struct ns_id *peer_ns = NULL; struct ns_id *peer_ns = NULL;
...@@ -1237,46 +1240,33 @@ static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req, ...@@ -1237,46 +1240,33 @@ static int veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req,
} }
if (nde->has_peer_nsid) { if (nde->has_peer_nsid) {
if (ns && nde->peer_nsid == ns->id) { struct net_link *plink;
struct net_link *link;
list_for_each_entry(link, &ns->net.links, node)
if (link->nde->ifindex == nde->peer_ifindex && link->created) {
pr_err("%d\n", nde->peer_ifindex);
req->h.nlmsg_type = RTM_SETLINK;
return 0;
}
}
peer_ns = lookup_ns_by_id(nde->peer_nsid, &net_ns_desc); peer_ns = lookup_ns_by_id(nde->peer_nsid, &net_ns_desc);
if (peer_ns->ns_populated) { if (!peer_ns)
req->h.nlmsg_type = RTM_SETLINK; goto out;
return 0; list_for_each_entry(plink, &peer_ns->net.links, node) {
if (plink->nde->ifindex == nde->peer_ifindex && plink->created) {
req->h.nlmsg_type = RTM_SETLINK;
return 0;
}
} }
} }
link->created = true;
if (peer_ns) { if (peer_ns) {
if (ns && nde->peer_nsid == ns->id) {
struct net_link *link;
link = xmalloc(sizeof(*link));
if (link == NULL)
return -1;
link->created = true;
list_add(&link->node, &ns->net.links);
}
addattr_l(&req->h, sizeof(*req), IFLA_NET_NS_FD, &peer_ns->net.ns_fd, sizeof(int)); addattr_l(&req->h, sizeof(*req), IFLA_NET_NS_FD, &peer_ns->net.ns_fd, sizeof(int));
return 0; return 0;
} }
out:
pr_err("Unknown peer net namespace"); pr_err("Unknown peer net namespace");
return -1; return -1;
} }
static int veth_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_req *req) static int veth_link_info(struct ns_id *ns, struct net_link *link, struct newlink_req *req)
{ {
int ns_fd = get_service_fd(NS_FD_OFF); int ns_fd = get_service_fd(NS_FD_OFF);
NetDeviceEntry *nde = link->nde;
struct rtattr *veth_data, *peer_data; struct rtattr *veth_data, *peer_data;
struct ifinfomsg ifm; struct ifinfomsg ifm;
...@@ -1290,14 +1280,14 @@ static int veth_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_ ...@@ -1290,14 +1280,14 @@ static int veth_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_
ifm.ifi_index = nde->peer_ifindex; ifm.ifi_index = nde->peer_ifindex;
addattr_l(&req->h, sizeof(*req), VETH_INFO_PEER, &ifm, sizeof(ifm)); addattr_l(&req->h, sizeof(*req), VETH_INFO_PEER, &ifm, sizeof(ifm));
veth_peer_info(nde, req, ns, ns_fd); veth_peer_info(link, req, ns, 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;
return 0; return 0;
} }
static int venet_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_req *req) static int venet_link_info(struct ns_id *ns, struct net_link *link, struct newlink_req *req)
{ {
int ns_fd = get_service_fd(NS_FD_OFF); int ns_fd = get_service_fd(NS_FD_OFF);
struct rtattr *venet_data; struct rtattr *venet_data;
...@@ -1313,7 +1303,7 @@ static int venet_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink ...@@ -1313,7 +1303,7 @@ static int venet_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink
return 0; return 0;
} }
static int bridge_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_req *req) static int bridge_link_info(struct ns_id *ns, struct net_link *link, struct newlink_req *req)
{ {
struct rtattr *bridge_data; struct rtattr *bridge_data;
...@@ -1339,9 +1329,10 @@ static int changeflags(int s, char *name, short flags) ...@@ -1339,9 +1329,10 @@ static int changeflags(int s, char *name, short flags)
return 0; return 0;
} }
static int macvlan_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_req *req) static int macvlan_link_info(struct ns_id *ns, struct net_link *link, struct newlink_req *req)
{ {
struct rtattr *macvlan_data; struct rtattr *macvlan_data;
NetDeviceEntry *nde = link->nde;
MacvlanLinkEntry *macvlan = nde->macvlan; MacvlanLinkEntry *macvlan = nde->macvlan;
if (!macvlan) { if (!macvlan) {
...@@ -1393,7 +1384,7 @@ out: ...@@ -1393,7 +1384,7 @@ out:
return ret; return ret;
} }
static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk) static int restore_one_macvlan(struct ns_id *ns, struct net_link *link, int nlsk)
{ {
struct newlink_extras extras = { struct newlink_extras extras = {
.link = -1, .link = -1,
...@@ -1401,6 +1392,7 @@ static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk) ...@@ -1401,6 +1392,7 @@ static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk)
}; };
char key[100], *val; char key[100], *val;
int my_netns = -1, ret = -1; int my_netns = -1, ret = -1;
NetDeviceEntry *nde = link->nde;
snprintf(key, sizeof(key), "macvlan[%s]", nde->name); snprintf(key, sizeof(key), "macvlan[%s]", nde->name);
val = external_lookup_data(key); val = external_lookup_data(key);
...@@ -1428,7 +1420,7 @@ static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk) ...@@ -1428,7 +1420,7 @@ static int restore_one_macvlan(struct ns_id *ns, NetDeviceEntry *nde, int nlsk)
{ {
struct newlink_req req; struct newlink_req req;
if (populate_newlink_req(ns, &req, RTM_NEWLINK, nde, macvlan_link_info, &extras) < 0) if (populate_newlink_req(ns, &req, RTM_NEWLINK, link, macvlan_link_info, &extras) < 0)
goto out; goto out;
if (userns_call(userns_restore_one_link, 0, &req, sizeof(req), my_netns) < 0) { if (userns_call(userns_restore_one_link, 0, &req, sizeof(req), my_netns) < 0) {
...@@ -1444,8 +1436,9 @@ out: ...@@ -1444,8 +1436,9 @@ out:
return ret; return ret;
} }
static int sit_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_req *req) static int sit_link_info(struct ns_id *ns, struct net_link *link, struct newlink_req *req)
{ {
NetDeviceEntry *nde = link->nde;
struct rtattr *sit_data; struct rtattr *sit_data;
SitEntry *se = nde->sit; SitEntry *se = nde->sit;
...@@ -1532,28 +1525,30 @@ skip:; ...@@ -1532,28 +1525,30 @@ skip:;
return 0; return 0;
} }
static int __restore_link(struct ns_id *ns, NetDeviceEntry *nde, int nlsk) static int __restore_link(struct ns_id *ns, struct net_link *link, int nlsk)
{ {
NetDeviceEntry *nde = link->nde;
pr_info("Restoring link %s type %d\n", nde->name, nde->type); pr_info("Restoring link %s type %d\n", nde->name, nde->type);
switch (nde->type) { switch (nde->type) {
case ND_TYPE__LOOPBACK: /* fallthrough */ case ND_TYPE__LOOPBACK: /* fallthrough */
case ND_TYPE__EXTLINK: /* see comment in images/netdev.proto */ case ND_TYPE__EXTLINK: /* see comment in images/netdev.proto */
return restore_link_parms(nde, nlsk); return restore_link_parms(link, nlsk);
case ND_TYPE__VENET: case ND_TYPE__VENET:
return restore_one_link(ns, nde, nlsk, venet_link_info, NULL); return restore_one_link(ns, link, nlsk, venet_link_info, NULL);
case ND_TYPE__VETH: case ND_TYPE__VETH:
return restore_one_link(ns, nde, nlsk, veth_link_info, NULL); return restore_one_link(ns, link, nlsk, veth_link_info, NULL);
case ND_TYPE__TUN: case ND_TYPE__TUN:
return restore_one_tun(nde, nlsk); return restore_one_tun(link, nlsk);
case ND_TYPE__BRIDGE: case ND_TYPE__BRIDGE:
return restore_one_link(ns, nde, nlsk, bridge_link_info, NULL); return restore_one_link(ns, link, nlsk, bridge_link_info, NULL);
case ND_TYPE__MACVLAN: case ND_TYPE__MACVLAN:
return restore_one_macvlan(ns, nde, nlsk); return restore_one_macvlan(ns, link, 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, link, nlsk, sit_link_info, NULL);
default: default:
pr_err("Unsupported link type %d\n", nde->type); pr_err("Unsupported link type %d\n", link->nde->type);
break; break;
} }
...@@ -1599,7 +1594,7 @@ static int restore_link(int nlsk, struct ns_id *ns, struct net_link *link) ...@@ -1599,7 +1594,7 @@ static int restore_link(int nlsk, struct ns_id *ns, struct net_link *link)
NetnsEntry **def_netns = &ns->net.netns; NetnsEntry **def_netns = &ns->net.netns;
int ret; int ret;
ret = __restore_link(ns, nde, nlsk); ret = __restore_link(ns, link, nlsk);
if (ret) { if (ret) {
pr_err("Can't restore link: %d\n", ret); pr_err("Can't restore link: %d\n", ret);
goto exit; goto exit;
...@@ -1626,26 +1621,35 @@ exit: ...@@ -1626,26 +1621,35 @@ exit:
return ret; return ret;
} }
static int restore_links(struct ns_id *ns) static int restore_links()
{ {
struct net_link *link, *t; struct net_link *link, *t;
int exit_code = -1, nlsk; int exit_code = -1, nlsk = -1;
struct ns_id *nsid;
nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
if (nlsk < 0) { if (nsid->nd != &net_ns_desc)
pr_perror("Can't create nlk socket"); continue;
return -1;
}
list_for_each_entry_safe(link, t, &ns->net.links, node) { if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL))
if (restore_link(nlsk, ns, link))
goto out; goto out;
xfree(link);
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, &nsid->net.links, node) {
if (restore_link(nlsk, nsid, link))
goto out;
}
close_safe(&nlsk);
} }
exit_code = 0; exit_code = 0;
out: out:
close(nlsk); close_safe(&nlsk);
return exit_code; return exit_code;
} }
...@@ -2172,19 +2176,27 @@ out: ...@@ -2172,19 +2176,27 @@ out:
return exit_code; return exit_code;
} }
static int prepare_net_ns(struct ns_id *ns) static int prepare_net_ns_first_stage(struct ns_id *ns)
{
int ret = 0;
if (opts.empty_ns & CLONE_NEWNET)
return 0;
ret = restore_netns_conf(ns);
if (!ret)
ret = restore_netns_ids(ns);
if (!ret)
ret = read_links(ns);
return ret;
}
static int prepare_net_ns_second_stage(struct ns_id *ns)
{ {
int ret = 0, nsid = ns->id; int ret = 0, nsid = ns->id;
if (!(opts.empty_ns & CLONE_NEWNET)) { if (!(opts.empty_ns & CLONE_NEWNET)) {
ret = restore_netns_conf(ns);
if (!ret)
ret = restore_netns_ids(ns);
if (!ret)
ret = read_links(ns);
if (!ret)
ret = restore_links(ns);
if (ns->net.netns) if (ns->net.netns)
netns_entry__free_unpacked(ns->net.netns, NULL); netns_entry__free_unpacked(ns->net.netns, NULL);
...@@ -2263,7 +2275,21 @@ int prepare_net_namespaces() ...@@ -2263,7 +2275,21 @@ int prepare_net_namespaces()
if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL)) if (switch_ns_by_fd(nsid->net.ns_fd, &net_ns_desc, NULL))
goto err; goto err;
if (prepare_net_ns(nsid)) if (prepare_net_ns_first_stage(nsid))
goto err;
}
if (restore_links())
goto err;
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))
goto err;
if (prepare_net_ns_second_stage(nsid))
goto err; goto err;
} }
...@@ -2811,8 +2837,9 @@ int net_get_nsid(int rtsk, int pid, int *nsid) ...@@ -2811,8 +2837,9 @@ int net_get_nsid(int rtsk, int pid, int *nsid)
} }
static int nsid_link_info(struct ns_id *ns, NetDeviceEntry *nde, struct newlink_req *req) static int nsid_link_info(struct ns_id *ns, struct net_link *link, struct newlink_req *req)
{ {
NetDeviceEntry *nde = link->nde;
struct rtattr *veth_data, *peer_data; struct rtattr *veth_data, *peer_data;
struct ifinfomsg ifm; struct ifinfomsg ifm;
...@@ -2889,6 +2916,10 @@ int kerndat_link_nsid() ...@@ -2889,6 +2916,10 @@ int kerndat_link_nsid()
if (pid == 0) { if (pid == 0) {
NetDeviceEntry nde = NET_DEVICE_ENTRY__INIT; NetDeviceEntry nde = NET_DEVICE_ENTRY__INIT;
struct net_link link = {
.created = false,
.nde = &nde,
};
int nsfd, sk, ret; int nsfd, sk, ret;
sk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); sk = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
...@@ -2920,7 +2951,7 @@ int kerndat_link_nsid() ...@@ -2920,7 +2951,7 @@ int kerndat_link_nsid()
nde.has_peer_ifindex = true; nde.has_peer_ifindex = true;
nde.has_peer_nsid = true; nde.has_peer_nsid = true;
ret = restore_one_link(NULL, &nde, sk, nsid_link_info, NULL); ret = restore_one_link(NULL, &link, sk, nsid_link_info, NULL);
if (ret) { if (ret) {
pr_err("Unable to create a veth pair: %d\n", ret); pr_err("Unable to create a veth pair: %d\n", ret);
exit(1); exit(1);
......
...@@ -439,8 +439,9 @@ int dump_tun_link(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **in ...@@ -439,8 +439,9 @@ int dump_tun_link(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **in
return write_netdev_img(nde, fds, info); return write_netdev_img(nde, fds, info);
} }
int restore_one_tun(NetDeviceEntry *nde, int nlsk) int restore_one_tun(struct net_link *link, int nlsk)
{ {
NetDeviceEntry *nde = link->nde;
int fd, ret = -1, aux; int fd, ret = -1, aux;
if (!nde->tun) { if (!nde->tun) {
...@@ -489,7 +490,7 @@ int restore_one_tun(NetDeviceEntry *nde, int nlsk) ...@@ -489,7 +490,7 @@ int restore_one_tun(NetDeviceEntry *nde, int nlsk)
goto out; goto out;
} }
if (restore_link_parms(nde, nlsk)) { if (restore_link_parms(link, nlsk)) {
pr_err("Error restoring %s link params\n", nde->name); pr_err("Error restoring %s link params\n", nde->name);
goto out; goto out;
} }
......
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