diff --git a/doc/source/admin/config-ml2.rst b/doc/source/admin/config-ml2.rst index 44e00647a47..b9ed28ba9a3 100644 --- a/doc/source/admin/config-ml2.rst +++ b/doc/source/admin/config-ml2.rst @@ -260,6 +260,31 @@ For more details, see the Configuration of those drivers is not part of this document. +Supported VNIC types +^^^^^^^^^^^^^^^^^^^^ + +The ``vnic_type_blacklist`` option is used to remove values from the mechanism driver's +``supported_vnic_types`` list. + +.. list-table:: Mechanism drivers and supported VNIC types + :header-rows: 1 + + * - mech driver / supported_vnic_types + - supported VNIC types + - blacklisting available + * - Linux bridge + - normal + - no + * - MacVTap + - macvtap + - no + * - Open vSwitch + - normal, direct + - yes (ovs_driver vnic_type_blacklist, see: `Configuration Reference <../configuration/ml2-conf.html#ovs_driver>`__) + * - SRIOV + - direct, macvtap, direct_physical + - no + Extension Drivers ----------------- diff --git a/neutron/conf/plugins/ml2/drivers/openvswitch/__init__.py b/neutron/conf/plugins/ml2/drivers/openvswitch/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/neutron/conf/plugins/ml2/drivers/openvswitch/mech_ovs_conf.py b/neutron/conf/plugins/ml2/drivers/openvswitch/mech_ovs_conf.py new file mode 100644 index 00000000000..5e34ff2c47a --- /dev/null +++ b/neutron/conf/plugins/ml2/drivers/openvswitch/mech_ovs_conf.py @@ -0,0 +1,40 @@ +# Copyright (c) 2018 Ericsson +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_config import cfg + +from neutron._i18n import _ + + +ovs_driver_opts = [ + cfg.ListOpt('vnic_type_blacklist', + default=[], + help=_("Comma-separated list of VNIC types for which support " + "is administratively prohibited by the mechanism " + "driver. Please note that the supported vnic_types " + "depend on your network interface card, on the kernel " + "version of your operating system, and on other " + "factors, like OVS version. In case of ovs mechanism " + "driver the valid vnic types are normal and direct. " + "Note that direct is supported only from kernel 4.8, " + "and from ovs 2.8.0. Bind DIRECT (SR-IOV) port allows " + "to offload the OVS flows using tc to the SR-IOV NIC. " + "This allows to support hardware offload via tc and " + "that allows us to manage the VF by OpenFlow control " + "plane using representor net-device.")), +] + + +def register_ovs_mech_driver_opts(cfg=cfg.CONF): + cfg.register_opts(ovs_driver_opts, "OVS_DRIVER") diff --git a/neutron/opts.py b/neutron/opts.py index 0d1a1d93bc9..f968902a47a 100644 --- a/neutron/opts.py +++ b/neutron/opts.py @@ -47,6 +47,7 @@ import neutron.conf.plugins.ml2.drivers.l2pop import neutron.conf.plugins.ml2.drivers.linuxbridge import neutron.conf.plugins.ml2.drivers.macvtap import neutron.conf.plugins.ml2.drivers.mech_sriov.agent_common +import neutron.conf.plugins.ml2.drivers.openvswitch.mech_ovs_conf import neutron.conf.plugins.ml2.drivers.ovs_conf import neutron.conf.quota import neutron.conf.service @@ -255,7 +256,10 @@ def list_ml2_conf_opts(): ('securitygroup', neutron.conf.agent.securitygroups_rpc.security_group_opts), ('l2pop', - neutron.conf.plugins.ml2.drivers.l2pop.l2_population_options) + neutron.conf.plugins.ml2.drivers.l2pop.l2_population_options), + ('ovs_driver', + neutron.conf.plugins.ml2.drivers.openvswitch.mech_ovs_conf. + ovs_driver_opts) ] diff --git a/neutron/plugins/ml2/drivers/mech_agent.py b/neutron/plugins/ml2/drivers/mech_agent.py index 56e7907df04..ee1fa12e8e3 100644 --- a/neutron/plugins/ml2/drivers/mech_agent.py +++ b/neutron/plugins/ml2/drivers/mech_agent.py @@ -22,6 +22,7 @@ from neutron_lib.plugins.ml2 import api from oslo_log import log import six +from neutron._i18n import _ from neutron.db import provisioning_blocks LOG = log.getLogger(__name__) @@ -132,6 +133,34 @@ class AgentMechanismDriverBase(api.MechanismDriver): return True. Otherwise, it must return False. """ + def blacklist_supported_vnic_types(self, vnic_types, blacklist): + """Validate the blacklist and blacklist the supported_vnic_types + + :param vnic_types: The supported_vnic_types list + :param blacklist: The blacklist as in vnic_type_blacklist + :return The blacklisted vnic_types + """ + if not blacklist: + return vnic_types + + # Not valid values in the blacklist: + if not all(bl in vnic_types for bl in blacklist): + raise ValueError(_("Not all of the items from vnic_type_blacklist " + "are valid vnic_types for %(agent)s mechanism " + "driver. The valid values are: " + "%(valid_vnics)s.") % + {'agent': self.agent_type, + 'valid_vnics': vnic_types}) + + supported_vnic_types = [vnic_t for vnic_t in vnic_types if + vnic_t not in blacklist] + + # Nothing left in the supported vnict types list: + if len(supported_vnic_types) < 1: + raise ValueError(_("All possible vnic_types were blacklisted for " + "%s mechanism driver!") % self.agent_type) + return supported_vnic_types + @six.add_metaclass(abc.ABCMeta) class SimpleAgentMechanismDriverBase(AgentMechanismDriverBase): diff --git a/neutron/plugins/ml2/drivers/openvswitch/mech_driver/mech_openvswitch.py b/neutron/plugins/ml2/drivers/openvswitch/mech_driver/mech_openvswitch.py index a2ba6ee943b..8d67ca2ffd6 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/mech_driver/mech_openvswitch.py +++ b/neutron/plugins/ml2/drivers/openvswitch/mech_driver/mech_openvswitch.py @@ -23,6 +23,7 @@ from oslo_config import cfg from oslo_log import log from neutron.agent import securitygroups_rpc +from neutron.conf.plugins.ml2.drivers.openvswitch import mech_ovs_conf from neutron.plugins.ml2.drivers import mech_agent from neutron.plugins.ml2.drivers.openvswitch.agent.common \ import constants as a_const @@ -34,6 +35,8 @@ LOG = log.getLogger(__name__) IPTABLES_FW_DRIVER_FULL = ("neutron.agent.linux.iptables_firewall." "OVSHybridIptablesFirewallDriver") +mech_ovs_conf.register_ovs_mech_driver_opts() + class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase): """Attach to networks using openvswitch L2 agent. @@ -60,8 +63,18 @@ class OpenvswitchMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase): super(OpenvswitchMechanismDriver, self).__init__( constants.AGENT_TYPE_OVS, portbindings.VIF_TYPE_OVS, - vif_details, supported_vnic_types=[portbindings.VNIC_NORMAL, - portbindings.VNIC_DIRECT]) + vif_details) + + # TODO(lajoskatona): move this blacklisting to + # SimpleAgentMechanismDriverBase. By that e blacklisting and validation + # of the vnic_types would be available for all mechanism drivers. + self.supported_vnic_types = self.blacklist_supported_vnic_types( + vnic_types=[portbindings.VNIC_NORMAL, portbindings.VNIC_DIRECT], + blacklist=cfg.CONF.OVS_DRIVER.vnic_type_blacklist + ) + LOG.info("%s's supported_vnic_types: %s", + self.agent_type, self.supported_vnic_types) + ovs_qos_driver.register() log_driver.register() diff --git a/neutron/tests/unit/plugins/ml2/_test_mech_agent.py b/neutron/tests/unit/plugins/ml2/_test_mech_agent.py index 3562dddf0bf..89398c29171 100644 --- a/neutron/tests/unit/plugins/ml2/_test_mech_agent.py +++ b/neutron/tests/unit/plugins/ml2/_test_mech_agent.py @@ -13,6 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_config import cfg +from oslo_config import fixture as config_fixture + from neutron_lib.api.definitions import portbindings from neutron_lib.plugins.ml2 import api @@ -171,6 +174,31 @@ class FakePortContext(api.PortContext): pass +class MechDriverConfFixture(config_fixture.Config): + + def __init__(self, conf=cfg.CONF, blacklist_cfg=None, + registration_func=None): + """ConfigFixture for vnic_type_blacklist + + :param conf: The driver configuration object + :param blacklist_cfg: A dictionary in the form + {'group': {'opt': 'value'}}, i.e.: + {'OVS_DRIVER': {'vnic_type_blacklist': + ['foo']}} + :param registration_func: The method which do the config group's + registration. + """ + super(MechDriverConfFixture, self).__init__(conf) + self.blacklist_cfg = blacklist_cfg + self.registration_func = registration_func + + def setUp(self): + super(MechDriverConfFixture, self).setUp() + self.registration_func(self.conf) + for group, option in self.blacklist_cfg.items(): + self.config(group=group, **option) + + class AgentMechanismBaseTestCase(base.BaseTestCase): # The following must be overridden for the specific mechanism # driver being tested: diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/mech_driver/test_mech_openvswitch.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/mech_driver/test_mech_openvswitch.py index 7a4e4e76ab2..7405e85597a 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/mech_driver/test_mech_openvswitch.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/mech_driver/test_mech_openvswitch.py @@ -21,6 +21,7 @@ from neutron_lib import constants from neutron_lib.plugins.ml2 import api from oslo_config import cfg +from neutron.conf.plugins.ml2.drivers.openvswitch import mech_ovs_conf from neutron.plugins.ml2.drivers.openvswitch.agent.common import ( constants as a_const) from neutron.plugins.ml2.drivers.openvswitch.mech_driver import ( @@ -296,3 +297,61 @@ class OpenvswitchMechanismSRIOVTestCase(OpenvswitchMechanismBaseTestCase): context = self._make_port_ctx(self.AGENTS, profile=profile) self.driver.bind_port(context) mocked_bind_port.assert_called() + + +class OpenvswitchMechVnicTypesTestCase(OpenvswitchMechanismBaseTestCase): + def setUp(self): + self.blacklist_cfg = { + 'OVS_DRIVER': { + 'vnic_type_blacklist': [] + } + } + self.default_supported_vnics = [portbindings.VNIC_NORMAL, + portbindings.VNIC_DIRECT] + super(OpenvswitchMechVnicTypesTestCase, self).setUp() + + def test_default_vnic_types(self): + self.assertEqual([portbindings.VNIC_NORMAL, + portbindings.VNIC_DIRECT], + self.driver.supported_vnic_types) + + def test_vnic_type_blacklist_valid_item(self): + self.blacklist_cfg['OVS_DRIVER']['vnic_type_blacklist'] = \ + [portbindings.VNIC_DIRECT] + + fake_conf = cfg.CONF + fake_conf_fixture = base.MechDriverConfFixture( + fake_conf, self.blacklist_cfg, + mech_ovs_conf.register_ovs_mech_driver_opts) + self.useFixture(fake_conf_fixture) + + test_driver = mech_openvswitch.OpenvswitchMechanismDriver() + + supported_vnic_types = test_driver.supported_vnic_types + self.assertNotIn(portbindings.VNIC_DIRECT, supported_vnic_types) + self.assertEqual(len(self.default_supported_vnics) - 1, + len(supported_vnic_types)) + + def test_vnic_type_blacklist_not_valid_item(self): + self.blacklist_cfg['OVS_DRIVER']['vnic_type_blacklist'] = ['foo'] + + fake_conf = cfg.CONF + fake_conf_fixture = base.MechDriverConfFixture( + fake_conf, self.blacklist_cfg, + mech_ovs_conf.register_ovs_mech_driver_opts) + self.useFixture(fake_conf_fixture) + + self.assertRaises(ValueError, + mech_openvswitch.OpenvswitchMechanismDriver) + + def test_vnic_type_blacklist_all_items(self): + self.blacklist_cfg['OVS_DRIVER']['vnic_type_blacklist'] = \ + [portbindings.VNIC_NORMAL, portbindings.VNIC_DIRECT] + fake_conf = cfg.CONF + fake_conf_fixture = base.MechDriverConfFixture( + fake_conf, self.blacklist_cfg, + mech_ovs_conf.register_ovs_mech_driver_opts) + self.useFixture(fake_conf_fixture) + + self.assertRaises(ValueError, + mech_openvswitch.OpenvswitchMechanismDriver) diff --git a/releasenotes/notes/make-supported-vnic-types-configurable-for-ovs-fc73422daffd42b0.yaml b/releasenotes/notes/make-supported-vnic-types-configurable-for-ovs-fc73422daffd42b0.yaml new file mode 100644 index 00000000000..f612fdd2da3 --- /dev/null +++ b/releasenotes/notes/make-supported-vnic-types-configurable-for-ovs-fc73422daffd42b0.yaml @@ -0,0 +1,9 @@ +--- +other: + - | + Add new configuration group ``ovs_driver`` and new configuration option + under it ``vnic_type_blacklist``, to make the previously hardcoded + ``supported_vnic_types`` parameter of the OpenvswitchMechanismDriver + configurable. + The ``vnic_types`` listed in the blacklist will be removed from the + supported_vnic_types list.