[PATCH 3/4] Add IPv6 address checkpoint handler

Dan Smith danms at us.ibm.com
Thu Apr 8 10:48:51 PDT 2010


Signed-off-by: Dan Smith <danms at us.ibm.com>
---
 include/linux/checkpoint_hdr.h |    8 +++
 net/ipv6/addrconf.c            |   95 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+), 0 deletions(-)

diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index 13bf62c..98aa79c 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -804,6 +804,7 @@ struct ckpt_hdr_netdev {
 
 enum ckpt_netdev_addr_types {
 	CKPT_NETDEV_ADDR_IPV4,
+	CKPT_NETDEV_ADDR_IPV6,
 	CKPT_NETDEV_ADDR_MAX
 };
 
@@ -816,6 +817,13 @@ struct ckpt_netdev_addr {
 			__be32 inet4_mask;
 			__be32 inet4_broadcast;
 		};
+		struct {
+			struct in6_addr inet6_addr;
+			__u32  inet6_prefix_len;
+			__u32  inet6_valid_lft;
+			__u32  inet6_prefered_lft;
+			__u16  inet6_scope;
+		};
 	} __attribute__((aligned(8)));
 } __attribute__((aligned(8)));
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 143791d..75cc3b8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -87,6 +87,8 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
+#include <linux/checkpoint.h>
+
 /* Set to 3 to get tracing... */
 #define ACONF_DEBUG 2
 
@@ -4514,6 +4516,91 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
 
 EXPORT_SYMBOL(unregister_inet6addr_notifier);
 
+#ifdef CONFIG_NETNS_CHECKPOING
+static int inet6_checkpoint(struct ckpt_ctx *ctx, struct net_device *dev,
+			    int index, int max,
+			    struct ckpt_netdev_addr *addrs)
+{
+	struct inet6_dev *indev = dev->ip6_ptr;
+	struct inet6_ifaddr *addr;
+	struct ifmcaddr6 *mcaddr;
+	struct ifacaddr6 *acaddr;
+
+	for (addr = indev->addr_list; addr; addr = addr->if_next) {
+		if (ipv6_addr_scope(&addr->addr))
+			continue; /* Ignore non-global scope addresses */
+
+		addrs[index].type = CKPT_NETDEV_ADDR_IPV6;
+
+		ipv6_addr_copy(&addrs[index].inet6_addr, &addr->addr);
+
+		ckpt_debug("Checkpointed inet6: %pI6\n", &addr->addr);
+
+		addrs[index].inet6_prefix_len = addr->prefix_len;
+		addrs[index].inet6_valid_lft = addr->valid_lft;
+		addrs[index].inet6_prefered_lft = addr->prefered_lft;
+		addrs[index].inet6_scope = addr->scope;
+
+		if (++index >= max)
+			return -E2BIG;
+	}
+
+	for (mcaddr = indev->mc_list; mcaddr; mcaddr = mcaddr->next) {
+		if (ipv6_addr_scope(&mcaddr->mca_addr))
+			continue; /* Ignore non-global scope addresses */
+
+		/* TODO */
+
+		/* Multicast addresses are not supported, so do not
+		 * allow checkpoint to continue if one is assigned
+		 */
+		ckpt_debug("ipv6 multicast addresses are not supported\n");
+		return -EINVAL;
+	}
+
+	for (acaddr = indev->ac_list; acaddr; acaddr = acaddr->aca_next) {
+		if (ipv6_addr_scope(&acaddr->aca_addr))
+			continue; /* Ignore non-global scope addresses */
+
+		/* TODO */
+
+		/* Anycast addresses are not supported, so do not
+		 * allow checkpoint to continue if one is assigned
+		 */
+		ckpt_debug("ipv6 anycast addresses are not supported\n");
+		return -EINVAL;
+	}
+
+	return index;
+}
+
+static int inet6_restore(struct ckpt_ctx *ctx,
+			 struct net_device *dev,
+			 struct net *net,
+			 struct ckpt_netdev_addr *addr)
+{
+	int ret;
+
+	rtnl_lock();
+	ret = inet6_addr_add(net, dev->ifindex, &addr->inet6_addr,
+			     addr->inet6_prefix_len, IFA_F_PERMANENT,
+			     INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
+	rtnl_unlock();
+	if (ret < 0)
+		ckpt_err(ctx, ret, "Failed to set address %pI6\n",
+			 &addr->inet6_addr);
+
+	return ret;
+}
+
+struct ckpt_netdev_addr_handler inet6_addr_handler = {
+	.type =			CKPT_NETDEV_ADDR_IPV6,
+	.owner =		THIS_MODULE,
+	.checkpoint_addr =	inet6_checkpoint,
+	.restore_addr =		inet6_restore,
+};
+#endif /* CONFIG_NETNS_CHECKPOINT */
+
 /*
  *	Init / cleanup code
  */
@@ -4572,6 +4659,10 @@ int __init addrconf_init(void)
 
 	ipv6_addr_label_rtnl_register();
 
+#ifdef CONFIG_NETNS_CHECKPOINT
+	ckpt_netdev_addr_register(&inet6_addr_handler);
+#endif
+
 	return 0;
 errout:
 	unregister_netdevice_notifier(&ipv6_dev_notf);
@@ -4590,6 +4681,10 @@ void addrconf_cleanup(void)
 	unregister_netdevice_notifier(&ipv6_dev_notf);
 	unregister_pernet_subsys(&addrconf_ops);
 
+#ifdef CONFIG_NETNS_CHECKPOINT
+	ckpt_netdev_addr_unregister(&inet6_addr_handler);
+#endif
+
 	rtnl_lock();
 
 	/* clean dev list */
-- 
1.6.2.5



More information about the Containers mailing list