[Devel] [PATCH CRIU] dump/restore: Supported ipset

Alexander Mikhalitsyn alexander.mikhalitsyn at virtuozzo.com
Thu Jan 30 11:56:20 MSK 2020


On Wed, 29 Jan 2020 20:04:15 +0300
Valeriy Vdovin <valeriy.vdovin at virtuozzo.com> wrote:

> https://jira.sw.ru/browse/PSBM-100083
> 
> Added ipset dump/restore functionality. At dump operation it calls
> 'ipset save' and stores result into raw text image. At restore
> it restores ipset by calling 'ipset restore'. This is done prior
> to restoring iptables.
> 
> Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
> ---
>  criu/image-desc.c              |  1 +
>  criu/include/image-desc.h      |  1 +
>  criu/include/magic.h           |  1 +
>  criu/net.c                     | 43 +++++++++++++++++++++++++++++++++++
>  test/zdtm/static/Makefile      |  1 +
>  test/zdtm/static/netns-ipset.c | 51 ++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 98 insertions(+)
>  create mode 100644 test/zdtm/static/netns-ipset.c
> 
> diff --git a/criu/image-desc.c b/criu/image-desc.c
> index 04e827d..475d176 100644
> --- a/criu/image-desc.c
> +++ b/criu/image-desc.c
> @@ -74,6 +74,7 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
>  	FD_ENTRY_F(ROUTE,	"route-%u", O_NOBUF),
>  	FD_ENTRY_F(ROUTE6,	"route6-%u", O_NOBUF),
>  	FD_ENTRY_F(RULE,	"rule-%u", O_NOBUF),
> +	FD_ENTRY_F(IPSET,	"ipset-%u", O_NOBUF),
>  	FD_ENTRY_F(IPTABLES,	"iptables-%u", O_NOBUF),
>  	FD_ENTRY_F(IP6TABLES,	"ip6tables-%u", O_NOBUF),
>  	FD_ENTRY_F(NFTABLES,	"nftables-%u", O_NOBUF),
> diff --git a/criu/include/image-desc.h b/criu/include/image-desc.h
> index 1015191..d875722 100644
> --- a/criu/include/image-desc.h
> +++ b/criu/include/image-desc.h
> @@ -40,6 +40,7 @@ enum {
>  	CR_FD_ROUTE,
>  	CR_FD_ROUTE6,
>  	CR_FD_RULE,
> +	CR_FD_IPSET,
>  	CR_FD_IPTABLES,
>  	CR_FD_IP6TABLES,
>  	CR_FD_NFTABLES,
> diff --git a/criu/include/magic.h b/criu/include/magic.h
> index 1a583f4..32421ed 100644
> --- a/criu/include/magic.h
> +++ b/criu/include/magic.h
> @@ -101,6 +101,7 @@
>  #define RULE_MAGIC		RAW_IMAGE_MAGIC
>  #define TMPFS_IMG_MAGIC		RAW_IMAGE_MAGIC
>  #define TMPFS_DEV_MAGIC		RAW_IMAGE_MAGIC
> +#define IPSET_MAGIC		RAW_IMAGE_MAGIC
>  #define IPTABLES_MAGIC		RAW_IMAGE_MAGIC
>  #define IP6TABLES_MAGIC		RAW_IMAGE_MAGIC
>  #define NFTABLES_MAGIC		RAW_IMAGE_MAGIC
> diff --git a/criu/net.c b/criu/net.c
> index 8ee560c..dccc491 100644
> --- a/criu/net.c
> +++ b/criu/net.c
> @@ -1775,6 +1775,26 @@ static int restore_links()
>  	return 0;
>  }
>  
> +static int run_ipset_tool(char *arg1, char *arg2, char *arg3, int fdin, int fdout)
> +{
> +	char *cmd;
> +	int ret;
> +
> +	pr_debug("\tRunning ipset %s %s %s \n", arg1, arg2, arg3 ? : "");
> +
> +	cmd = getenv("CR_IPSET_TOOL");
> +	if (!cmd)
> +		cmd = "ipset";
> +
> +	ret = cr_system(fdin, fdout, -1, cmd,
> +				(char *[]) { cmd, arg1, arg2, arg3, NULL }, 0);
> +	if (ret) {
> +		pr_err("ipset tool failed on %s %s %s \n", arg1, arg2, arg3 ? : "");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
>  
>  static int run_ip_tool(char *arg1, char *arg2, char *arg3, char *arg4, int fdin, int fdout, unsigned flags)
>  {
> @@ -1845,6 +1865,7 @@ static int iptables_tool_dump(char *def_cmd, int fdin, int fdout)
>  	return run_iptables_tool(def_cmd, fdin, fdout);
>  }
>  
> +
is it needed here?
>  static inline int dump_ifaddr(struct cr_imgset *fds)
>  {
>  	struct cr_img *img = img_from_set(fds, CR_FD_IFADDR);
> @@ -1891,6 +1912,13 @@ static inline int dump_rule(struct cr_imgset *fds)
>  	return 0;
>  }
>  
> +static inline int dump_ipset(struct cr_imgset *fds)
> +{
> +	struct cr_img *img;
> +	img = img_from_set(fds, CR_FD_IPSET);
> +	return run_ipset_tool("save", 0, 0, -1, img_raw_fd(img));
> +}
> +
>  static inline int dump_iptables(struct cr_imgset *fds)
>  {
>  	struct cr_img *img;
> @@ -2129,6 +2157,17 @@ static int prepare_xtable_lock()
>  	return 0;
>  }
>  
> +static inline int restore_ipset(int pid)
> +{
> +	struct cr_img *img;
> +	img = open_image(CR_FD_IPSET, O_RSTR, pid);
> +	if (img == NULL)
> +		return -1;
> +	if (empty_image(img))
close_image(img) ?
> +		return 0;
> +	return run_ipset_tool("restore", 0, 0, img_raw_fd(img), -1);
here, you also need to close_image(img).
> +}
> +
>  static inline int restore_iptables(int pid)
>  {
>  	int ret = -1;
> @@ -2446,6 +2485,8 @@ int dump_net_ns(struct ns_id *ns)
>  		if (!ret)
>  			ret = dump_rule(fds);
>  		if (!ret)
> +			ret = dump_ipset(fds);
> +		if (!ret)
>  			ret = dump_iptables(fds);
>  		if (!ret)
>  			ret = dump_nftables(fds);
> @@ -2541,6 +2582,8 @@ static int prepare_net_ns_second_stage(struct ns_id *ns)
>  		if (!ret)
>  			ret = restore_rule(nsid);
>  		if (!ret)
> +			ret = restore_ipset(nsid);
> +		if (!ret)
>  			ret = restore_iptables(nsid);
>  		if (!ret)
>  			ret = restore_nftables(nsid);
> diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
> index 28717b1..bdef4d0 100644
> --- a/test/zdtm/static/Makefile
> +++ b/test/zdtm/static/Makefile
> @@ -143,6 +143,7 @@ TST_NOFILE	:=				\
>  		poll				\
>  		mountpoints			\
>  		netns				\
> +		netns-ipset			\
>  		netns-dev			\
>  		session01			\
>  		session02			\
> diff --git a/test/zdtm/static/netns-ipset.c b/test/zdtm/static/netns-ipset.c
> new file mode 100644
> index 0000000..2650685
> --- /dev/null
> +++ b/test/zdtm/static/netns-ipset.c
> @@ -0,0 +1,51 @@
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include "zdtmtst.h"
> +
> +const char *test_doc	= "Check that ipset are dumped and restored correctly";
> +
> +#define RUN_OR_ERR(cmd, failmsg) if (system(cmd)) { pr_perror(failmsg); return -1; }
> +#define RUN_OR_FAIL(cmd, failmsg) if (system(cmd)) { fail(failmsg); return -1; }
> +
> +int main(int argc, char **argv)
> +{
> +	char dump_ipset_old[]    = "ipset save > ipset.old";
> +	char dump_ipset_new[]    = "ipset save > ipset.new";
> +	char dump_iptables_old[] = "iptables -L INPUT 1 > iptables.old";
> +	char dump_iptables_new[] = "iptables -L INPUT 1 > iptables.new";
> +	char cmp_ipset[]         = "diff ipset.old ipset.new";
> +	char cmp_iptables[]      = "diff iptables.old iptables.new";
> +
> +	test_init(argc, argv);
> +
> +	/* create ipset group and add some ip addresses to it */
> +	RUN_OR_ERR("ipset create testgroup nethash", "Can't create test ipset");
> +	RUN_OR_ERR("ipset add testgroup 127.0.0.1/8", "Can't add ip addresses to ipset group");
what about ipv6?
> +
> +	/* Use testgroup in iptables rule */
> +	RUN_OR_ERR("iptables -I INPUT 1 -p tcp -m set --match-set testgroup src,dst -j ACCEPT",
> +		"Failed to setup iptables rule with ipset group");
> +
> +	/* dump ipset and iptables states to text files */
> +	RUN_OR_ERR(dump_iptables_old, "Can't save iptables rules.");
> +	RUN_OR_ERR(dump_ipset_old   , "Can't save ipset list.");
> +
> +	test_daemon();
> +	test_waitsig();
> +
> +	/* again dump ipset and iptables states to other text files */
> +	RUN_OR_ERR(dump_iptables_new, "Can't dump restored iptables rules.");
> +	RUN_OR_ERR(dump_ipset_new   , "Can't save restored ipset list to file.");
> +
> +	/* compare original and restored iptables rules */
> +	RUN_OR_FAIL(cmp_iptables, "iptables rules differ");
> +
> +	/* compare original and restored ipset rules */
> +	RUN_OR_FAIL(cmp_ipset, "ipset lists differ");
> +
> +	pass();
> +	return 0;
> +}
> -- 
> 1.8.3.1
> 


More information about the Devel mailing list