summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-04-08 15:57:10 +0000
committerGerrit Code Review <review@openstack.org>2015-04-08 15:57:10 +0000
commit4543a4cefa3910fdc7a2087257d9d4d9e29aa8d1 (patch)
tree1e0b76bc0dbee7b6b6c9771845c3cb5c37393af1
parentbc66a04ae4ee4e1802eed01807dad1815072ab98 (diff)
parentb5b919a7a3569ccb93c3d7d523c1edfaeddb7cb9 (diff)
downloadneutron-4543a4cefa3910fdc7a2087257d9d4d9e29aa8d1.tar.gz
Merge "Add ipset element and hashsize tunables"
-rw-r--r--etc/neutron.conf9
-rw-r--r--neutron/agent/common/config.py15
-rw-r--r--neutron/agent/linux/ipset_manager.py20
-rw-r--r--neutron/tests/unit/agent/linux/test_ipset_manager.py37
4 files changed, 75 insertions, 6 deletions
diff --git a/etc/neutron.conf b/etc/neutron.conf
index 2dd11210e4..b20d099c2f 100644
--- a/etc/neutron.conf
+++ b/etc/neutron.conf
@@ -661,6 +661,15 @@
# each rule's purpose. (System must support the iptables comments module.)
# comment_iptables_rules = True
+# Maximum number of elements which can be stored in an IPset.
+# If None is specified, the system default will be used.
+# ipset_maxelem = 131072
+
+# Initial hash size for an IPset. Must be a power of 2,
+# else the kernel will round it up automatically.
+# If None is specified, the system default will be used.
+# ipset_hashsize = 2048
+
# Use the root helper when listing the namespaces on a system. This may not
# be required depending on the security configuration. If the root helper is
# not required, set this to False for a performance improvement.
diff --git a/neutron/agent/common/config.py b/neutron/agent/common/config.py
index 7e63ea3878..efc1ca4760 100644
--- a/neutron/agent/common/config.py
+++ b/neutron/agent/common/config.py
@@ -63,6 +63,17 @@ IPTABLES_OPTS = [
help=_("Add comments to iptables rules.")),
]
+IPSET_OPTS = [
+ cfg.IntOpt('ipset_maxelem', default=131072,
+ help=_("Maximum number of elements which can be stored in "
+ "an IPset. If None is specified, the system default "
+ "will be used.")),
+ cfg.IntOpt('ipset_hashsize', default=2048,
+ help=_("Initial hash size for an IPset. Must be a power of 2, "
+ "else the kernel will round it up automatically. If "
+ "None is specified, the system default will be used.")),
+]
+
PROCESS_MONITOR_OPTS = [
cfg.StrOpt('check_child_processes_action', default='respawn',
choices=['respawn', 'exit'],
@@ -122,6 +133,10 @@ def register_iptables_opts(conf):
conf.register_opts(IPTABLES_OPTS, 'AGENT')
+def register_ipset_opts(conf):
+ conf.register_opts(IPSET_OPTS, 'AGENT')
+
+
def register_process_monitor_opts(conf):
conf.register_opts(PROCESS_MONITOR_OPTS, 'AGENT')
diff --git a/neutron/agent/linux/ipset_manager.py b/neutron/agent/linux/ipset_manager.py
index e5ab7a01e9..33b6379b58 100644
--- a/neutron/agent/linux/ipset_manager.py
+++ b/neutron/agent/linux/ipset_manager.py
@@ -11,6 +11,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from oslo_config import cfg
+
+from neutron.agent.common import config
from neutron.agent.linux import utils as linux_utils
from neutron.common import utils
@@ -29,6 +32,7 @@ class IpsetManager(object):
def __init__(self, execute=None, namespace=None):
self.execute = execute or linux_utils.execute
self.namespace = namespace
+ config.register_ipset_opts(cfg.CONF)
self.ipset_sets = {}
@staticmethod
@@ -39,6 +43,15 @@ class IpsetManager(object):
name = ethertype + id
return name[:IPSET_NAME_MAX_LENGTH]
+ @staticmethod
+ def get_hashargs():
+ args = []
+ if cfg.CONF.AGENT.ipset_hashsize:
+ args.extend(['hashsize', str(cfg.CONF.AGENT.ipset_hashsize)])
+ if cfg.CONF.AGENT.ipset_maxelem:
+ args.extend(['maxelem', str(cfg.CONF.AGENT.ipset_maxelem)])
+ return args
+
def set_exists(self, id, ethertype):
"""Returns true if the id+ethertype pair is known to the manager."""
set_name = self.get_name(id, ethertype)
@@ -85,8 +98,10 @@ class IpsetManager(object):
def _refresh_set(self, set_name, member_ips, ethertype):
new_set_name = set_name + SWAP_SUFFIX
set_type = self._get_ipset_set_type(ethertype)
- process_input = ["create %s hash:ip family %s" % (new_set_name,
- set_type)]
+ hash_args = ' '.join(self.get_hashargs())
+ process_input = ["create %s hash:ip family %s %s" % (new_set_name,
+ set_type,
+ hash_args)]
for ip in member_ips:
process_input.append("add %s %s" % (new_set_name, ip))
@@ -103,6 +118,7 @@ class IpsetManager(object):
def _create_set(self, set_name, ethertype):
cmd = ['ipset', 'create', '-exist', set_name, 'hash:ip', 'family',
self._get_ipset_set_type(ethertype)]
+ cmd.extend(self.get_hashargs())
self._apply(cmd)
self.ipset_sets[set_name] = []
diff --git a/neutron/tests/unit/agent/linux/test_ipset_manager.py b/neutron/tests/unit/agent/linux/test_ipset_manager.py
index cbd156218f..19fbb7e20e 100644
--- a/neutron/tests/unit/agent/linux/test_ipset_manager.py
+++ b/neutron/tests/unit/agent/linux/test_ipset_manager.py
@@ -12,7 +12,9 @@
# limitations under the License.
import mock
+from oslo_config import cfg
+from neutron.agent.common import config as a_cfg
from neutron.agent.linux import ipset_manager
from neutron.tests import base
@@ -25,8 +27,13 @@ FAKE_IPS = ['10.0.0.1', '10.0.0.2', '10.0.0.3', '10.0.0.4',
class BaseIpsetManagerTest(base.BaseTestCase):
- def setUp(self):
+ def setUp(self, maxelem=None, hashsize=None):
super(BaseIpsetManagerTest, self).setUp()
+ cfg.CONF.register_opts(a_cfg.IPSET_OPTS, 'AGENT')
+ cfg.CONF.set_override('ipset_maxelem', maxelem, 'AGENT')
+ cfg.CONF.set_override('ipset_hashsize', hashsize, 'AGENT')
+ self.maxelem = maxelem
+ self.hashsize = hashsize
self.ipset = ipset_manager.IpsetManager()
self.execute = mock.patch.object(self.ipset, "execute").start()
self.expected_calls = []
@@ -36,7 +43,13 @@ class BaseIpsetManagerTest(base.BaseTestCase):
self.execute.assert_has_calls(self.expected_calls, any_order=False)
def expect_set(self, addresses):
- temp_input = ['create IPv4fake_sgid-new hash:ip family inet']
+ hash_args = []
+ if self.hashsize:
+ hash_args.extend(['hashsize', str(self.hashsize)])
+ if self.maxelem:
+ hash_args.extend(['maxelem', str(self.maxelem)])
+ temp_input = ['create IPv4fake_sgid-new hash:ip family inet %s' %
+ ' '.join(hash_args)]
temp_input.extend('add IPv4fake_sgid-new %s' % ip for ip in addresses)
input = '\n'.join(temp_input)
self.expected_calls.extend([
@@ -63,9 +76,14 @@ class BaseIpsetManagerTest(base.BaseTestCase):
run_as_root=True) for ip in addresses)
def expect_create(self):
+ ipset_call = ['ipset', 'create', '-exist', TEST_SET_NAME,
+ 'hash:ip', 'family', 'inet']
+ if self.hashsize:
+ ipset_call.extend(['hashsize', str(self.hashsize)])
+ if self.maxelem:
+ ipset_call.extend(['maxelem', str(self.maxelem)])
self.expected_calls.append(
- mock.call(['ipset', 'create', '-exist', TEST_SET_NAME,
- 'hash:ip', 'family', 'inet'],
+ mock.call(ipset_call,
process_input=None,
run_as_root=True))
@@ -85,6 +103,10 @@ class BaseIpsetManagerTest(base.BaseTestCase):
class IpsetManagerTestCase(BaseIpsetManagerTest):
+ """Run all tests, but with maxelem/hashsize values not configured
+ """
+ def setUp(self):
+ super(IpsetManagerTestCase, self).setUp()
def test_set_exists(self):
self.add_first_ip()
@@ -117,3 +139,10 @@ class IpsetManagerTestCase(BaseIpsetManagerTest):
self.expect_destroy()
self.ipset.destroy(TEST_SET_ID, ETHERTYPE)
self.verify_mock_calls()
+
+
+class IpsetManagerTestCaseHashArgs(IpsetManagerTestCase):
+ """Run all the above tests, but with maxelem/hashsize values configured
+ """
+ def setUp(self):
+ super(IpsetManagerTestCase, self).setUp(maxelem=131072, hashsize=2048)