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