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

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) ===
Stopping an instance was not detaching the bridged NIC device from the openvswitch bridge, causing port leaks such as:

```
sudo ovs-vsctl show
84593e35-9a66-45ba-b647-929e396b3a59
    Bridge lxdbr1
        Port lxdbr1
            Interface lxdbr1
                type: internal
        Port veth1d5cd6a9
            Interface veth1d5cd6a9
                error: "could not open network device veth1d5cd6a9 (No such device)"
```

Also includes some other comment/code clarity improvements.
From e1ca192063d262540c5c36f6945145e8716df311 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 2 Jun 2020 09:27:41 +0100
Subject: [PATCH 1/4] lxd/device/nic/bridged: Corrects vlan comment

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/device/nic_bridged.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index a7d6a3a865..d270f80e1c 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -1197,7 +1197,7 @@ func (d *nicBridged) networkDHCPv6CreateIAAddress(IP 
net.IP) []byte {
 
 // setupBridgePortVLANs configures the bridge port with the specified VLAN 
settings in device config.
 func (d *nicBridged) setupBridgePortVLANs(hostName string) error {
-       // Enable vlan_filtering on bridge if needed.
+       // Check vlan_filtering is enabled on bridge if needed.
        if d.config["vlan"] != "" || d.config["vlan.tagged"] != "" {
                vlanFilteringStatus, err := 
network.BridgeVLANFilteringStatus(d.config["parent"])
                if err != nil {

From c8f2731714810b90bb0d76729acde799a81563da Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 2 Jun 2020 10:11:28 +0100
Subject: [PATCH 2/4] lxd/network/network/utils: Improve comments on ovs switch
 attach/detach

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

diff --git a/lxd/network/network_utils.go b/lxd/network/network_utils.go
index 6d3b6b2330..577dd5583c 100644
--- a/lxd/network/network_utils.go
+++ b/lxd/network/network_utils.go
@@ -100,6 +100,7 @@ func AttachInterface(netName string, devName string) error {
                        return err
                }
        } else {
+               // Check if interface is already connected to a bridge, if not 
connect it to the specified bridge.
                _, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
                if err != nil {
                        _, err := shared.RunCommand("ovs-vsctl", "add-port", 
netName, devName)
@@ -120,6 +121,7 @@ func DetachInterface(netName string, devName string) error {
                        return err
                }
        } else {
+               // Check if interface is connected to a bridge, if so, then 
remove it from the bridge.
                _, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
                if err == nil {
                        _, err := shared.RunCommand("ovs-vsctl", "del-port", 
netName, devName)

From 39f9ef666866e2b9191f47fe99453b1f57d2be5e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 2 Jun 2020 10:15:52 +0100
Subject: [PATCH 3/4] lxd/network/network/utils: Improves arg name in network
 attach/detach functions

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

diff --git a/lxd/network/network_utils.go b/lxd/network/network_utils.go
index 577dd5583c..bb56b2b187 100644
--- a/lxd/network/network_utils.go
+++ b/lxd/network/network_utils.go
@@ -93,9 +93,9 @@ func GetIP(subnet *net.IPNet, host int64) net.IP {
 }
 
 // AttachInterface attaches an interface to a bridge.
-func AttachInterface(netName string, devName string) error {
-       if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", netName)) {
-               _, err := shared.RunCommand("ip", "link", "set", "dev", 
devName, "master", netName)
+func AttachInterface(bridgeName string, devName string) error {
+       if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", 
bridgeName)) {
+               _, err := shared.RunCommand("ip", "link", "set", "dev", 
devName, "master", bridgeName)
                if err != nil {
                        return err
                }
@@ -103,7 +103,7 @@ func AttachInterface(netName string, devName string) error {
                // Check if interface is already connected to a bridge, if not 
connect it to the specified bridge.
                _, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
                if err != nil {
-                       _, err := shared.RunCommand("ovs-vsctl", "add-port", 
netName, devName)
+                       _, err := shared.RunCommand("ovs-vsctl", "add-port", 
bridgeName, devName)
                        if err != nil {
                                return err
                        }
@@ -114,8 +114,8 @@ func AttachInterface(netName string, devName string) error {
 }
 
 // DetachInterface detaches an interface from a bridge.
-func DetachInterface(netName string, devName string) error {
-       if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", netName)) {
+func DetachInterface(bridgeName string, devName string) error {
+       if shared.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", 
bridgeName)) {
                _, err := shared.RunCommand("ip", "link", "set", "dev", 
devName, "nomaster")
                if err != nil {
                        return err
@@ -124,7 +124,7 @@ func DetachInterface(netName string, devName string) error {
                // Check if interface is connected to a bridge, if so, then 
remove it from the bridge.
                _, err := shared.RunCommand("ovs-vsctl", "port-to-br", devName)
                if err == nil {
-                       _, err := shared.RunCommand("ovs-vsctl", "del-port", 
netName, devName)
+                       _, err := shared.RunCommand("ovs-vsctl", "del-port", 
bridgeName, devName)
                        if err != nil {
                                return err
                        }

From da2f7177633bb57e96e6f8ede76a35a977d40b53 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 2 Jun 2020 10:21:58 +0100
Subject: [PATCH 4/4] lxd/device/bic/bridged: Fixes openvswitch port leak when
 device is stopped

Port was not being detached from bridge on stop causing disconnected ports to 
accumulate on bridge:

 sudo ovs-vsctl show
 84593e35-9a66-45ba-b647-929e396b3a59
    Bridge lxdbr1
        Port lxdbr1
            Interface lxdbr1
                type: internal
        Port veth1d5cd6a9
            Interface veth1d5cd6a9
                error: "could not open network device veth1d5cd6a9 (No such 
device)"

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

diff --git a/lxd/device/nic_bridged.go b/lxd/device/nic_bridged.go
index d270f80e1c..e906903d65 100644
--- a/lxd/device/nic_bridged.go
+++ b/lxd/device/nic_bridged.go
@@ -278,6 +278,7 @@ func (d *nicBridged) Start() (*deviceConfig.RunConfig, 
error) {
        if err != nil {
                return nil, err
        }
+       revert.Add(func() { network.DetachInterface(d.config["parent"], 
saveData["host_name"]) })
 
        // Attempt to disable router advertisement acceptance.
        err = util.SysctlSet(fmt.Sprintf("net/ipv6/conf/%s/accept_ra", 
saveData["host_name"]), "0")
@@ -402,8 +403,14 @@ func (d *nicBridged) postStop() error {
        }
 
        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).
+               err := network.DetachInterface(d.config["parent"], 
d.config["host_name"])
+               if err != nil {
+                       return err
+               }
+
                // Removing host-side end of veth pair will delete the peer end 
too.
-               err := NetworkRemoveInterface(d.config["host_name"])
+               err = NetworkRemoveInterface(d.config["host_name"])
                if err != nil {
                        return fmt.Errorf("Failed to remove interface %s: %s", 
d.config["host_name"], err)
                }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to