Debian: fix VLAN creation in duplex-direct mode

In duplex-direct mode, the ifupdown VLAN configuration tries to
disable DAD using pre-up command 'sysctl -wq net.ipv6.conf.%s.accept_dad=0'
where %s is the vlan device and fails because the VLAN is not created yet.

This happens because Debian's ifupdown tool runs pre-up commands from
/etc/network/interface.d/ before running /etc/network/if-pre-up/vlan
script that creates the VLAN.

Moving the sysctl command to up or post-up won't avoid DAD to run.

The solution found is to add a VLAN creation command in pre-up before
the sysctl command.

Some bonding configuration was also being added to VLANs. Although it
was not causing any issues, it was fixed to be added only to the
bonding interfaces.

Test Plan:
    PASS: Run new VLAN unit test for duplex-direct mode
    PASS: Install duplex-direct system

Closes-Bug: 1992832

Signed-off-by: Caio Bruchert <caio.bruchert@windriver.com>
Change-Id: Icbdd113e6051d584959039e85f2dfa078ec0eb2c
This commit is contained in:
Caio Bruchert 2022-10-13 13:30:10 -03:00
parent 18b852dfa3
commit a13a27c767
2 changed files with 69 additions and 9 deletions

View File

@ -888,15 +888,24 @@ def get_duplex_direct_network_config(context, iface, config, sysctl_ifname, netw
"""
Disable dad on the specified interface for duplex-direct config
"""
networktype = find_networktype_by_network_id(context, network_id)
if (networktype and networktype in [constants.NETWORK_TYPE_MGMT,
constants.NETWORK_TYPE_CLUSTER_HOST]):
command = ("/sbin/modprobe bonding; "
"grep %s /sys/class/net/bonding_masters || "
"echo +%s > /sys/class/net/bonding_masters" % (
iface['ifname'], iface['ifname']))
fill_interface_config_option_operation(config['options'], IFACE_PRE_UP_OP, command)
new_pre_up = "sysctl -wq net.ipv6.conf.%s.accept_dad=0" % sysctl_ifname
if iface['iftype'] == constants.INTERFACE_TYPE_AE:
networktype = find_networktype_by_network_id(context, network_id)
if (networktype and networktype in [constants.NETWORK_TYPE_MGMT,
constants.NETWORK_TYPE_CLUSTER_HOST]):
command = ("/sbin/modprobe bonding; "
"grep %s /sys/class/net/bonding_masters || "
"echo +%s > /sys/class/net/bonding_masters" % (
iface['ifname'], iface['ifname']))
fill_interface_config_option_operation(config['options'], IFACE_PRE_UP_OP, command)
new_pre_up = ""
if not is_syscfg_network() and iface['iftype'] == constants.INTERFACE_TYPE_VLAN:
lower_os_ifname = get_lower_interface_os_ifname(context, iface)
new_pre_up = "ip link add link %s name %s type vlan id %s; " % (
lower_os_ifname, sysctl_ifname, iface['vlan_id'])
new_pre_up += "sysctl -wq net.ipv6.conf.%s.accept_dad=0" % sysctl_ifname
fill_interface_config_option_operation(config['options'], IFACE_PRE_UP_OP, new_pre_up)
return config

View File

@ -1761,6 +1761,57 @@ class InterfaceTestCase(InterfaceTestCaseMixin, dbbase.BaseHostTestCase):
print(expected)
self.assertEqual(expected, config)
def test_get_controller_vlan_config_duplex_direct(self):
system_dict = self.system.as_dict()
system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT
self.dbapi.isystem_update(self.system.uuid, system_dict)
vlan = self._create_vlan_test(
"vlan100", constants.INTERFACE_CLASS_PLATFORM,
constants.NETWORK_TYPE_MGMT, 100, self.iface)
self._update_context()
self._update_interface_address_pool(
vlan, constants.NETWORK_TYPE_MGMT)
network = self.dbapi.network_get_by_type(constants.NETWORK_TYPE_MGMT)
config = interface.get_interface_network_config(self.context, vlan, network.id)
options = {'IPV6_AUTOCONF': 'no',
'PHYSDEV': self.port['name'],
'VLAN': 'yes',
'pre_up': '/sbin/modprobe -q 8021q; sysctl -wq '
'net.ipv6.conf.vlan100.accept_dad=0'}
expected = self._get_static_network_config(ifname=vlan['ifname'],
gateway='192.168.204.1', ipaddress='192.168.1.2', mtu=1500,
options=options)
print(expected)
self.assertEqual(expected, config)
def test_get_controller_vlan_config_duplex_direct_ifupdown(self):
self.mock_puppet_interface_sysconfig.return_value = False
system_dict = self.system.as_dict()
system_dict['system_mode'] = constants.SYSTEM_MODE_DUPLEX_DIRECT
self.dbapi.isystem_update(self.system.uuid, system_dict)
vlan = self._create_vlan_test(
"vlan100", constants.INTERFACE_CLASS_PLATFORM,
constants.NETWORK_TYPE_MGMT, 100, self.iface)
self._update_context()
self._update_interface_address_pool(
vlan, constants.NETWORK_TYPE_MGMT)
network = self.dbapi.network_get_by_type(constants.NETWORK_TYPE_MGMT)
config = interface.get_interface_network_config(self.context, vlan, network.id)
options = {'gateway': '192.168.204.1',
'mtu': '1500',
'post-up': '/usr/sbin/ip link set dev vlan100 mtu 1500; echo 0 > '
'/proc/sys/net/ipv6/conf/vlan100/autoconf; echo 0 '
'> /proc/sys/net/ipv6/conf/vlan100/accept_ra; echo 0 > '
'/proc/sys/net/ipv6/conf/vlan100/accept_redirects',
'pre-up': '/sbin/modprobe -q 8021q; ip link add link eth0 name '
'vlan100 type vlan id 100; sysctl -wq '
'net.ipv6.conf.vlan100.accept_dad=0',
'vlan-raw-device': '{}'.format(self.port['name'])}
expected = self._get_static_network_config_ifupdown(
ifname=vlan['ifname'], options=options)
print(expected)
self.assertEqual(expected, config)
def test_get_controller_vlan_config_over_bond(self):
bond = self._create_bond_test("bond0")
vlan = self._create_vlan_test("vlan1", None, None, 1, bond)