]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Add Geneve type driver support to ML2
authorAaron Rosen <aaronorosen@gmail.com>
Tue, 5 May 2015 21:35:08 +0000 (14:35 -0700)
committerGal Sagie <gal.sagie@huawei.com>
Thu, 27 Aug 2015 17:04:35 +0000 (20:04 +0300)
More information about Geneve protocol can be found here:
  https://tools.ietf.org/pdf/draft-gross-geneve-02.pdf

Following configuration variables were added:
[ml2_type_geneve]
  vni_ranges - Comma-separated list of <vni_min>:<vni_max> tuples
               enumerating ranges of Geneve VNI IDs that are
               available for tenant network allocation
  max_header_size - Geneve encapsulation header size is dynamic, this
                    value is used to calculate the maximum MTU for the driver
                    this is the sum of the sizes of the outer
                    ETH + IP + UDP + GENEVE header sizes

DocImpact

Change-Id: I8c29a1c1a7c79e02c26ac9e2ad2645d30dfbeefc
Closes-Bug: #1461069

17 files changed:
doc/source/devref/openvswitch_agent.rst
etc/neutron/plugins/ml2/ml2_conf.ini
neutron/cmd/sanity/checks.py
neutron/cmd/sanity_check.py
neutron/db/migration/alembic_migrations/versions/HEADS
neutron/db/migration/alembic_migrations/versions/liberty/contract/11926bcfe72d_add_geneve_ml2_type_driver.py [new file with mode: 0644]
neutron/db/migration/models/head.py
neutron/plugins/common/constants.py
neutron/plugins/common/utils.py
neutron/plugins/ml2/config.py
neutron/plugins/ml2/drivers/openvswitch/agent/common/constants.py
neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py
neutron/plugins/ml2/drivers/type_geneve.py [new file with mode: 0644]
neutron/tests/functional/sanity/test_sanity.py
neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/test_br_tun.py
neutron/tests/unit/plugins/ml2/drivers/test_type_geneve.py [new file with mode: 0644]
setup.cfg

index a4b2685320a96dfbbec80e708a2b3a5b107b1490..177520071bc767ac5db7973cab6bfa2001b83035 100644 (file)
@@ -26,7 +26,6 @@ GRE Tunneling is documented in depth in the `Networking in too much
 detail <http://openstack.redhat.com/Networking_in_too_much_detail>`_
 by RedHat.
 
-
 VXLAN Tunnels
 -------------
 
@@ -35,6 +34,16 @@ at layer 2 into a UDP header.
 More information can be found in `The VXLAN wiki page.
 <http://en.wikipedia.org/wiki/Virtual_Extensible_LAN>`_
 
+Geneve Tunnels
+--------------
+
+Geneve uses UDP as its transport protocol and is dynamic
+in size using extensible option headers.
+It is important to note that currently it is only supported in
+newer kernels. (kernel >= 3.18, OVS version >=2.4)
+More information can be found in the `Geneve RFC document.
+<https://tools.ietf.org/html/draft-ietf-nvo3-geneve-00>`_
+
 
 Bridge Management
 -----------------
@@ -71,6 +80,7 @@ future to support existing VLAN-tagged traffic (coming from NFV VMs
 for instance) and/or to deal with potential QinQ support natively
 available in the Open vSwitch.
 
+
 Further Reading
 ---------------
 
index 9aad25b7b8bddb8b30c39131d522e51a1f3d10fb..2cef2c6ffb9a52069e97f5b6a36c9623c22aae53 100644 (file)
@@ -2,15 +2,16 @@
 # (ListOpt) List of network type driver entrypoints to be loaded from
 # the neutron.ml2.type_drivers namespace.
 #
-# type_drivers = local,flat,vlan,gre,vxlan
-# Example: type_drivers = flat,vlan,gre,vxlan
+# type_drivers = local,flat,vlan,gre,vxlan,geneve
+# Example: type_drivers = flat,vlan,gre,vxlan,geneve
 
 # (ListOpt) Ordered list of network_types to allocate as tenant
 # networks. The default value 'local' is useful for single-box testing
 # but provides no connectivity between hosts.
 #
 # tenant_network_types = local
-# Example: tenant_network_types = vlan,gre,vxlan
+# Example: tenant_network_types = vlan,gre,vxlan,geneve
+
 
 # (ListOpt) Ordered list of networking mechanism driver entrypoints
 # to be loaded from the neutron.ml2.mechanism_drivers namespace.
 # vxlan_group =
 # Example: vxlan_group = 239.1.1.1
 
+[ml2_type_geneve]
+# (ListOpt) Comma-separated list of <vni_min>:<vni_max> tuples enumerating
+# ranges of Geneve VNI IDs that are available for tenant network allocation.
+#
+# vni_ranges =
+
+# (IntOpt) Geneve encapsulation header size is dynamic, this
+# value is used to calculate the maximum MTU for the driver.
+# this is the sum of the sizes of the outer ETH+IP+UDP+GENEVE
+# header sizes.
+# The default size for this field is 50, which is the size of the
+# Geneve header without any additional option headers
+#
+# max_header_size =
+# Example: max_header_size = 50 (Geneve headers with no additional options)
+
 [securitygroup]
 # Controls if neutron security group is enabled or not.
 # It should be false when you use nova security group.
index 484438e05f381832f142ff72f5bc39df0b49453a..819d00c23e21c6caaf784d667b19b61470136df2 100644 (file)
@@ -52,6 +52,13 @@ def ovs_vxlan_supported(from_ip='192.0.2.1', to_ip='192.0.2.2'):
         return port != ovs_lib.INVALID_OFPORT
 
 
+def ovs_geneve_supported(from_ip='192.0.2.3', to_ip='192.0.2.4'):
+    name = "genevetest-" + utils.get_random_string(6)
+    with ovs_lib.OVSBridge(name) as br:
+        port = br.add_tunnel_port(from_ip, to_ip, const.TYPE_GENEVE)
+        return port != ovs_lib.INVALID_OFPORT
+
+
 def iproute2_vxlan_supported():
     ip = ip_lib.IPWrapper()
     name = "vxlantest-" + utils.get_random_string(4)
index 123db3edb2d6ea7184c0cd8961cae870db219e66..2188f3771a7dd54765dfa1a57190a7e8a98215a8 100644 (file)
@@ -56,6 +56,15 @@ def check_ovs_vxlan():
     return result
 
 
+def check_ovs_geneve():
+    result = checks.ovs_geneve_supported()
+    if not result:
+        LOG.error(_LE('Check for Open vSwitch Geneve support failed. '
+                      'Please ensure that the version of openvswitch '
+                      'and kernel being used has Geneve support.'))
+    return result
+
+
 def check_iproute2_vxlan():
     result = checks.iproute2_vxlan_supported()
     if not result:
@@ -181,6 +190,8 @@ def check_ebtables():
 OPTS = [
     BoolOptCallback('ovs_vxlan', check_ovs_vxlan, default=False,
                     help=_('Check for OVS vxlan support')),
+    BoolOptCallback('ovs_geneve', check_ovs_geneve, default=False,
+                    help=_('Check for OVS Geneve support')),
     BoolOptCallback('iproute2_vxlan', check_iproute2_vxlan, default=False,
                     help=_('Check for iproute2 vxlan support')),
     BoolOptCallback('ovs_patch', check_ovs_patch, default=False,
@@ -216,6 +227,8 @@ def enable_tests_from_config():
 
     if 'vxlan' in cfg.CONF.AGENT.tunnel_types:
         cfg.CONF.set_override('ovs_vxlan', True)
+    if 'geneve' in cfg.CONF.AGENT.tunnel_types:
+        cfg.CONF.set_override('ovs_geneve', True)
     if ('vxlan' in cfg.CONF.ml2.type_drivers or
             cfg.CONF.VXLAN.enable_vxlan):
         cfg.CONF.set_override('iproute2_vxlan', True)
index 5e424af8a52ae9d345abffa0f7dc408a0501291c..9928899efb210c1cf2ed0f8adc5e3798cf534fc4 100644 (file)
@@ -1,2 +1,2 @@
-2e5352a0ad4d
+11926bcfe72d
 34af2b5c5a59
diff --git a/neutron/db/migration/alembic_migrations/versions/liberty/contract/11926bcfe72d_add_geneve_ml2_type_driver.py b/neutron/db/migration/alembic_migrations/versions/liberty/contract/11926bcfe72d_add_geneve_ml2_type_driver.py
new file mode 100644 (file)
index 0000000..9ef5584
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright 2015 OpenStack Foundation
+#
+#    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.
+#
+
+"""add geneve ml2 type driver
+
+Revision ID: 11926bcfe72d
+Revises: 2e5352a0ad4d
+Create Date: 2015-08-27 19:56:16.356522
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '11926bcfe72d'
+down_revision = '2e5352a0ad4d'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.create_table(
+        'ml2_geneve_allocations',
+        sa.Column('geneve_vni', sa.Integer(),
+                  autoincrement=False, nullable=False),
+        sa.Column('allocated', sa.Boolean(),
+                  server_default=sa.sql.false(), nullable=False),
+        sa.PrimaryKeyConstraint('geneve_vni'),
+    )
+    op.create_index(op.f('ix_ml2_geneve_allocations_allocated'),
+                    'ml2_geneve_allocations', ['allocated'], unique=False)
+    op.create_table(
+        'ml2_geneve_endpoints',
+        sa.Column('ip_address', sa.String(length=64), nullable=False),
+        sa.Column('host', sa.String(length=255), nullable=True),
+        sa.PrimaryKeyConstraint('ip_address'),
+        sa.UniqueConstraint('host', name='unique_ml2_geneve_endpoints0host'),
+    )
index 54953981865c13eae687ed8a4444e257dad5229b..72e5e660e04de74e52fd9b7a227d2871d896b68b 100644 (file)
@@ -56,6 +56,7 @@ from neutron.plugins.cisco.db import network_models_v2  # noqa
 from neutron.plugins.ml2.drivers.brocade.db import (  # noqa
     models as ml2_brocade_models)
 from neutron.plugins.ml2.drivers import type_flat  # noqa
+from neutron.plugins.ml2.drivers import type_geneve  # noqa
 from neutron.plugins.ml2.drivers import type_gre  # noqa
 from neutron.plugins.ml2.drivers import type_vlan  # noqa
 from neutron.plugins.ml2.drivers import type_vxlan  # noqa
index e5aa166d15c92976dde74ac89ba81091686803ed..65a0fb3e55db95f4b01caaeff764212ec9cdec61 100644 (file)
@@ -56,6 +56,7 @@ ACTIVE_PENDING_STATUSES = (
 
 # Network Type constants
 TYPE_FLAT = 'flat'
+TYPE_GENEVE = 'geneve'
 TYPE_GRE = 'gre'
 TYPE_LOCAL = 'local'
 TYPE_VXLAN = 'vxlan'
@@ -68,6 +69,10 @@ TYPE_NONE = 'none'
 MIN_VLAN_TAG = 1
 MAX_VLAN_TAG = 4094
 
+# For Geneve Tunnel
+MIN_GENEVE_VNI = 1
+MAX_GENEVE_VNI = 2 ** 24 - 1
+
 # For GRE Tunnel
 MIN_GRE_ID = 1
 MAX_GRE_ID = 2 ** 32 - 1
@@ -78,5 +83,6 @@ MAX_VXLAN_VNI = 2 ** 24 - 1
 VXLAN_UDP_PORT = 4789
 
 # Network Type MTU overhead
+GENEVE_ENCAP_MIN_OVERHEAD = 50
 GRE_ENCAP_OVERHEAD = 42
 VXLAN_ENCAP_OVERHEAD = 50
index 287ea1a30013f539e790bbe0d97b36ba0dbf9862..61e7c164f243642b87f1ff2628aadeda5fb01e33 100644 (file)
@@ -35,10 +35,15 @@ def is_valid_vxlan_vni(vni):
     return p_const.MIN_VXLAN_VNI <= vni <= p_const.MAX_VXLAN_VNI
 
 
+def is_valid_geneve_vni(vni):
+    return p_const.MIN_GENEVE_VNI <= vni <= p_const.MAX_GENEVE_VNI
+
+
 def verify_tunnel_range(tunnel_range, tunnel_type):
     """Raise an exception for invalid tunnel range or malformed range."""
     mappings = {p_const.TYPE_GRE: is_valid_gre_id,
-                p_const.TYPE_VXLAN: is_valid_vxlan_vni}
+                p_const.TYPE_VXLAN: is_valid_vxlan_vni,
+                p_const.TYPE_GENEVE: is_valid_geneve_vni}
     if tunnel_type in mappings:
         for ident in tunnel_range:
             if not mappings[tunnel_type](ident):
index 3eb3b2bd4a097a77b9ac52a461715ac6bc8ea1c0..a248c1ceb8041b5cd07ea7df043422c0fdafbc69 100644 (file)
@@ -18,7 +18,7 @@ from oslo_config import cfg
 
 ml2_opts = [
     cfg.ListOpt('type_drivers',
-                default=['local', 'flat', 'vlan', 'gre', 'vxlan'],
+                default=['local', 'flat', 'vlan', 'gre', 'vxlan', 'geneve'],
                 help=_("List of network type driver entrypoints to be loaded "
                        "from the neutron.ml2.type_drivers namespace.")),
     cfg.ListOpt('tenant_network_types',
index 6dde277a88a000fb7b586bb146fd98b1ad304d22..4643ffe279e14c170e82b9a3d122165739c13bd9 100644 (file)
@@ -32,7 +32,9 @@ PEER_PHYSICAL_PREFIX = 'phy-'
 NONEXISTENT_PEER = 'nonexistent-peer'
 
 # The different types of tunnels
-TUNNEL_NETWORK_TYPES = [p_const.TYPE_GRE, p_const.TYPE_VXLAN]
+TUNNEL_NETWORK_TYPES = [p_const.TYPE_GRE, p_const.TYPE_VXLAN,
+                        p_const.TYPE_GENEVE]
+
 
 # Various tables for DVR use of integration bridge flows
 LOCAL_SWITCHING = 0
@@ -44,6 +46,8 @@ DVR_PROCESS = 1
 PATCH_LV_TO_TUN = 2
 GRE_TUN_TO_LV = 3
 VXLAN_TUN_TO_LV = 4
+GENEVE_TUN_TO_LV = 6
+
 DVR_NOT_LEARN = 9
 LEARN_FROM_TUN = 10
 UCAST_TO_TUN = 20
@@ -67,7 +71,9 @@ ARP_REPLY = '0x2'
 
 # Map tunnel types to tables number
 TUN_TABLE = {p_const.TYPE_GRE: GRE_TUN_TO_LV,
-             p_const.TYPE_VXLAN: VXLAN_TUN_TO_LV}
+             p_const.TYPE_VXLAN: VXLAN_TUN_TO_LV,
+             p_const.TYPE_GENEVE: GENEVE_TUN_TO_LV}
+
 
 # The default respawn interval for the ovsdb monitor
 DEFAULT_OVSDBMON_RESPAWN = 30
index 0c590e38c8e50378ccc4185dd1ac682f5b44607e..117b181497db163819acceb1bc22069a24f73f40 100644 (file)
@@ -239,7 +239,9 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
         self.bridge_mappings = bridge_mappings
         self.setup_physical_bridges(self.bridge_mappings)
         self.local_vlan_map = {}
-        self.tun_br_ofports = {p_const.TYPE_GRE: {},
+
+        self.tun_br_ofports = {p_const.TYPE_GENEVE: {},
+                               p_const.TYPE_GRE: {},
                                p_const.TYPE_VXLAN: {}}
 
         self.polling_interval = polling_interval
@@ -584,7 +586,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
 
         :param net_uuid: the uuid of the network associated with this vlan.
         :param network_type: the network type ('gre', 'vxlan', 'vlan', 'flat',
-                                               'local')
+                                               'local', 'geneve')
         :param physical_network: the physical network for 'vlan' or 'flat'
         :param segmentation_id: the VID for 'vlan' or tunnel ID for 'tunnel'
         '''
@@ -1738,9 +1740,10 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
     def _check_agent_configurations(self):
         if (self.enable_distributed_routing and self.enable_tunneling
             and not self.l2_pop):
-            raise ValueError(_("DVR deployments for VXLAN/GRE underlays "
-                               "require L2-pop to be enabled, in both the "
-                               "Agent and Server side."))
+
+            raise ValueError(_("DVR deployments for VXLAN/GRE/Geneve "
+                               "underlays require L2-pop to be enabled, "
+                               "in both the Agent and Server side."))
 
 
 def create_agent_config_map(config):
diff --git a/neutron/plugins/ml2/drivers/type_geneve.py b/neutron/plugins/ml2/drivers/type_geneve.py
new file mode 100644 (file)
index 0000000..d8f430a
--- /dev/null
@@ -0,0 +1,103 @@
+# Copyright (c) 2015 OpenStack Foundation
+# All Rights Reserved.
+#
+#    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 oslo_log import log
+import sqlalchemy as sa
+from sqlalchemy import sql
+
+from neutron.common import exceptions as n_exc
+from neutron.db import model_base
+from neutron.i18n import _LE
+from neutron.plugins.common import constants as p_const
+from neutron.plugins.ml2.drivers import type_tunnel
+
+LOG = log.getLogger(__name__)
+
+geneve_opts = [
+    cfg.ListOpt('vni_ranges',
+                default=[],
+                help=_("Comma-separated list of <vni_min>:<vni_max> tuples "
+                       "enumerating ranges of Geneve VNI IDs that are "
+                       "available for tenant network allocation")),
+    cfg.IntOpt('max_header_size',
+               default=p_const.GENEVE_ENCAP_MIN_OVERHEAD,
+               help=_("Geneve encapsulation header size is dynamic, this "
+                      "value is used to calculate the maximum MTU "
+                      "for the driver."
+                      "this is the sum of the sizes of the outer "
+                      "ETH + IP + UDP + GENEVE header sizes")),
+]
+
+cfg.CONF.register_opts(geneve_opts, "ml2_type_geneve")
+
+
+class GeneveAllocation(model_base.BASEV2):
+
+    __tablename__ = 'ml2_geneve_allocations'
+
+    geneve_vni = sa.Column(sa.Integer, nullable=False, primary_key=True,
+                        autoincrement=False)
+    allocated = sa.Column(sa.Boolean, nullable=False, default=False,
+                          server_default=sql.false(), index=True)
+
+
+class GeneveEndpoints(model_base.BASEV2):
+    """Represents tunnel endpoint in RPC mode."""
+
+    __tablename__ = 'ml2_geneve_endpoints'
+    __table_args__ = (
+        sa.UniqueConstraint('host',
+                            name='unique_ml2_geneve_endpoints0host'),
+        model_base.BASEV2.__table_args__
+    )
+    ip_address = sa.Column(sa.String(64), primary_key=True)
+    host = sa.Column(sa.String(255), nullable=True)
+
+    def __repr__(self):
+        return "<GeneveTunnelEndpoint(%s)>" % self.ip_address
+
+
+class GeneveTypeDriver(type_tunnel.EndpointTunnelTypeDriver):
+
+    def __init__(self):
+        super(GeneveTypeDriver, self).__init__(GeneveAllocation,
+                                               GeneveEndpoints)
+        self.max_encap_size = cfg.CONF.ml2_type_geneve.max_header_size
+
+    def get_type(self):
+        return p_const.TYPE_GENEVE
+
+    def initialize(self):
+        try:
+            self._initialize(cfg.CONF.ml2_type_geneve.vni_ranges)
+        except n_exc.NetworkTunnelRangeError:
+            LOG.error(_LE("Failed to parse vni_ranges. "
+                          "Service terminated!"))
+            raise SystemExit()
+
+    def get_endpoints(self):
+        """Get every geneve endpoints from database."""
+        geneve_endpoints = self._get_endpoints()
+        return [{'ip_address': geneve_endpoint.ip_address,
+                 'host': geneve_endpoint.host}
+                for geneve_endpoint in geneve_endpoints]
+
+    def add_endpoint(self, ip, host):
+        return self._add_endpoint(ip, host)
+
+    def get_mtu(self, physical_network=None):
+        mtu = super(GeneveTypeDriver, self).get_mtu()
+        return mtu - self.max_encap_size if mtu else 0
index f6029e8ed7bf4db2248ccf086f8d62ba920e077c..a47bb4e2759e9afc65e8accb22c074936d4cd2aa 100644 (file)
@@ -50,6 +50,9 @@ class SanityTestCaseRoot(functional_base.BaseSudoTestCase):
     def test_ovs_vxlan_support_runs(self):
         checks.ovs_vxlan_supported()
 
+    def test_ovs_geneve_support_runs(self):
+        checks.ovs_geneve_supported()
+
     def test_iproute2_vxlan_support_runs(self):
         checks.iproute2_vxlan_supported()
 
index 6d04f230cc5a57a5faa1a5e4b7c71b8ce700efa5..9f730246e3c0fa565e648e04b7cc9e114466ebd6 100644 (file)
@@ -53,6 +53,7 @@ class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase,
                       'actions': 'resubmit(,22)'},
                      {'priority': 0, 'table': 3, 'actions': 'drop'},
                      {'priority': 0, 'table': 4, 'actions': 'drop'},
+                     {'priority': 0, 'table': 6, 'actions': 'drop'},
                      {'priority': 1, 'table': 10,
                       'actions': 'learn(cookie=0x0,table=20,priority=1,'
                       'hard_timeout=300,NXM_OF_VLAN_TCI[0..11],'
@@ -87,6 +88,7 @@ class OVSTunnelBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase,
                       'actions': 'resubmit(,22)'},
                      {'priority': 0, 'table': 3, 'actions': 'drop'},
                      {'priority': 0, 'table': 4, 'actions': 'drop'},
+                     {'priority': 0, 'table': 6, 'actions': 'drop'},
                      {'priority': 1, 'table': 10,
                       'actions': 'learn(cookie=0x0,table=20,priority=1,'
                       'hard_timeout=300,NXM_OF_VLAN_TCI[0..11],'
diff --git a/neutron/tests/unit/plugins/ml2/drivers/test_type_geneve.py b/neutron/tests/unit/plugins/ml2/drivers/test_type_geneve.py
new file mode 100644 (file)
index 0000000..fb0ffdf
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright (c) 2015 OpenStack Foundation
+# All Rights Reserved.
+#
+#    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 neutron.plugins.common import constants as p_const
+from neutron.plugins.ml2.drivers import type_geneve
+from neutron.tests.unit.plugins.ml2.drivers import base_type_tunnel
+from neutron.tests.unit.plugins.ml2 import test_rpc
+from neutron.tests.unit import testlib_api
+
+
+TUNNEL_IP_ONE = "10.10.10.77"
+TUNNEL_IP_TWO = "10.10.10.78"
+HOST_ONE = 'fake_host_one1'
+HOST_TWO = 'fake_host_two2'
+
+
+class GeneveTypeTest(base_type_tunnel.TunnelTypeTestMixin,
+                     testlib_api.SqlTestCase):
+    DRIVER_CLASS = type_geneve.GeneveTypeDriver
+    TYPE = p_const.TYPE_GENEVE
+
+    def test_get_endpoints(self):
+        self.driver.add_endpoint(TUNNEL_IP_ONE, HOST_ONE)
+        self.driver.add_endpoint(TUNNEL_IP_TWO, HOST_TWO)
+
+        endpoints = self.driver.get_endpoints()
+        for endpoint in endpoints:
+            if endpoint['ip_address'] == TUNNEL_IP_ONE:
+                self.assertEqual(HOST_ONE, endpoint['host'])
+            elif endpoint['ip_address'] == TUNNEL_IP_TWO:
+                self.assertEqual(HOST_TWO, endpoint['host'])
+
+
+class GeneveTypeMultiRangeTest(base_type_tunnel.TunnelTypeMultiRangeTestMixin,
+                               testlib_api.SqlTestCase):
+    DRIVER_CLASS = type_geneve.GeneveTypeDriver
+
+
+class GeneveTypeRpcCallbackTest(base_type_tunnel.TunnelRpcCallbackTestMixin,
+                                test_rpc.RpcCallbacksTestCase,
+                                testlib_api.SqlTestCase):
+    DRIVER_CLASS = type_geneve.GeneveTypeDriver
+    TYPE = p_const.TYPE_GENEVE
index c2ac4ac297c2907a4324de4b201d57c372881da2..27feb9a38a334a2cc1c3a3547c76ed0712358ae9 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -151,6 +151,7 @@ neutron.ml2.type_drivers =
     flat = neutron.plugins.ml2.drivers.type_flat:FlatTypeDriver
     local = neutron.plugins.ml2.drivers.type_local:LocalTypeDriver
     vlan = neutron.plugins.ml2.drivers.type_vlan:VlanTypeDriver
+    geneve = neutron.plugins.ml2.drivers.type_geneve:GeneveTypeDriver
     gre = neutron.plugins.ml2.drivers.type_gre:GreTypeDriver
     vxlan = neutron.plugins.ml2.drivers.type_vxlan:VxlanTypeDriver
 neutron.ml2.mechanism_drivers =