[lxc-devel] [lxd/master] Clean up old DHCPv6 leases when IPv6 static IP changed.

tomponline on Github lxc-bot at linuxcontainers.org
Fri Jul 5 12:42:59 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190705/dbb13973/attachment.bin>
-------------- next part --------------
From b4545460dc3b6e59afc9ddca6b84f2f847264072 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 5 Jul 2019 13:37:13 +0100
Subject: [PATCH 1/2] networks/utils: Updates networkClearLease to support a
 mode flag

Allows specifying whether networkClearLease should clear only IPv4 or IPv6 leases.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/networks_utils.go | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/lxd/networks_utils.go b/lxd/networks_utils.go
index d94b63d17e..b4fa182a91 100644
--- a/lxd/networks_utils.go
+++ b/lxd/networks_utils.go
@@ -1568,7 +1568,13 @@ func networkGetMacSlice(hwaddr string) []string {
 	return buf
 }
 
-func networkClearLease(name string, network string, hwaddr string) error {
+const (
+	clearLeaseAll = iota
+	clearLeaseIPv4Only
+	clearLeaseIPv6Only
+)
+
+func networkClearLease(name string, network string, hwaddr string, mode int) error {
 	leaseFile := shared.VarPath("networks", network, "dnsmasq.leases")
 
 	// Check that we are in fact running a dnsmasq for the network
@@ -1624,7 +1630,7 @@ func networkClearLease(name string, network string, hwaddr string) error {
 
 		// Handle lease lines
 		if fieldsLen == 5 {
-			if srcMAC.String() == fields[1] { // Handle IPv4 leases by matching MAC address to lease.
+			if (mode == clearLeaseAll || mode == clearLeaseIPv4Only) && srcMAC.String() == fields[1] { // Handle IPv4 leases by matching MAC address to lease.
 				srcIP := net.ParseIP(fields[2])
 
 				if dstIPv4 == nil {
@@ -1636,7 +1642,7 @@ func networkClearLease(name string, network string, hwaddr string) error {
 				if err != nil {
 					logger.Errorf("Failed to release DHCPv4 lease for container \"%s\", IP \"%s\", MAC \"%s\", %v", name, srcIP, srcMAC, err)
 				}
-			} else if name == fields[3] { // Handle IPv6 addresses by matching hostname to lease.
+			} else if (mode == clearLeaseAll || mode == clearLeaseIPv6Only) && name == fields[3] { // Handle IPv6 addresses by matching hostname to lease.
 				IAID := fields[1]
 				srcIP := net.ParseIP(fields[2])
 				DUID := fields[4]

From 605eed1ee71fc3fd9f5bc8b69c31b4dc53faeaa6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 5 Jul 2019 13:38:21 +0100
Subject: [PATCH 2/2] container/lxc: Updates setupHostVethDevice to remove old
 DHCPv6 leases on IP change

When a static IPv6 address is changed on a bridged nic for managed networks the old DHCPv6 leases are cleared.

The host side interface of the veth pair is also bounced to allow the container to detect the change in carrier and re-apply for the lease.

Fixes #5891

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_lxc.go | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 871631a9ab..db1875ae52 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -621,6 +621,9 @@ type containerLXC struct {
 	op *operation
 
 	expiryDate time.Time
+
+	// Interfaces to bring down then up when changing dnsmasq config.
+	dnsmasqDownUpIfaces []string
 }
 
 func (c *containerLXC) createOperation(action string, reusable bool, reuse bool) (*lxcContainerOperation, error) {
@@ -3793,6 +3796,15 @@ func (c *containerLXC) setupHostVethDevice(deviceName string, device types.Devic
 		return err
 	}
 
+	// If an IPv6 address has changed, flush all existing IPv6 leases for container.
+	if device["nictype"] == "bridged" && oldDevice["nictype"] == "bridged" && device["ipv6.address"] != oldDevice["ipv6.address"] {
+		networkClearLease(c.Name(), device["parent"], device["hwaddr"], clearLeaseIPv6Only)
+
+		// Queue the interface to be bounched once dnsmasq config has been reloaded to give
+		// container a chance to detect the change and re-apply for the updated leases.
+		c.dnsmasqDownUpIfaces = append(c.dnsmasqDownUpIfaces, device["host_name"])
+	}
+
 	return nil
 }
 
@@ -4382,7 +4394,7 @@ func (c *containerLXC) Delete() error {
 				continue
 			}
 
-			err = networkClearLease(c.name, m["parent"], m["hwaddr"])
+			err = networkClearLease(c.name, m["parent"], m["hwaddr"], clearLeaseAll)
 			if err != nil {
 				logger.Error("Failed to delete DHCP lease", log.Ctx{"name": c.Name(), "err": err, "device": k, "hwaddr": m["hwaddr"]})
 			}
@@ -5796,6 +5808,21 @@ func (c *containerLXC) Update(args db.ContainerArgs, userRequested bool) error {
 
 	if needsUpdate {
 		networkUpdateStatic(c.state, "")
+
+		// After dnsmasq config is updated and reloaded, reset any interfaces requested,
+		// this will cause the container to have a carrier lost/carrier gained event, and
+		// some DHCP clients (such as systemd) will then re-apply for their leases allowing
+		// static IP changes to take effect.
+		for _, hostName := range c.dnsmasqDownUpIfaces {
+			_, err := shared.RunCommand("ip", "link", "set", hostName, "down")
+			if err != nil {
+				return err
+			}
+			_, err = shared.RunCommand("ip", "link", "set", hostName, "up")
+			if err != nil {
+				return err
+			}
+		}
 	}
 
 	// Send devlxd notifications


More information about the lxc-devel mailing list