Browse Source

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)
tags/10.4.1^0
Moshe Levi 2 months ago
parent
commit
14e46a5acc
3 changed files with 69 additions and 6 deletions
  1. 36
    2
      os_net_config/cli.py
  2. 30
    2
      os_net_config/sriov_config.py
  3. 3
    2
      os_net_config/utils.py

+ 36
- 2
os_net_config/cli.py View File

@@ -30,6 +30,7 @@ from os_net_config import validator
30 30
 from os_net_config import version
31 31
 
32 32
 logger = logging.getLogger(__name__)
33
+_SYSTEM_CTL_CONFIG_FILE = '/etc/sysctl.d/os-net-sysctl.conf'
33 34
 
34 35
 
35 36
 def parse_opts(argv):
@@ -143,13 +144,32 @@ def check_configure_sriov(obj):
143 144
     return configure_sriov
144 145
 
145 146
 
147
+def disable_ipv6_for_netdevs(net_devices):
148
+    sysctl_conf = ""
149
+    for net_device in net_devices:
150
+        sysctl_conf += "net.ipv6.conf.%s.disable_ipv6 = 1\n" % net_device
151
+    utils.write_config(_SYSTEM_CTL_CONFIG_FILE, sysctl_conf)
152
+
153
+
154
+def get_sriovpf_member_of_bond_ovs_port(obj):
155
+    net_devs_list = []
156
+    if isinstance(obj, objects.OvsBridge):
157
+        for member in obj.members:
158
+            if isinstance(member, objects.LinuxBond):
159
+                for child_member in member.members:
160
+                    if isinstance(child_member, objects.SriovPF):
161
+                        if child_member.link_mode == 'switchdev':
162
+                            net_devs_list.append(child_member.name)
163
+    return net_devs_list
164
+
165
+
146 166
 def main(argv=sys.argv):
147 167
     opts = parse_opts(argv)
148 168
     configure_logger(opts.verbose, opts.debug)
149 169
     logger.info('Using config file at: %s' % opts.config_file)
150 170
     iface_array = []
151 171
     configure_sriov = False
152
-
172
+    sriovpf_member_of_bond_ovs_port_list = []
153 173
     provider = None
154 174
     if opts.provider:
155 175
         if opts.provider == 'ifcfg':
@@ -278,6 +298,18 @@ def main(argv=sys.argv):
278 298
                 configure_sriov = True
279 299
                 provider.add_object(obj)
280 300
 
301
+                sriovpf_member_of_bond_ovs_port_list.extend(
302
+                    get_sriovpf_member_of_bond_ovs_port(obj))
303
+
304
+    # After reboot, shared_block for pf interface in switchdev mode will be
305
+    # missing in case IPv6 is enabled on the slaves of the bond and that bond
306
+    # is an ovs port. This is due to the fact that OVS assumes another entity
307
+    # manages the slaves.
308
+    # So as a workaround for that case we are disabling IPv6 over pfs so that
309
+    # OVS creates the shared_blocks ingress
310
+    if sriovpf_member_of_bond_ovs_port_list:
311
+        disable_ipv6_for_netdevs(sriovpf_member_of_bond_ovs_port_list)
312
+
281 313
     if configure_sriov:
282 314
         # Apply the ifcfgs for PFs now, so that NM_CONTROLLED=no is applied
283 315
         # for each of the PFs before configuring the numvfs for the PF device.
@@ -288,7 +320,9 @@ def main(argv=sys.argv):
288 320
         pf_files_changed = provider.apply(cleanup=opts.cleanup,
289 321
                                           activate=not opts.no_activate)
290 322
         if not opts.noop:
291
-            utils.configure_sriov_pfs()
323
+            utils.configure_sriov_pfs(
324
+                execution_from_cli=True,
325
+                restart_openvswitch=bool(sriovpf_member_of_bond_ovs_port_list))
292 326
 
293 327
     for iface_json in iface_array:
294 328
         # All objects other than the sriov_pf will be added here.

+ 30
- 2
os_net_config/sriov_config.py View File

@@ -113,7 +113,16 @@ def get_numvfs(ifname):
113 113
         raise SRIOVNumvfsException(msg)
114 114
 
115 115
 
116
-def configure_sriov_pf():
116
+def restart_ovs_and_pfs_netdevs():
117
+    sriov_map = _get_sriov_map()
118
+    processutils.execute('/usr/bin/systemctl', 'restart', 'openvswitch')
119
+    for item in sriov_map:
120
+        if item['device_type'] == 'pf':
121
+            if_down_interface(item['name'])
122
+            if_up_interface(item['name'])
123
+
124
+
125
+def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False):
117 126
     # Create a context for pyudev and observe udev events for network
118 127
     context = pyudev.Context()
119 128
     monitor = pyudev.Monitor.from_netlink(context)
@@ -169,13 +178,23 @@ def configure_sriov_pf():
169 178
                 trigger_udev_rule = add_udev_rule_for_vf_representors(
170 179
                     item['name']) or trigger_udev_rule
171 180
 
172
-                if_up_interface(item['name'])
181
+                # Moving the sriov-PFs to switchdev mode will put the netdev
182
+                # interfaces in down state.
183
+                # In case we are running during initial deployment,
184
+                # bring the interfaces up.
185
+                # In case we are running as part of the sriov_config service
186
+                # after reboot, net config scripts, which run after
187
+                # sriov_config service will bring the interfaces up.
188
+                if execution_from_cli:
189
+                    if_up_interface(item['name'])
173 190
 
174 191
     # Trigger udev rules if there is new rules written
175 192
     if trigger_udev_rule:
176 193
         trigger_udev_rules()
177 194
 
178 195
     observer.stop()
196
+    if restart_openvswitch:
197
+        restart_ovs_and_pfs_netdevs()
179 198
 
180 199
 
181 200
 def _wait_for_vf_creation(pf_name, numvfs):
@@ -393,6 +412,15 @@ def get_vf_pcis_list(pf_name):
393 412
     return vf_pcis_list
394 413
 
395 414
 
415
+def if_down_interface(device):
416
+    logger.info("Running /sbin/ifdown %s" % device)
417
+    try:
418
+        processutils.execute('/sbin/ifdown', device)
419
+    except processutils.ProcessExecutionError:
420
+        logger.error("Failed to ifdown  %s" % device)
421
+        raise
422
+
423
+
396 424
 def if_up_interface(device):
397 425
     logger.info("Running /sbin/ifup %s" % device)
398 426
     try:

+ 3
- 2
os_net_config/utils.py View File

@@ -540,9 +540,10 @@ def _configure_sriov_config_service():
540 540
     processutils.execute('systemctl', 'enable', 'sriov_config')
541 541
 
542 542
 
543
-def configure_sriov_pfs():
543
+def configure_sriov_pfs(execution_from_cli=False, restart_openvswitch=False):
544 544
     logger.info("Configuring PFs now")
545
-    sriov_config.configure_sriov_pf()
545
+    sriov_config.configure_sriov_pf(execution_from_cli=execution_from_cli,
546
+                                    restart_openvswitch=restart_openvswitch)
546 547
     _configure_sriov_config_service()
547 548
 
548 549
 

Loading…
Cancel
Save