The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7707

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
- Splits host veth helper functions, so that OVN NICs can make selective use of them.
- Standardises enrichment of `hwaddr` and `host_name` fields from volatile map.
- Adds `Create` function for networks, and defaults to it being a no-op.

From 0cd7e953d6bb9d3e8003befd18326ca7099634fe Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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
                                }
                        }
                }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to