diff --git a/etc/os-net-config/samples/sriov_pf_switchdev.json b/etc/os-net-config/samples/sriov_pf_switchdev.json index 8b3cb014..391d8ace 100644 --- a/etc/os-net-config/samples/sriov_pf_switchdev.json +++ b/etc/os-net-config/samples/sriov_pf_switchdev.json @@ -6,7 +6,8 @@ "numvfs": 10, "use_dhcp": false, "promisc": true, - "link_mode": "switchdev" + "link_mode": "switchdev", + "steering_mode": "dmfs" }, { "type": "ovs_bridge", diff --git a/etc/os-net-config/samples/sriov_pf_switchdev.yaml b/etc/os-net-config/samples/sriov_pf_switchdev.yaml index 6962ed41..21b11856 100644 --- a/etc/os-net-config/samples/sriov_pf_switchdev.yaml +++ b/etc/os-net-config/samples/sriov_pf_switchdev.yaml @@ -23,6 +23,9 @@ network_config: # - switchdev # - legacy (default) link_mode: switchdev + # (Optional) The flow steering mode, which could be smfs or dmfs + # If it's not set (None), the default will be smfs + steering_mode: dmfs - type: ovs_bridge diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py index 4a5cadd8..b10f019a 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -1037,7 +1037,8 @@ class IfcfgNetConfig(os_net_config.NetConfig): utils.update_sriov_pf_map(sriov_pf.name, sriov_pf.numvfs, self.noop, promisc=sriov_pf.promisc, link_mode=sriov_pf.link_mode, - vdpa=sriov_pf.vdpa) + vdpa=sriov_pf.vdpa, + steering_mode=sriov_pf.steering_mode) self.interface_data[sriov_pf.name] = data if sriov_pf.routes: self._add_routes(sriov_pf.name, sriov_pf.routes) diff --git a/os_net_config/objects.py b/os_net_config/objects.py index d4df71d8..d0d44a05 100644 --- a/os_net_config/objects.py +++ b/os_net_config/objects.py @@ -1513,7 +1513,7 @@ class SriovPF(_BaseOpts): defroute=True, dhclient_args=None, dns_servers=None, nm_controlled=False, onboot=True, domain=None, members=None, promisc=None, link_mode='legacy', ethtool_opts=None, - vdpa=False): + vdpa=False, steering_mode=None): addresses = addresses or [] routes = routes or [] rules = rules or [] @@ -1533,6 +1533,7 @@ class SriovPF(_BaseOpts): self.link_mode = link_mode self.ethtool_opts = ethtool_opts self.vdpa = vdpa + self.steering_mode = steering_mode @staticmethod def get_on_off(config): @@ -1553,6 +1554,10 @@ class SriovPF(_BaseOpts): link_mode = json.get('link_mode', 'legacy') ethtool_opts = json.get('ethtool_opts', None) vdpa = json.get('vdpa', False) + steering_mode = json.get('steering_mode') + if steering_mode is not None and steering_mode not in ['smfs', 'dmfs']: + msg = 'Expecting steering_mode to match smfs/dmfs' + raise InvalidConfigException(msg) if vdpa: msg = "" if link_mode != 'switchdev': @@ -1569,7 +1574,7 @@ class SriovPF(_BaseOpts): opts = _BaseOpts.base_opts_from_json(json) return SriovPF(name, numvfs, *opts, promisc=promisc, link_mode=link_mode, ethtool_opts=ethtool_opts, - vdpa=vdpa) + vdpa=vdpa, steering_mode=steering_mode) class OvsDpdkBond(_BaseOpts): diff --git a/os_net_config/schema.yaml b/os_net_config/schema.yaml index 45888b73..78d67856 100644 --- a/os_net_config/schema.yaml +++ b/os_net_config/schema.yaml @@ -38,6 +38,11 @@ definitions: - type: string pattern: "^(legacy|switchdev)$" - $ref: "#/definitions/param" + sriov_steering_mode_or_param: + oneOf: + - type: string + pattern: "^(smfs|dmfs)$" + - $ref: "#/definitions/param" # MAC address type mac_address_string: type: string @@ -365,6 +370,8 @@ definitions: $ref: "#/definitions/sriov_link_mode_or_param" vdpa: $ref: "#/definitions/bool_or_param" + steering_mode: + $ref: "#/definitions/sriov_steering_mode_or_param" required: - type - name diff --git a/os_net_config/sriov_config.py b/os_net_config/sriov_config.py index 9b945581..8150d0cc 100644 --- a/os_net_config/sriov_config.py +++ b/os_net_config/sriov_config.py @@ -362,7 +362,11 @@ def configure_sriov_pf(execution_from_cli=False, restart_openvswitch=False): if not vdpa: # This is used for the sriov_bind_config dpdk_vfs_pcis_list += vf_pcis_list - configure_smfs_software_steering(item['name']) + + # Configure flow steering mode, default to smfs + configure_flow_steering(item['name'], + item.get('steering_mode', 'smfs')) + # Configure switchdev mode configure_switchdev(item['name']) # Adding a udev rule to rename vf-representors @@ -592,17 +596,17 @@ def configure_vdpa_vhost_device(pci): raise -def configure_smfs_software_steering(pf_name): +def configure_flow_steering(pf_name, steering_mode): pf_pci = get_pf_pci(pf_name) try: processutils.execute('/usr/sbin/devlink', 'dev', 'param', 'set', f'pci/{pf_pci}', 'name', 'flow_steering_mode', - 'value', 'smfs', 'cmode', 'runtime') - logger.info(f"{pf_name}: Device pci/{pf_pci} is set to smfs steering " - "mode.") + 'value', steering_mode, 'cmode', 'runtime') + logger.info(f"{pf_name}: Device pci/{pf_pci} is set to" + " {steering_mode} steering mode.") except processutils.ProcessExecutionError as exc: - logger.warning(f"{pf_name}: Could not set pci/{pf_pci} to smfs " - f" steering mode: {exc}") + logger.warning(f"{pf_name}: Could not set pci/{pf_pci} to" + f" {steering_mode} steering mode: {exc}") def run_ip_config_cmd(*cmd, **kwargs): diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py index f22af945..47676fa8 100644 --- a/os_net_config/tests/test_impl_ifcfg.py +++ b/os_net_config/tests/test_impl_ifcfg.py @@ -1659,7 +1659,8 @@ NETMASK=255.255.255.0 pf = objects.SriovPF(name='nic3', numvfs=10) def test_update_sriov_pf_map(name, numvfs, noop, promisc=None, - link_mode='legacy', vdpa=False): + link_mode='legacy', vdpa=False, + steering_mode="smfs"): self.assertEqual(name, 'eth2') self.assertEqual(numvfs, 10) self.assertEqual(promisc, None) @@ -1684,7 +1685,8 @@ BOOTPROTO=none pf = objects.SriovPF(name='nic3', numvfs=10, promisc=True) def test_update_sriov_pf_map(name, numvfs, noop, promisc=None, - link_mode='legacy', vdpa=False): + link_mode='legacy', vdpa=False, + steering_mode="smfs"): self.assertEqual(name, 'eth2') self.assertEqual(numvfs, 10) self.assertTrue(promisc) @@ -1709,7 +1711,8 @@ BOOTPROTO=none pf = objects.SriovPF(name='nic3', numvfs=10, promisc=False) def test_update_sriov_pf_map(name, numvfs, noop, promisc=None, - link_mode='legacy', vdpa=False): + link_mode='legacy', vdpa=False, + steering_mode="smfs"): self.assertEqual(name, 'eth2') self.assertEqual(numvfs, 10) self.assertFalse(promisc) diff --git a/os_net_config/tests/test_objects.py b/os_net_config/tests/test_objects.py index 9a9e896d..523556b7 100644 --- a/os_net_config/tests/test_objects.py +++ b/os_net_config/tests/test_objects.py @@ -1997,6 +1997,52 @@ class TestSriovPF(base.TestCase): expected = 'Expecting to have at least 1 numvfs when vdpa is enabled' self.assertIn(expected, str(err)) + def test_from_json_steering_mode_dmfs(self): + data = '{"type": "sriov_pf", "name": "p6p1", "numvfs": 8,' \ + '"use_dhcp": false, "promisc": false, "link_mode":' \ + '"switchdev", "steering_mode": "dmfs"}' + pf = objects.object_from_json(json.loads(data)) + self.assertEqual("p6p1", pf.name) + self.assertEqual(8, pf.numvfs) + self.assertEqual("off", pf.promisc) + self.assertFalse(pf.use_dhcp) + self.assertEqual("switchdev", pf.link_mode) + self.assertEqual("dmfs", pf.steering_mode) + + def test_from_json_steering_mode_smfs(self): + data = '{"type": "sriov_pf", "name": "p6p1", "numvfs": 8,' \ + '"use_dhcp": false, "promisc": false, "link_mode":' \ + '"switchdev", "steering_mode": "smfs"}' + pf = objects.object_from_json(json.loads(data)) + self.assertEqual("p6p1", pf.name) + self.assertEqual(8, pf.numvfs) + self.assertEqual("off", pf.promisc) + self.assertFalse(pf.use_dhcp) + self.assertEqual("switchdev", pf.link_mode) + self.assertEqual("smfs", pf.steering_mode) + + def test_from_json_steering_mode_none(self): + data = '{"type": "sriov_pf", "name": "p6p1", "numvfs": 8,' \ + '"use_dhcp": false, "promisc": false, "link_mode":' \ + '"switchdev"}' + pf = objects.object_from_json(json.loads(data)) + self.assertEqual("p6p1", pf.name) + self.assertEqual(8, pf.numvfs) + self.assertEqual("off", pf.promisc) + self.assertFalse(pf.use_dhcp) + self.assertEqual("switchdev", pf.link_mode) + self.assertIsNone(pf.steering_mode) + + def test_from_json_steering_mode_invalid(self): + data = '{"type": "sriov_pf", "name": "p6p1", "numvfs": 8,' \ + '"use_dhcp": false, "promisc": false, "link_mode":' \ + '"switchdev", "steering_mode": "dmfss"}' + err = self.assertRaises(objects.InvalidConfigException, + objects.object_from_json, + json.loads(data)) + expected = 'Expecting steering_mode to match smfs/dmfs' + self.assertIn(expected, str(err)) + def test_from_json_ethtool_opts(self): data = '{"type": "sriov_pf", "name": "em1", "numvfs": 16, ' \ '"use_dhcp": false, "promisc": false, ' \ diff --git a/os_net_config/utils.py b/os_net_config/utils.py index ba019e21..759c9075 100644 --- a/os_net_config/utils.py +++ b/os_net_config/utils.py @@ -421,7 +421,7 @@ def _get_dpdk_map(): def update_sriov_pf_map(ifname, numvfs, noop, promisc=None, - link_mode='legacy', vdpa=False): + link_mode='legacy', vdpa=False, steering_mode=None): if not noop: cur_numvfs = sriov_config.get_numvfs(ifname) if cur_numvfs > 0 and cur_numvfs != numvfs: @@ -435,6 +435,8 @@ def update_sriov_pf_map(ifname, numvfs, noop, promisc=None, if promisc is not None: item['promisc'] = promisc item['link_mode'] = link_mode + if steering_mode is not None: + item['steering_mode'] = steering_mode break else: new_item = {} @@ -445,6 +447,8 @@ def update_sriov_pf_map(ifname, numvfs, noop, promisc=None, if promisc is not None: new_item['promisc'] = promisc new_item['link_mode'] = link_mode + if steering_mode is not None: + new_item['steering_mode'] = steering_mode sriov_map.append(new_item) write_yaml_config(common.SRIOV_CONFIG_FILE, sriov_map)