fix missing shared_block for PF interface in switchdev bond connected to ovs

When having a deployment with ovs bridge having a linux bond and
the slaves of that bond are in switchdev mode , shared_blocks are
expected to be created for both the bond and the slaves, but because the
slaves have an autoconfig IPv6 so ovs will assume that the slaves are not
managed by it, and so those shared_blocks will be missing for those slaves.

As a workaround for this issue we should handle two cases:
 * First os-net-config run / Post deployment
 * Reboot compute node

For deployment case, we are restarting openvswitch and ifdown ifup
any PF interface, this will make openvswitch recreate PF shared_block

For reboot case, we are disabling ipv6 for PF interfaces and because
the ovs will start after moving to swichdev, so the shared_blocks will
be created.

Also there is no need to ifup the PF interfaces after moving to switchdev
in reboot case as the config scripts will bring them up later

Change-Id: I2468866629d95dc9f088985d57fbf70263253235
Closes-Bug: #1836581
(cherry picked from commit a74bbdd7b0)
This commit is contained in:
Moshe Levi 2019-07-15 00:26:02 +03:00 committed by waleed mousa
parent 591ba03a9b
commit e1b03386e5
3 changed files with 69 additions and 6 deletions

View File

@ -30,6 +30,7 @@ from os_net_config import validator
from os_net_config import version
logger = logging.getLogger(__name__)
_SYSTEM_CTL_CONFIG_FILE = '/etc/sysctl.d/os-net-sysctl.conf'
def parse_opts(argv):
@ -143,13 +144,32 @@ def check_configure_sriov(obj):
return configure_sriov
def disable_ipv6_for_netdevs(net_devices):
sysctl_conf = ""
for net_device in net_devices:
sysctl_conf += "net.ipv6.conf.%s.disable_ipv6 = 1\n" % net_device
utils.write_config(_SYSTEM_CTL_CONFIG_FILE, sysctl_conf)
def get_sriovpf_member_of_bond_ovs_port(obj):
net_devs_list = []
if isinstance(obj, objects.OvsBridge):
for member in obj.members:
if isinstance(member, objects.LinuxBond):
for child_member in member.members:
if isinstance(child_member, objects.SriovPF):
if child_member.link_mode == 'switchdev':
net_devs_list.append(child_member.name)
return net_devs_list
def main(argv=sys.argv):
opts = parse_opts(argv)
configure_logger(opts.verbose, opts.debug)
logger.info('Using config file at: %s' % opts.config_file)
iface_array = []
configure_sriov = False
sriovpf_member_of_bond_ovs_port_list = []
provider = None
if opts.provider:
if opts.provider == 'ifcfg':
@ -278,6 +298,18 @@ def main(argv=sys.argv):
configure_sriov = True
provider.add_object(obj)
sriovpf_member_of_bond_ovs_port_list.extend(
get_sriovpf_member_of_bond_ovs_port(obj))
# After reboot, shared_block for pf interface in switchdev mode will be
# missing in case IPv6 is enabled on the slaves of the bond and that bond
# is an ovs port. This is due to the fact that OVS assumes another entity
# manages the slaves.
# So as a workaround for that case we are disabling IPv6 over pfs so that
# OVS creates the shared_blocks ingress
if sriovpf_member_of_bond_ovs_port_list:
disable_ipv6_for_netdevs(sriovpf_member_of_bond_ovs_port_list)
if configure_sriov:
# Apply the ifcfgs for PFs now, so that NM_CONTROLLED=no is applied
# for each of the PFs before configuring the numvfs for the PF device.
@ -288,7 +320,9 @@ def main(argv=sys.argv):
pf_files_changed = provider.apply(cleanup=opts.cleanup,
activate=not opts.no_activate)
if not opts.noop:
utils.configure_sriov_pfs()
utils.configure_sriov_pfs(
execution_from_cli=True,
restart_openvswitch=bool(sriovpf_member_of_bond_ovs_port_list))
for iface_json in iface_array:
# All objects other than the sriov_pf will be added here.

View File

@ -113,7 +113,16 @@ def get_numvfs(ifname):
raise SRIOVNumvfsException(msg)
def configure_sriov_pf():
def restart_ovs_and_pfs_netdevs():
sriov_map = _get_sriov_map()
processutils.execute('/usr/bin/systemctl', 'restart', 'openvswitch')
for item in sriov_map:
if item['device_type'] == 'pf':
if_down_interface(item['name'])
if_up_interface(item['name'])
def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False):
# Create a context for pyudev and observe udev events for network
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
@ -169,13 +178,23 @@ def configure_sriov_pf():
trigger_udev_rule = add_udev_rule_for_vf_representors(
item['name']) or trigger_udev_rule
if_up_interface(item['name'])
# Moving the sriov-PFs to switchdev mode will put the netdev
# interfaces in down state.
# In case we are running during initial deployment,
# bring the interfaces up.
# In case we are running as part of the sriov_config service
# after reboot, net config scripts, which run after
# sriov_config service will bring the interfaces up.
if execution_from_cli:
if_up_interface(item['name'])
# Trigger udev rules if there is new rules written
if trigger_udev_rule:
trigger_udev_rules()
observer.stop()
if restart_openvswitch:
restart_ovs_and_pfs_netdevs()
def _wait_for_vf_creation(pf_name, numvfs):
@ -393,6 +412,15 @@ def get_vf_pcis_list(pf_name):
return vf_pcis_list
def if_down_interface(device):
logger.info("Running /sbin/ifdown %s" % device)
try:
processutils.execute('/sbin/ifdown', device)
except processutils.ProcessExecutionError:
logger.error("Failed to ifdown %s" % device)
raise
def if_up_interface(device):
logger.info("Running /sbin/ifup %s" % device)
try:

View File

@ -537,9 +537,10 @@ def _configure_sriov_config_service():
processutils.execute('systemctl', 'enable', 'sriov_config')
def configure_sriov_pfs():
def configure_sriov_pfs(execution_from_cli=False, restart_openvswitch=False):
logger.info("Configuring PFs now")
sriov_config.configure_sriov_pf()
sriov_config.configure_sriov_pf(execution_from_cli=execution_from_cli,
restart_openvswitch=restart_openvswitch)
_configure_sriov_config_service()