From 9ef2ba47c94a8469cdfa8670b358f2425c0b72c1 Mon Sep 17 00:00:00 2001 From: Saikrishna Arcot Date: Wed, 27 Oct 2021 18:16:01 -0700 Subject: [PATCH] [vlanmgr]: Update VLAN removal code to work with 5.10 kernel and newer iproute2 versions (#1970) * Update VLAN removal code to work with 5.10 kernel and newer iproute2 versions There is an issue discovered by Alexander Allen where VLAN member removal from a VLAN doesn't fully happen on a 5.10 kernel. The reason for this is that there is a change in the output of the `bridge vlan show` command between the 4.19 kernel and the 5.10 kernel. To add to this, the output is different depending on whether iproute2 4.20 or iproute2 5.10 is installed. These output changes cause only some of the VLAN member removal code to run; specifically, the interface will not be the member of a VLAN anymore, but it will still be part of the bridge. Therefore, update the code that parses the output of `bridge vlan show` to handle iproute2 4.20 with 4.19 kernel, iproute2 4.20 with 5.10 kernel, and iproute2 5.10 with 5.10 kernel. This should cover all possible combinations we'll have until all containers are on Bullseye. Signed-off-by: Saikrishna Arcot * Store the exit code of the bridge vlan show command. Signed-off-by: Saikrishna Arcot * Add missing space. Signed-off-by: Saikrishna Arcot --- cfgmgr/vlanmgr.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/cfgmgr/vlanmgr.cpp b/cfgmgr/vlanmgr.cpp index 830f8d9d26a7..5124cd5a7a0f 100644 --- a/cfgmgr/vlanmgr.cpp +++ b/cfgmgr/vlanmgr.cpp @@ -237,19 +237,27 @@ bool VlanMgr::removeHostVlanMember(int vlan_id, const string &port_alias) // The command should be generated as: // /bin/bash -c '/sbin/bridge vlan del vid {{vlan_id}} dev {{port_alias}} && - // ( /sbin/bridge vlan show dev {{port_alias}} | /bin/grep -q None; - // ret=$?; if [ $ret -eq 0 ]; then + // ( vlanShow=$(/sbin/bridge vlan show dev {{port_alias}}); + // ret=$?; + // if [ $ret -eq 0 ]; then + // if (! echo "$vlanShow" | grep -q {{port_alias}}) + // || (echo "$vlanShow" | grep -q None$) + // || (echo "$vlanShow" | grep -q {{port_alias}}$); then // /sbin/ip link set {{port_alias}} nomaster; - // elif [ $ret -eq 1 ]; then exit 0; + // fi; // else exit $ret; fi )' // When port is not member of any VLAN, it shall be detached from Dot1Q bridge! ostringstream cmds, inner; inner << BRIDGE_CMD " vlan del vid " + std::to_string(vlan_id) + " dev " << shellquote(port_alias) << " && ( " - BRIDGE_CMD " vlan show dev " << shellquote(port_alias) << " | " - GREP_CMD " -q None; ret=$?; if [ $ret -eq 0 ]; then " + "vlanShow=$(" BRIDGE_CMD " vlan show dev " << shellquote(port_alias) << "); " + "ret=$?; " + "if [ $ret -eq 0 ]; then " + "if (! echo \"$vlanShow\" | " GREP_CMD " -q " << shellquote(port_alias) << ") " + " || (echo \"$vlanShow\" | " GREP_CMD " -q None$) " + " || (echo \"$vlanShow\" | " GREP_CMD " -q " << shellquote(port_alias) << "$); then " IP_CMD " link set " << shellquote(port_alias) << " nomaster; " - "elif [ $ret -eq 1 ]; then exit 0; " + "fi; " "else exit $ret; fi )"; cmds << BASH_CMD " -c " << shellquote(inner.str());