[lxc-devel] [lxd/master] Network: Splits host veth helper functions

tomponline on Github lxc-bot at linuxcontainers.org
Wed Jul 29 14:12:29 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 543 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200729/f036d4c1/attachment.bin>
-------------- next part --------------
From 0cd7e953d6bb9d3e8003befd18326ca7099634fe Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 27 Jul 2020 17:08:37 +0100
Subject: [PATCH 1/9] lxd/network/driver/common: Adds Create function no-op

Most network types don't need this.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/network/driver_common.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lxd/network/driver_common.go b/lxd/network/driver_common.go
index bc26dcaed3..584d90ec7f 100644
--- a/lxd/network/driver_common.go
+++ b/lxd/network/driver_common.go
@@ -362,6 +362,11 @@ func (n *common) delete(clusterNotification bool) error {
 	return nil
 }
 
+// Create is a no-op.
+func (n *common) Create(clusterNotification bool) error {
+	return nil
+}
+
 // HandleHeartbeat is a no-op.
 func (n *common) HandleHeartbeat(heartbeatData *cluster.APIHeartbeat) error {
 	return nil

From 3972cf6937e9e57568d9b49e838cf0f210792520 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 27 Jul 2020 17:09:00 +0100
Subject: [PATCH 2/9] lxd/network/network/interface: Adds Create function

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/network/network_interface.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/network/network_interface.go b/lxd/network/network_interface.go
index cedb68ef31..0bba1fd637 100644
--- a/lxd/network/network_interface.go
+++ b/lxd/network/network_interface.go
@@ -25,6 +25,7 @@ type Network interface {
 	DHCPv6Ranges() []DHCPRange
 
 	// Actions.
+	Create(clusterNotification bool) error
 	Start() error
 	Stop() error
 	Rename(name string) error

From 0a784e9bbbd4ce6686c8ec356b18ff63d14866b6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 27 Jul 2020 17:09:52 +0100
Subject: [PATCH 3/9] lxd/networks: Adds call to network Create in
 doNetworksCreate

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

diff --git a/lxd/networks.go b/lxd/networks.go
index c5c25ce106..7f7913e4ec 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -355,6 +355,12 @@ func doNetworksCreate(d *Daemon, req api.NetworksPost, clusterNotification bool)
 		return err
 	}
 
+	// Run initial creation setup for the network driver.
+	err = n.Create(clusterNotification)
+	if err != nil {
+		return err
+	}
+
 	err = n.Start()
 	if err != nil {
 		n.Delete(clusterNotification)

From ebdd0ae69448260a35e26c45ec70ed92bdcd1519 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 29 Jul 2020 12:36:23 +0100
Subject: [PATCH 4/9] lxd/device/device/utils/network: Adds networkDHCPValidIP

For use with multiple NIC types (bridged and ovn).

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/device_utils_network.go | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/lxd/device/device_utils_network.go b/lxd/device/device_utils_network.go
index 01306bd716..c88341c5fe 100644
--- a/lxd/device/device_utils_network.go
+++ b/lxd/device/device_utils_network.go
@@ -1,10 +1,12 @@
 package device
 
 import (
+	"bytes"
 	"crypto/rand"
 	"encoding/hex"
 	"fmt"
 	"io/ioutil"
+	"net"
 	"strconv"
 	"strings"
 	"sync"
@@ -603,3 +605,23 @@ func networkInterfaceBindWait(ifName string) error {
 
 	return fmt.Errorf("Bind of interface %q took too long", ifName)
 }
+
+// networkDHCPValidIP returns whether an IP fits inside one of the supplied DHCP ranges and subnet.
+func networkDHCPValidIP(subnet *net.IPNet, ranges []network.DHCPRange, IP net.IP) bool {
+	inSubnet := subnet.Contains(IP)
+	if !inSubnet {
+		return false
+	}
+
+	if len(ranges) > 0 {
+		for _, IPRange := range ranges {
+			if bytes.Compare(IP, IPRange.Start) >= 0 && bytes.Compare(IP, IPRange.End) <= 0 {
+				return true
+			}
+		}
+	} else if inSubnet {
+		return true
+	}
+
+	return false
+}

From 04495ec8f82b939be9a8e1f0becc5517d6f2bd46 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 29 Jul 2020 12:36:59 +0100
Subject: [PATCH 5/9] lxd/device/nic/bridged: Removes networkDHCPValidIP

Updates usage to package level networkDHCPValidIP.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/nic_bridged.go | 34 +++++++---------------------------
 1 file changed, 7 insertions(+), 27 deletions(-)

diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index aaa375f3af..c509126c75 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -109,7 +109,7 @@ func (d *nicBridged) validateConfig(instConf instance.ConfigReader) error {
 
 			// Check the static IP supplied is valid for the linked network. It should be part of the
 			// network's subnet, but not necessarily part of the dynamic allocation ranges.
-			if !d.networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv4.address"])) {
+			if !networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv4.address"])) {
 				return fmt.Errorf("Device IP address %q not within network %q subnet", d.config["ipv4.address"], d.config["network"])
 			}
 		}
@@ -127,7 +127,7 @@ func (d *nicBridged) validateConfig(instConf instance.ConfigReader) error {
 
 			// Check the static IP supplied is valid for the linked network. It should be part of the
 			// network's subnet, but not necessarily part of the dynamic allocation ranges.
-			if !d.networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv6.address"])) {
+			if !networkDHCPValidIP(subnet, nil, net.ParseIP(d.config["ipv6.address"])) {
 				return fmt.Errorf("Device IP address %q not within network %q subnet", d.config["ipv6.address"], d.config["network"])
 			}
 		}
@@ -208,7 +208,7 @@ func (d *nicBridged) validateEnvironment() error {
 	}
 
 	if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["parent"])) {
-		return fmt.Errorf("Parent device '%s' doesn't exist", d.config["parent"])
+		return fmt.Errorf("Parent device %q doesn't exist", d.config["parent"])
 	}
 
 	return nil
@@ -715,7 +715,7 @@ func (d *nicBridged) allocateFilterIPs(n network.Network) (net.IP, net.IP, error
 		// Check the existing static DHCP IP is still valid in the subnet & ranges, if not
 		// then we'll need to generate a new one.
 		ranges := n.DHCPv4Ranges()
-		if d.networkDHCPValidIP(subnet, ranges, curIPv4.IP.To4()) {
+		if networkDHCPValidIP(subnet, ranges, curIPv4.IP.To4()) {
 			IPv4 = curIPv4.IP.To4()
 		}
 	}
@@ -730,7 +730,7 @@ func (d *nicBridged) allocateFilterIPs(n network.Network) (net.IP, net.IP, error
 		// Check the existing static DHCP IP is still valid in the subnet & ranges, if not
 		// then we'll need to generate a new one.
 		ranges := n.DHCPv6Ranges()
-		if d.networkDHCPValidIP(subnet, ranges, curIPv6.IP.To16()) {
+		if networkDHCPValidIP(subnet, ranges, curIPv6.IP.To16()) {
 			IPv6 = curIPv6.IP.To16()
 		}
 	}
@@ -787,26 +787,6 @@ func (d *nicBridged) allocateFilterIPs(n network.Network) (net.IP, net.IP, error
 	return IPv4, IPv6, nil
 }
 
-// networkDHCPValidIP returns whether an IP fits inside one of the supplied DHCP ranges and subnet.
-func (d *nicBridged) networkDHCPValidIP(subnet *net.IPNet, ranges []network.DHCPRange, IP net.IP) bool {
-	inSubnet := subnet.Contains(IP)
-	if !inSubnet {
-		return false
-	}
-
-	if len(ranges) > 0 {
-		for _, IPRange := range ranges {
-			if bytes.Compare(IP, IPRange.Start) >= 0 && bytes.Compare(IP, IPRange.End) <= 0 {
-				return true
-			}
-		}
-	} else if inSubnet {
-		return true
-	}
-
-	return false
-}
-
 // getDHCPFreeIPv4 attempts to find a free IPv4 address for the device.
 // It first checks whether there is an existing allocation for the instance.
 // If no previous allocation, then a free IP is picked from the ranges configured.
@@ -826,7 +806,7 @@ func (d *nicBridged) getDHCPFreeIPv4(usedIPs map[[4]byte]dnsmasq.DHCPAllocation,
 	// Lets see if there is already an allocation for our device and that it sits within subnet.
 	// If there are custom DHCP ranges defined, check also that the IP falls within one of the ranges.
 	for _, DHCP := range usedIPs {
-		if (ctName == DHCP.Name || bytes.Compare(MAC, DHCP.MAC) == 0) && d.networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) {
+		if (ctName == DHCP.Name || bytes.Compare(MAC, DHCP.MAC) == 0) && networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) {
 			return DHCP.IP, nil
 		}
 	}
@@ -898,7 +878,7 @@ func (d *nicBridged) getDHCPFreeIPv6(usedIPs map[[16]byte]dnsmasq.DHCPAllocation
 	// allocations using instance name. If there are custom DHCP ranges defined, check also
 	// that the IP falls within one of the ranges.
 	for _, DHCP := range usedIPs {
-		if ctName == DHCP.Name && d.networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) {
+		if ctName == DHCP.Name && networkDHCPValidIP(subnet, dhcpRanges, DHCP.IP) {
 			return DHCP.IP, nil
 		}
 	}

From 92729611c7cbb827a60489d827233871b499f6d9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 29 Jul 2020 14:32:47 +0100
Subject: [PATCH 6/9] lxd/device/device/utils/networks: Splits
 networkSetupHostVethDevice into multiple functions

So that each specific host-side veth feature can be used in isolation without having to use all of them.

This supports applying host-veth limits for OVN NICs without needing the static routes functionality (that will be in OVN itself).

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/device_utils_network.go | 59 +++++++++++++-----------------
 1 file changed, 25 insertions(+), 34 deletions(-)

diff --git a/lxd/device/device_utils_network.go b/lxd/device/device_utils_network.go
index c88341c5fe..71295a098d 100644
--- a/lxd/device/device_utils_network.go
+++ b/lxd/device/device_utils_network.go
@@ -337,46 +337,23 @@ func networkCreateTap(hostName string, m deviceConfig.Device) error {
 	return nil
 }
 
-// networkSetupHostVethDevice configures a nic device's host side veth settings.
-func networkSetupHostVethDevice(s *state.State, device deviceConfig.Device, oldDevice deviceConfig.Device, v map[string]string) error {
-	// If not configured, check if volatile data contains the most recently added host_name.
-	if device["host_name"] == "" {
-		device["host_name"] = v["host_name"]
-	}
-
-	// If not configured, check if volatile data contains the most recently added hwaddr.
-	if device["hwaddr"] == "" {
-		device["hwaddr"] = v["hwaddr"]
-	}
-
+// networkSetupHostVethRoutes configures a nic device's host side veth routes.
+// Accepts an optional oldDevice that will have its old host routes removed before adding the new device routes.
+// This allows live update of a veth device.
+func networkSetupHostVethRoutes(s *state.State, device deviceConfig.Device, oldDevice deviceConfig.Device, v map[string]string) error {
 	// Check whether host device resolution succeeded.
 	if device["host_name"] == "" {
-		return fmt.Errorf("Failed to find host side veth name for device \"%s\"", device["name"])
-	}
-
-	// Refresh tc limits.
-	err := networkSetVethLimits(device)
-	if err != nil {
-		return err
+		return fmt.Errorf("Failed to find host side veth name for device %q", device["name"])
 	}
 
 	// If oldDevice provided, remove old routes if any remain.
 	if oldDevice != nil {
-		// If not configured, copy the volatile host_name into old device to support live updates.
-		if oldDevice["host_name"] == "" {
-			oldDevice["host_name"] = v["host_name"]
-		}
-
-		// If not configured, copy the volatile hwaddr into old device to support live updates.
-		if oldDevice["hwaddr"] == "" {
-			oldDevice["hwaddr"] = v["hwaddr"]
-		}
-
+		networkVethFillFromVolatile(oldDevice, v)
 		networkRemoveVethRoutes(s, oldDevice)
 	}
 
 	// Setup static routes to container.
-	err = networkSetVethRoutes(s, device)
+	err := networkSetVethRoutes(s, device)
 	if err != nil {
 		return err
 	}
@@ -384,6 +361,19 @@ func networkSetupHostVethDevice(s *state.State, device deviceConfig.Device, oldD
 	return nil
 }
 
+// networkVethFillFromVolatile fills veth host_name and hwaddr fields from volatile if not set in device config.
+func networkVethFillFromVolatile(device deviceConfig.Device, volatile map[string]string) {
+	// If not configured, check if volatile data contains the most recently added host_name.
+	if device["host_name"] == "" {
+		device["host_name"] = volatile["host_name"]
+	}
+
+	// If not configured, check if volatile data contains the most recently added hwaddr.
+	if device["hwaddr"] == "" {
+		device["hwaddr"] = volatile["hwaddr"]
+	}
+}
+
 // networkSetVethRoutes applies any static routes configured from the host to the container nic.
 func networkSetVethRoutes(s *state.State, m deviceConfig.Device) error {
 	// Decide whether the route should point to the veth parent or the bridge parent.
@@ -476,13 +466,14 @@ func networkRemoveVethRoutes(s *state.State, m deviceConfig.Device) {
 	}
 }
 
-// networkSetVethLimits applies any network rate limits to the veth device specified in the config.
-func networkSetVethLimits(m deviceConfig.Device) error {
+// networkSetupHostVethLimits applies any network rate limits to the veth device specified in the config.
+func networkSetupHostVethLimits(m deviceConfig.Device) error {
 	var err error
 
 	veth := m["host_name"]
-	if !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", veth)) {
-		return fmt.Errorf("Unknown or missing host side veth: %s", veth)
+
+	if veth == "" || !shared.PathExists(fmt.Sprintf("/sys/class/net/%s", veth)) {
+		return fmt.Errorf("Unknown or missing host side veth device %q", veth)
 	}
 
 	// Apply max limit

From 292c6df3d7d958f47dcdf9f3d8cbd4c672c9b889 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 29 Jul 2020 14:35:42 +0100
Subject: [PATCH 7/9] lxd/device/nic/bridged: networkVethFillFromVolatile usage
 and other host-veth functions

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/nic_bridged.go | 40 +++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index c509126c75..1f77dd13b9 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -266,8 +266,17 @@ func (d *nicBridged) Start() (*deviceConfig.RunConfig, error) {
 
 	revert.Add(func() { NetworkRemoveInterface(saveData["host_name"]) })
 
-	// Apply and host-side limits and routes.
-	err = networkSetupHostVethDevice(d.state, d.config, nil, saveData)
+	// Populate device config with volatile fields if needed.
+	networkVethFillFromVolatile(d.config, saveData)
+
+	// Apply host-side routes.
+	err = networkSetupHostVethRoutes(d.state, d.config, nil, saveData)
+	if err != nil {
+		return nil, err
+	}
+
+	// Apply host-side limits.
+	err = networkSetupHostVethLimits(d.config)
 	if err != nil {
 		return nil, err
 	}
@@ -351,6 +360,9 @@ func (d *nicBridged) Update(oldDevices deviceConfig.Devices, isRunning bool) err
 
 	v := d.volatileGet()
 
+	// Populate device config with volatile fields if needed.
+	networkVethFillFromVolatile(d.config, v)
+
 	// If instance is running, apply host side limits and filters first before rebuilding
 	// dnsmasq config below so that existing config can be used as part of the filter removal.
 	if isRunning {
@@ -359,8 +371,14 @@ func (d *nicBridged) Update(oldDevices deviceConfig.Devices, isRunning bool) err
 			return err
 		}
 
-		// Apply and host-side limits and routes.
-		err = networkSetupHostVethDevice(d.state, d.config, oldConfig, v)
+		// Apply host-side routes.
+		err = networkSetupHostVethRoutes(d.state, d.config, oldConfig, v)
+		if err != nil {
+			return err
+		}
+
+		// Apply host-side limits.
+		err = networkSetupHostVethLimits(d.config)
 		if err != nil {
 			return err
 		}
@@ -381,12 +399,12 @@ func (d *nicBridged) Update(oldDevices deviceConfig.Devices, isRunning bool) err
 	// If an IPv6 address has changed, if the instance is running we should bounce the host-side
 	// veth interface to give the instance a chance to detect the change and re-apply for an
 	// updated lease with new IP address.
-	if d.config["ipv6.address"] != oldConfig["ipv6.address"] && v["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", v["host_name"])) {
-		_, err := shared.RunCommand("ip", "link", "set", v["host_name"], "down")
+	if d.config["ipv6.address"] != oldConfig["ipv6.address"] && d.config["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["host_name"])) {
+		_, err := shared.RunCommand("ip", "link", "set", d.config["host_name"], "down")
 		if err != nil {
 			return err
 		}
-		_, err = shared.RunCommand("ip", "link", "set", v["host_name"], "up")
+		_, err = shared.RunCommand("ip", "link", "set", d.config["host_name"], "up")
 		if err != nil {
 			return err
 		}
@@ -412,13 +430,7 @@ func (d *nicBridged) postStop() error {
 
 	v := d.volatileGet()
 
-	if d.config["host_name"] == "" {
-		d.config["host_name"] = v["host_name"]
-	}
-
-	if d.config["hwaddr"] == "" {
-		d.config["hwaddr"] = v["hwaddr"]
-	}
+	networkVethFillFromVolatile(d.config, v)
 
 	if d.config["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["host_name"])) {
 		// Detach host-side end of veth pair from bridge (required for openvswitch particularly).

From 90d08afc0fd96355dd30425388caf8be2584705b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 29 Jul 2020 14:36:54 +0100
Subject: [PATCH 8/9] lxd/device/nic/p2p: networkVethFillFromVolatile usage and
 other host-veth helper functions

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/nic_p2p.go | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/lxd/device/nic_p2p.go b/lxd/device/nic_p2p.go
index 341ae1ea13..5f5b7ef089 100644
--- a/lxd/device/nic_p2p.go
+++ b/lxd/device/nic_p2p.go
@@ -6,6 +6,7 @@ import (
 	deviceConfig "github.com/lxc/lxd/lxd/device/config"
 	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/instance/instancetype"
+	"github.com/lxc/lxd/lxd/revert"
 	"github.com/lxc/lxd/shared"
 )
 
@@ -61,6 +62,9 @@ func (d *nicP2P) Start() (*deviceConfig.RunConfig, error) {
 		return nil, err
 	}
 
+	revert := revert.New()
+	defer revert.Fail()
+
 	saveData := make(map[string]string)
 	saveData["host_name"] = d.config["host_name"]
 
@@ -84,10 +88,20 @@ func (d *nicP2P) Start() (*deviceConfig.RunConfig, error) {
 		return nil, err
 	}
 
-	// Apply and host-side limits and routes.
-	err = networkSetupHostVethDevice(d.state, d.config, nil, saveData)
+	revert.Add(func() { NetworkRemoveInterface(saveData["host_name"]) })
+
+	// Populate device config with volatile fields if needed.
+	networkVethFillFromVolatile(d.config, saveData)
+
+	// Apply host-side routes.
+	err = networkSetupHostVethRoutes(d.state, d.config, nil, saveData)
+	if err != nil {
+		return nil, err
+	}
+
+	// Apply host-side limits.
+	err = networkSetupHostVethLimits(d.config)
 	if err != nil {
-		NetworkRemoveInterface(saveData["host_name"])
 		return nil, err
 	}
 
@@ -112,6 +126,7 @@ func (d *nicP2P) Start() (*deviceConfig.RunConfig, error) {
 			}...)
 	}
 
+	revert.Success()
 	return &runConf, nil
 }
 
@@ -130,8 +145,17 @@ func (d *nicP2P) Update(oldDevices deviceConfig.Devices, isRunning bool) error {
 
 	v := d.volatileGet()
 
-	// Apply and host-side limits and routes.
-	err = networkSetupHostVethDevice(d.state, d.config, oldConfig, v)
+	// Populate device config with volatile fields if needed.
+	networkVethFillFromVolatile(d.config, v)
+
+	// Apply host-side routes.
+	err = networkSetupHostVethRoutes(d.state, d.config, oldConfig, v)
+	if err != nil {
+		return err
+	}
+
+	// Apply host-side limits.
+	err = networkSetupHostVethLimits(d.config)
 	if err != nil {
 		return err
 	}
@@ -156,9 +180,7 @@ func (d *nicP2P) postStop() error {
 
 	v := d.volatileGet()
 
-	if d.config["host_name"] == "" {
-		d.config["host_name"] = v["host_name"]
-	}
+	networkVethFillFromVolatile(d.config, v)
 
 	if d.config["host_name"] != "" && shared.PathExists(fmt.Sprintf("/sys/class/net/%s", d.config["host_name"])) {
 		// Removing host-side end of veth pair will delete the peer end too.

From 1ea421ead29df66024cb45f52d33a9f3a49ca822 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 29 Jul 2020 14:37:56 +0100
Subject: [PATCH 9/9] lxd/device/nic/routed: networkVethFillFromVolatile usage
 and other host-veth helper functions

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/device/nic_routed.go | 125 ++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 62 deletions(-)

diff --git a/lxd/device/nic_routed.go b/lxd/device/nic_routed.go
index 9eaa638eb3..9a7f963e4c 100644
--- a/lxd/device/nic_routed.go
+++ b/lxd/device/nic_routed.go
@@ -307,9 +307,11 @@ func (d *nicRouted) Update(oldDevices deviceConfig.Devices, isRunning bool) erro
 			return err
 		}
 
+		// Populate device config with volatile fields if needed.
+		networkVethFillFromVolatile(d.config, v)
+
 		// Apply host-side limits.
-		d.config["host_name"] = v["host_name"]
-		err = networkSetVethLimits(d.config)
+		err = networkSetupHostVethLimits(d.config)
 		if err != nil {
 			return err
 		}
@@ -322,77 +324,76 @@ func (d *nicRouted) Update(oldDevices deviceConfig.Devices, isRunning bool) erro
 func (d *nicRouted) postStart() error {
 	v := d.volatileGet()
 
-	// If volatile host_name is defined (and it should be), then configure the host-side interface.
-	if v["host_name"] != "" {
-		// Apply host-side limits.
-		d.config["host_name"] = v["host_name"]
-		err := networkSetVethLimits(d.config)
-		if err != nil {
-			return err
-		}
+	// Populate device config with volatile fields if needed.
+	networkVethFillFromVolatile(d.config, v)
 
-		// Attempt to disable IPv6 router advertisement acceptance.
-		err = util.SysctlSet(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", v["host_name"]), "0")
-		if err != nil && !os.IsNotExist(err) {
-			return err
-		}
+	// Apply host-side limits.
+	err := networkSetupHostVethLimits(d.config)
+	if err != nil {
+		return err
+	}
 
-		// Prevent source address spoofing by requiring a return path.
-		err = util.SysctlSet(fmt.Sprintf("net/ipv4/conf/%s/rp_filter", v["host_name"]), "1")
-		if err != nil && !os.IsNotExist(err) {
-			return err
-		}
+	// Attempt to disable IPv6 router advertisement acceptance.
+	err = util.SysctlSet(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", d.config["host_name"]), "0")
+	if err != nil && !os.IsNotExist(err) {
+		return err
+	}
+
+	// Prevent source address spoofing by requiring a return path.
+	err = util.SysctlSet(fmt.Sprintf("net/ipv4/conf/%s/rp_filter", d.config["host_name"]), "1")
+	if err != nil && !os.IsNotExist(err) {
+		return err
+	}
+
+	// Apply firewall rules for reverse path filtering of IPv4 and IPv6.
+	err = d.state.Firewall.InstanceSetupRPFilter(d.inst.Project(), d.inst.Name(), d.name, d.config["host_name"])
+	if err != nil {
+		return errors.Wrapf(err, "Error setting up reverse path filter")
+	}
 
-		// Apply firewall rules for reverse path filtering of IPv4 and IPv6.
-		err = d.state.Firewall.InstanceSetupRPFilter(d.inst.Project(), d.inst.Name(), d.name, v["host_name"])
+	if d.config["ipv4.address"] != "" {
+		// Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that
+		// liveness detection of the gateways inside the instance work and ensure that traffic
+		// doesn't periodically halt whilst ARP is re-detected.
+		_, err := shared.RunCommand("ip", "-4", "addr", "add", fmt.Sprintf("%s/32", d.ipv4HostAddress()), "dev", d.config["host_name"])
 		if err != nil {
-			return errors.Wrapf(err, "Error setting up reverse path filter")
+			return err
 		}
 
-		if d.config["ipv4.address"] != "" {
-			// Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that
-			// liveness detection of the gateways inside the instance work and ensure that traffic
-			// doesn't periodically halt whilst ARP is re-detected.
-			_, err := shared.RunCommand("ip", "-4", "addr", "add", fmt.Sprintf("%s/32", d.ipv4HostAddress()), "dev", v["host_name"])
-			if err != nil {
-				return err
-			}
-
-			// Add static routes to instance IPs to custom routing tables if specified.
-			// This is in addition to the static route added by liblxc to the main routing table, which
-			// is still critical to ensure that reverse path filtering doesn't kick in blocking traffic
-			// from the instance.
-			if d.config["ipv4.host_table"] != "" {
-				for _, addr := range strings.Split(d.config["ipv4.address"], ",") {
-					addr = strings.TrimSpace(addr)
-					_, err := shared.RunCommand("ip", "-4", "route", "add", "table", d.config["ipv4.host_table"], fmt.Sprintf("%s/32", addr), "dev", v["host_name"])
-					if err != nil {
-						return err
-					}
+		// Add static routes to instance IPs to custom routing tables if specified.
+		// This is in addition to the static route added by liblxc to the main routing table, which
+		// is still critical to ensure that reverse path filtering doesn't kick in blocking traffic
+		// from the instance.
+		if d.config["ipv4.host_table"] != "" {
+			for _, addr := range strings.Split(d.config["ipv4.address"], ",") {
+				addr = strings.TrimSpace(addr)
+				_, err := shared.RunCommand("ip", "-4", "route", "add", "table", d.config["ipv4.host_table"], fmt.Sprintf("%s/32", addr), "dev", d.config["host_name"])
+				if err != nil {
+					return err
 				}
 			}
 		}
+	}
 
-		if d.config["ipv6.address"] != "" {
-			// Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that
-			// liveness detection of the gateways inside the instance work and ensure that traffic
-			// doesn't periodically halt whilst NDP is re-detected.
-			_, err := shared.RunCommand("ip", "-6", "addr", "add", fmt.Sprintf("%s/128", d.ipv6HostAddress()), "dev", v["host_name"])
-			if err != nil {
-				return err
-			}
+	if d.config["ipv6.address"] != "" {
+		// Add dummy link-local gateway IPs to the host end of the veth pair. This ensures that
+		// liveness detection of the gateways inside the instance work and ensure that traffic
+		// doesn't periodically halt whilst NDP is re-detected.
+		_, err := shared.RunCommand("ip", "-6", "addr", "add", fmt.Sprintf("%s/128", d.ipv6HostAddress()), "dev", d.config["host_name"])
+		if err != nil {
+			return err
+		}
 
-			// Add static routes to instance IPs to custom routing tables if specified.
-			// This is in addition to the static route added by liblxc to the main routing table, which
-			// is still critical to ensure that reverse path filtering doesn't kick in blocking traffic
-			// from the instance.
-			if d.config["ipv6.host_table"] != "" {
-				for _, addr := range strings.Split(d.config["ipv6.address"], ",") {
-					addr = strings.TrimSpace(addr)
-					_, err := shared.RunCommand("ip", "-6", "route", "add", "table", d.config["ipv6.host_table"], fmt.Sprintf("%s/128", addr), "dev", v["host_name"])
-					if err != nil {
-						return err
-					}
+		// Add static routes to instance IPs to custom routing tables if specified.
+		// This is in addition to the static route added by liblxc to the main routing table, which
+		// is still critical to ensure that reverse path filtering doesn't kick in blocking traffic
+		// from the instance.
+		if d.config["ipv6.host_table"] != "" {
+			for _, addr := range strings.Split(d.config["ipv6.address"], ",") {
+				addr = strings.TrimSpace(addr)
+				_, err := shared.RunCommand("ip", "-6", "route", "add", "table", d.config["ipv6.host_table"], fmt.Sprintf("%s/128", addr), "dev", d.config["host_name"])
+				if err != nil {
+					return err
 				}
 			}
 		}


More information about the lxc-devel mailing list