[CRIU] [PATCH 1/3] net: dump netfilter conntracks and expectations

Pavel Emelyanov xemul at virtuozzo.com
Sat Feb 6 09:53:32 PST 2016


On 02/04/2016 10:36 PM, Andrey Vagin wrote:
> From: Andrew Vagin <avagin at virtuozzo.com>
> 
> We request all contracks via netlink and save netlink messages which
> describe them in an image file, then we send these netlink messages back on restore.

Does it require any non-upstream kernel patch to work?

> https://github.com/xemul/criu/issues/54
> Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
> ---
>  image-desc.c         |   2 +
>  include/image-desc.h |   2 +
>  include/magic.h      |   2 +
>  net.c                | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 132 insertions(+)
> 
> diff --git a/image-desc.c b/image-desc.c
> index 9fb96c8..6770675 100644
> --- a/image-desc.c
> +++ b/image-desc.c
> @@ -95,6 +95,8 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
>  	FD_ENTRY(CPUINFO,	"cpuinfo"),
>  	FD_ENTRY(SECCOMP,	"seccomp"),
>  	FD_ENTRY(USERNS,	"userns-%d"),
> +	FD_ENTRY(NETNF_CT,	"netns-ct-%d"),
> +	FD_ENTRY(NETNF_EXP,	"netns-exp-%d"),
>  
>  	[CR_FD_STATS] = {
>  		.fmt	= "stats-%s",
> diff --git a/include/image-desc.h b/include/image-desc.h
> index 90933e9..532ced8 100644
> --- a/include/image-desc.h
> +++ b/include/image-desc.h
> @@ -44,6 +44,8 @@ enum {
>  	CR_FD_IPTABLES,
>  	CR_FD_IP6TABLES,
>  	CR_FD_NETNS,
> +	CR_FD_NETNF_CT,
> +	CR_FD_NETNF_EXP,
>  	_CR_FD_NETNS_TO,
>  
>  	CR_FD_PSTREE,
> diff --git a/include/magic.h b/include/magic.h
> index 3cb3766..b11a70e 100644
> --- a/include/magic.h
> +++ b/include/magic.h
> @@ -100,6 +100,8 @@
>  #define TMPFS_DEV_MAGIC		RAW_IMAGE_MAGIC
>  #define IPTABLES_MAGIC		RAW_IMAGE_MAGIC
>  #define IP6TABLES_MAGIC		RAW_IMAGE_MAGIC
> +#define NETNF_CT_MAGIC		RAW_IMAGE_MAGIC
> +#define NETNF_EXP_MAGIC		RAW_IMAGE_MAGIC
>  
>  #define PAGES_OLD_MAGIC		PAGEMAP_MAGIC
>  #define SHM_PAGES_OLD_MAGIC	PAGEMAP_MAGIC
> diff --git a/net.c b/net.c
> index 51b3159..c611f61 100644
> --- a/net.c
> +++ b/net.c
> @@ -2,6 +2,9 @@
>  #include <sys/socket.h>
>  #include <linux/netlink.h>
>  #include <linux/rtnetlink.h>
> +#include <linux/netfilter/nfnetlink.h>
> +#include <linux/netfilter/nfnetlink_conntrack.h>
> +#include <linux/netfilter/nf_conntrack_tcp.h>
>  #include <string.h>
>  #include <net/if_arp.h>
>  #include <sys/wait.h>
> @@ -344,6 +347,121 @@ unk:
>  	return ret;
>  }
>  
> +static int dump_one_nf(struct nlmsghdr *hdr, void *arg)
> +{
> +	struct cr_img *img = arg;
> +
> +	if (lazy_image(img) && open_image_lazy(img))
> +		return -1;
> +
> +	if (write_img_buf(img, hdr, hdr->nlmsg_len))
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static int restore_nf_ct(int pid, int type)
> +{
> +	struct nlmsghdr *nlh = NULL;
> +	int exit_code = -1, sk;
> +	struct cr_img *img;
> +
> +	img = open_image(type, O_RSTR, pid);
> +	if (empty_image(img)) {
> +		close_image(img);
> +		return 0;
> +	}
> +
> +	sk = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
> +	if (sk < 0) {
> +		pr_perror("Can't open rtnl sock for net dump");
> +		goto out_img;
> +	}
> +
> +	nlh = xmalloc(sizeof(struct nlmsghdr));
> +	if (nlh == NULL)
> +		goto out;
> +
> +	while (1) {
> +		struct nlmsghdr *p;
> +		int ret;
> +
> +		ret = read_img_buf_eof(img, nlh, sizeof(struct nlmsghdr));
> +		if (ret < 0)
> +			goto out;
> +		if (ret == 0)
> +			break;
> +
> +		p = xrealloc(nlh, nlh->nlmsg_len);
> +		if (p == NULL)
> +			goto out;
> +		nlh = p;
> +
> +		ret = read_img_buf_eof(img, nlh + 1, nlh->nlmsg_len - sizeof(struct nlmsghdr));
> +		if (ret < 0)
> +			goto out;
> +		if (ret == 0) {
> +			pr_err("The image file was truncated\n");
> +			goto out;
> +		}
> +
> +		nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE;
> +		ret = do_rtnl_req(sk, nlh, nlh->nlmsg_len, NULL, NULL, NULL);
> +		if (ret)
> +			goto out;
> +	}
> +
> +	exit_code = 0;
> +out:
> +	xfree(nlh);
> +	close(sk);
> +out_img:
> +	close_image(img);
> +	return exit_code;
> +}
> +
> +static int dump_nf_ct(struct cr_imgset *fds, int type)
> +{
> +	struct cr_img *img;
> +	struct {
> +		struct nlmsghdr nlh;
> +		struct nfgenmsg g;
> +	} req;
> +	int sk, ret;
> +
> +	pr_info("Dumping netns links\n");
> +
> +	ret = sk = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
> +	if (sk < 0) {
> +		pr_perror("Can't open rtnl sock for net dump");
> +		goto out;
> +	}
> +
> +	memset(&req, 0, sizeof(req));
> +	req.nlh.nlmsg_len = sizeof(req);
> +	req.nlh.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8);
> +
> +	if (type == CR_FD_NETNF_CT)
> +		req.nlh.nlmsg_type |= IPCTNL_MSG_CT_GET;
> +	else if (type == CR_FD_NETNF_EXP)
> +		req.nlh.nlmsg_type |= IPCTNL_MSG_EXP_GET;
> +	else
> +		BUG();
> +
> +	req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
> +	req.nlh.nlmsg_pid = 0;
> +	req.nlh.nlmsg_seq = CR_NLMSG_SEQ;
> +	req.g.nfgen_family = AF_UNSPEC;
> +
> +	img = img_from_set(fds, type);
> +
> +	ret = do_rtnl_req(sk, &req, sizeof(req), dump_one_nf, NULL, img);
> +	close(sk);
> +out:
> +	return ret;
> +
> +}
> +
>  static int dump_links(struct cr_imgset *fds)
>  {
>  	int sk, ret;
> @@ -904,6 +1022,10 @@ int dump_net_ns(int ns_id)
>  		ret = dump_rule(fds);
>  	if (!ret)
>  		ret = dump_iptables(fds);
> +	if (!ret)
> +		ret = dump_nf_ct(fds, CR_FD_NETNF_CT);
> +	if (!ret)
> +		ret = dump_nf_ct(fds, CR_FD_NETNF_EXP);
>  
>  	close(ns_sysfs_fd);
>  	ns_sysfs_fd = -1;
> @@ -931,6 +1053,10 @@ int prepare_net_ns(int pid)
>  		ret = restore_rule(pid);
>  	if (!ret)
>  		ret = restore_iptables(pid);
> +	if (!ret)
> +		ret = restore_nf_ct(pid, CR_FD_NETNF_CT);
> +	if (!ret)
> +		ret = restore_nf_ct(pid, CR_FD_NETNF_EXP);
>  
>  	close_service_fd(NS_FD_OFF);
>  
> 



More information about the CRIU mailing list