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

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) ===

From 9a0cf626779c141f59b358963cede5632c988563 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 1 Oct 2020 17:07:39 +0100
Subject: [PATCH 1/3] lxd/network/network/utils: Adds GetNeighbourV6Addresses
 function

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/network/network_utils.go | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/lxd/network/network_utils.go b/lxd/network/network_utils.go
index c195228a3d..a4ead17f6f 100644
--- a/lxd/network/network_utils.go
+++ b/lxd/network/network_utils.go
@@ -805,6 +805,34 @@ func GetHostDevice(parent string, vlan string) string {
        return defaultVlan
 }
 
+// GetNeighbourV6Addresses returns the IPv6 addresses in the neighbour cache 
for a particular interface and MAC.
+func GetNeighbourV6Addresses(interfaceName string, hwaddr string) ([]net.IP, 
error) {
+       addresses := []net.IP{}
+
+       // Look for neighbour entries for IPv6.
+       out, err := shared.RunCommand("ip", "-6", "neigh", "show", "dev", 
interfaceName)
+       if err == nil {
+               for _, line := range strings.Split(out, "\n") {
+                       // Split fields and early validation.
+                       fields := strings.Fields(line)
+                       if len(fields) != 4 {
+                               continue
+                       }
+
+                       if fields[2] != hwaddr {
+                               continue
+                       }
+
+                       ip := net.ParseIP(fields[0])
+                       if ip != nil {
+                               addresses = append(addresses, ip)
+                       }
+               }
+       }
+
+       return addresses, nil
+}
+
 // GetLeaseAddresses returns the lease addresses for a network and hwaddr.
 func GetLeaseAddresses(s *state.State, networkName string, hwaddr string) 
([]api.InstanceStateNetworkAddress, error) {
        addresses := []api.InstanceStateNetworkAddress{}

From 6ba197ad54e2dff9416ff698cdbbc2c6e836aa1c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 1 Oct 2020 17:46:42 +0100
Subject: [PATCH 2/3] lxd/network/network/utils: Updates GetLeaseAddresses to
 return only net.IP list

 - Removes IPv6 neighbour look as was out of scope for this function's name.
 - Returns []net.IP rather than []api.InstanceStateNetworkAddress.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/network/network_utils.go | 79 ++++--------------------------------
 1 file changed, 9 insertions(+), 70 deletions(-)

diff --git a/lxd/network/network_utils.go b/lxd/network/network_utils.go
index a4ead17f6f..96d57465ed 100644
--- a/lxd/network/network_utils.go
+++ b/lxd/network/network_utils.go
@@ -834,48 +834,10 @@ func GetNeighbourV6Addresses(interfaceName string, hwaddr 
string) ([]net.IP, err
 }
 
 // GetLeaseAddresses returns the lease addresses for a network and hwaddr.
-func GetLeaseAddresses(s *state.State, networkName string, hwaddr string) 
([]api.InstanceStateNetworkAddress, error) {
-       addresses := []api.InstanceStateNetworkAddress{}
-
-       // Look for neighborhood entries for IPv6.
-       out, err := shared.RunCommand("ip", "-6", "neigh", "show", "dev", 
networkName)
-       if err == nil {
-               for _, line := range strings.Split(out, "\n") {
-                       // Split fields and early validation.
-                       fields := strings.Fields(line)
-                       if len(fields) != 4 {
-                               continue
-                       }
-
-                       if fields[2] != hwaddr {
-                               continue
-                       }
-
-                       // Prepare the entry.
-                       addr := api.InstanceStateNetworkAddress{}
-                       addr.Address = fields[0]
-                       addr.Family = "inet6"
-
-                       if strings.HasPrefix(fields[0], "fe80::") {
-                               addr.Scope = "link"
-                       } else {
-                               addr.Scope = "global"
-                       }
-
-                       addresses = append(addresses, addr)
-               }
-       }
-
-       // Look for DHCP leases.
+func GetLeaseAddresses(networkName string, hwaddr string) ([]net.IP, error) {
        leaseFile := shared.VarPath("networks", networkName, "dnsmasq.leases")
        if !shared.PathExists(leaseFile) {
-               return addresses, nil
-       }
-
-       // Pass project.Default here, as currently dnsmasq (bridged) networks 
do not support projects.
-       dbInfo, err := LoadByName(s, project.Default, networkName)
-       if err != nil {
-               return nil, err
+               return nil, fmt.Errorf("Leases file not found for network %q", 
networkName)
        }
 
        content, err := ioutil.ReadFile(leaseFile)
@@ -883,13 +845,15 @@ func GetLeaseAddresses(s *state.State, networkName 
string, hwaddr string) ([]api
                return nil, err
        }
 
+       addresses := []net.IP{}
+
        for _, lease := range strings.Split(string(content), "\n") {
                fields := strings.Fields(lease)
                if len(fields) < 5 {
                        continue
                }
 
-               // Parse the MAC
+               // Parse the MAC.
                mac := GetMACSlice(fields[1])
                macStr := strings.Join(mac, ":")
 
@@ -901,36 +865,11 @@ func GetLeaseAddresses(s *state.State, networkName 
string, hwaddr string) ([]api
                        continue
                }
 
-               // Parse the IP
-               addr := api.InstanceStateNetworkAddress{
-                       Address: fields[2],
-                       Scope:   "global",
-               }
-
-               ip := net.ParseIP(addr.Address)
-               if ip == nil {
-                       continue
-               }
-
-               if ip.To4() != nil {
-                       addr.Family = "inet"
-
-                       _, subnet, _ := 
net.ParseCIDR(dbInfo.Config()["ipv4.address"])
-                       if subnet != nil {
-                               mask, _ := subnet.Mask.Size()
-                               addr.Netmask = fmt.Sprintf("%d", mask)
-                       }
-               } else {
-                       addr.Family = "inet6"
-
-                       _, subnet, _ := 
net.ParseCIDR(dbInfo.Config()["ipv6.address"])
-                       if subnet != nil {
-                               mask, _ := subnet.Mask.Size()
-                               addr.Netmask = fmt.Sprintf("%d", mask)
-                       }
+               // Parse the IP.
+               ip := net.ParseIP(fields[2])
+               if ip != nil {
+                       addresses = append(addresses, ip)
                }
-
-               addresses = append(addresses, addr)
        }
 
        return addresses, nil

From 5d2b5543d6a62aa4d77e4a3a8fedc59765045fc6 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 1 Oct 2020 17:21:54 +0100
Subject: [PATCH 3/3] lxd/device/nic/bridged: Updates State() to return partial
 data

 - Only tries to parse dnsmasq leases file if parent network is managed.
 - If parent network is not managed, no longer treat this as complete failure.
 - Try and find IPv6 addresses from IP neighbour cache using 
network.GetNeighbourV6Addresses.
 - Load interface MTU using NIC's `host_name` rather than parent interface 
(should be the same but more consistent with how OVN NIC does it).
 - Also means that if the NIC's host veth interface is missing, then this call 
will not return any results.
 - If interface is available, will return interface stats even with no IPs 
found.
 - Guess link-local address netmask size based on IP family.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/device/nic_bridged.go | 77 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 67 insertions(+), 10 deletions(-)

diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index f8a255e4d8..47b0d67379 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -1091,24 +1091,81 @@ func (d *nicBridged) State() 
(*api.InstanceStateNetwork, error) {
        // Populate device config with volatile fields if needed.
        networkVethFillFromVolatile(d.config, v)
 
-       if d.config["hwaddr"] == "" {
-               return nil, nil
+       ips := []net.IP{}
+
+       // Check if parent is managed network and load config.
+       // Pass project.Default here, as currently dnsmasq (bridged) networks 
do not support projects.
+       n, err := network.LoadByName(d.state, project.Default, 
d.config["parent"])
+       if err == nil && d.config["hwaddr"] != "" {
+               // Parse the leases file if parent network is managed.
+               leaseIPs, err := network.GetLeaseAddresses(n.Name(), 
d.config["hwaddr"])
+               if err == nil {
+                       for _, leaseIP := range leaseIPs {
+                               ips = append(ips, leaseIP)
+                       }
+               }
        }
 
-       // Parse the leases file.
-       addresses, err := network.GetLeaseAddresses(d.state, 
d.config["parent"], d.config["hwaddr"])
-       if err != nil {
-               return nil, err
+       // Get IPv6 addresses from IP neighbour cache if present.
+       neighIPs, err := network.GetNeighbourV6Addresses(d.config["parent"], 
d.config["hwaddr"])
+       if err == nil {
+               for _, neighIP := range neighIPs {
+                       ips = append(ips, neighIP)
+               }
+       }
+
+       // Extract subnet sizes from bridge addresses if available.
+       var v4mask string
+       var v6mask string
+
+       if n != nil {
+               netConfig := n.Config()
+               _, v4subnet, _ := net.ParseCIDR(netConfig["ipv4.address"])
+               _, v6subnet, _ := net.ParseCIDR(netConfig["ipv6.address"])
+
+               if v4subnet != nil {
+                       mask, _ := v4subnet.Mask.Size()
+                       v4mask = fmt.Sprintf("%d", mask)
+               }
+
+               if v6subnet != nil {
+                       mask, _ := v6subnet.Mask.Size()
+                       v6mask = fmt.Sprintf("%d", mask)
+               }
        }
 
-       if len(addresses) == 0 {
-               return nil, nil
+       // Convert IPs to InstanceStateNetworkAddresses.
+       addresses := []api.InstanceStateNetworkAddress{}
+       for _, ip := range ips {
+               addr := api.InstanceStateNetworkAddress{}
+               addr.Address = ip.String()
+               addr.Family = "inet"
+               addr.Netmask = v4mask
+
+               if ip.To4() == nil {
+                       addr.Family = "inet6"
+                       addr.Netmask = v6mask
+               }
+
+               if ip.IsLinkLocalUnicast() {
+                       addr.Scope = "link"
+
+                       if addr.Family == "inet6" {
+                               addr.Netmask = "64" // Link-local IPv6 
addresses are /64.
+                       } else {
+                               addr.Netmask = "16" // Local-local IPv4 
addresses are /16.
+                       }
+               } else {
+                       addr.Scope = "global"
+               }
+
+               addresses = append(addresses, addr)
        }
 
        // Get MTU.
-       iface, err := net.InterfaceByName(d.config["parent"])
+       iface, err := net.InterfaceByName(d.config["host_name"])
        if err != nil {
-               return nil, err
+               return nil, errors.Wrapf(err, "Failed getting host interface 
state")
        }
 
        // Retrieve the host counters, as we report the values from the 
instance's point of view,
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to