ADDRESS_SCOPE_MARK_IDS should not be global for L3 agent

Otherwise agent becomes unable to handle more than 1024 routers
(including deleted routers) and starts failing.

It should be enough to distinguish address scopes inside router namespace,
so this patch moves ADDRESS_SCOPE_MARK_IDS set to the RouterInfo class.

Closes-Bug: #1566291
Change-Id: I1e43bb3e68db4db93cc1dfc1383af0311bfb0f2d
This commit is contained in:
Oleg Bondarev 2016-04-05 16:18:03 +03:00
parent dfd3efef22
commit 1cb4373480
2 changed files with 29 additions and 5 deletions

View File

@ -33,7 +33,8 @@ EXTERNAL_DEV_PREFIX = namespaces.EXTERNAL_DEV_PREFIX
FLOATINGIP_STATUS_NOCHANGE = object()
ADDRESS_SCOPE_MARK_MASK = "0xffff0000"
ADDRESS_SCOPE_MARK_IDS = set(range(1024, 2048))
ADDRESS_SCOPE_MARK_ID_MIN = 1024
ADDRESS_SCOPE_MARK_ID_MAX = 2048
DEFAULT_ADDRESS_SCOPE = "noscope"
@ -57,8 +58,10 @@ class RouterInfo(object):
router_id, agent_conf, interface_driver, use_ipv6)
self.router_namespace = ns
self.ns_name = ns.name
self.available_mark_ids = set(range(ADDRESS_SCOPE_MARK_ID_MIN,
ADDRESS_SCOPE_MARK_ID_MAX))
self._address_scope_to_mark_id = {
DEFAULT_ADDRESS_SCOPE: ADDRESS_SCOPE_MARK_IDS.pop()}
DEFAULT_ADDRESS_SCOPE: self.available_mark_ids.pop()}
self.iptables_manager = iptables_manager.IptablesManager(
use_ipv6=use_ipv6,
namespace=self.ns_name)
@ -160,10 +163,8 @@ class RouterInfo(object):
address_scope = DEFAULT_ADDRESS_SCOPE
if address_scope not in self._address_scope_to_mark_id:
mark_ids = set(self._address_scope_to_mark_id.values())
available_ids = ADDRESS_SCOPE_MARK_IDS - mark_ids
self._address_scope_to_mark_id[address_scope] = (
available_ids.pop())
self.available_mark_ids.pop())
mark_id = self._address_scope_to_mark_id[address_scope]
# NOTE: Address scopes use only the upper 16 bits of the 32 fwmark

View File

@ -143,6 +143,29 @@ class TestRouterInfo(base.BaseTestCase):
ipv4_mangle.add_rule.assert_called_once_with(
'scope', ri.address_scope_mangle_rule('fake_device', 'fake_mark'))
def test_address_scope_mark_ids_handling(self):
mark_ids = set(range(router_info.ADDRESS_SCOPE_MARK_ID_MIN,
router_info.ADDRESS_SCOPE_MARK_ID_MAX))
ri = router_info.RouterInfo(_uuid(), {}, **self.ri_kwargs)
# first mark id is used for the default address scope
scope_to_mark_id = {router_info.DEFAULT_ADDRESS_SCOPE: mark_ids.pop()}
self.assertEqual(scope_to_mark_id, ri._address_scope_to_mark_id)
self.assertEqual(mark_ids, ri.available_mark_ids)
# new id should be used for new address scope
ri.get_address_scope_mark_mask('new_scope')
scope_to_mark_id['new_scope'] = mark_ids.pop()
self.assertEqual(scope_to_mark_id, ri._address_scope_to_mark_id)
self.assertEqual(mark_ids, ri.available_mark_ids)
# new router should have it's own mark ids set
new_mark_ids = set(range(router_info.ADDRESS_SCOPE_MARK_ID_MIN,
router_info.ADDRESS_SCOPE_MARK_ID_MAX))
new_ri = router_info.RouterInfo(_uuid(), {}, **self.ri_kwargs)
new_mark_ids.pop()
self.assertEqual(new_mark_ids, new_ri.available_mark_ids)
self.assertTrue(ri.available_mark_ids != new_ri.available_mark_ids)
class BasicRouterTestCaseFramework(base.BaseTestCase):
def _create_router(self, router=None, **kwargs):