Use only the lower 16 bits of iptables mark for marking

Since a packet can only have one mark, and we will need to mark a
packet for multiple purposes, we need to use a coordinated bitmask for
the two cases of simple marking that we currently do in Neutron
leaving the other bits for address scopes.

DocImpact

Change-Id: Id0517758d06e036a36dc8b8772e41af55d986b4e
Partially-Implements: blueprint address-scopes
This commit is contained in:
Carl Baldwin 2015-07-14 19:00:45 +00:00 committed by Brian Haley
parent 704c79cd89
commit aa4fa7b819
7 changed files with 35 additions and 23 deletions

View File

@ -84,9 +84,11 @@ OPTS = [
cfg.StrOpt('metadata_access_mark', cfg.StrOpt('metadata_access_mark',
default='0x1', default='0x1',
help=_('Iptables mangle mark used to mark metadata valid ' help=_('Iptables mangle mark used to mark metadata valid '
'requests')), 'requests. This mark will be masked with 0xffff so '
'that only the lower 16 bits will be used.')),
cfg.StrOpt('external_ingress_mark', cfg.StrOpt('external_ingress_mark',
default='0x2', default='0x2',
help=_('Iptables mangle mark used to mark ingress from ' help=_('Iptables mangle mark used to mark ingress from '
'external network')), 'external network. This mark will be masked with '
'0xffff so that only the lower 16 bits will be used.')),
] ]

View File

@ -30,7 +30,6 @@ LOG = logging.getLogger(__name__)
INTERNAL_DEV_PREFIX = namespaces.INTERNAL_DEV_PREFIX INTERNAL_DEV_PREFIX = namespaces.INTERNAL_DEV_PREFIX
EXTERNAL_DEV_PREFIX = namespaces.EXTERNAL_DEV_PREFIX EXTERNAL_DEV_PREFIX = namespaces.EXTERNAL_DEV_PREFIX
EXTERNAL_INGRESS_MARK_MASK = '0xffffffff'
FLOATINGIP_STATUS_NOCHANGE = object() FLOATINGIP_STATUS_NOCHANGE = object()
@ -551,9 +550,10 @@ class RouterInfo(object):
# Makes replies come back through the router to reverse DNAT # Makes replies come back through the router to reverse DNAT
ext_in_mark = self.agent_conf.external_ingress_mark ext_in_mark = self.agent_conf.external_ingress_mark
snat_internal_traffic_to_floating_ip = ( snat_internal_traffic_to_floating_ip = (
'snat', '-m mark ! --mark %s ' 'snat', '-m mark ! --mark %s/%s '
'-m conntrack --ctstate DNAT ' '-m conntrack --ctstate DNAT '
'-j SNAT --to-source %s' % (ext_in_mark, ex_gw_ip)) '-j SNAT --to-source %s'
% (ext_in_mark, l3_constants.ROUTER_MARK_MASK, ex_gw_ip))
return [dont_snat_traffic_to_internal_ports_if_not_to_floating_ip, return [dont_snat_traffic_to_internal_ports_if_not_to_floating_ip,
snat_normal_external_traffic, snat_normal_external_traffic,
@ -563,7 +563,7 @@ class RouterInfo(object):
mark = self.agent_conf.external_ingress_mark mark = self.agent_conf.external_ingress_mark
mark_packets_entering_external_gateway_port = ( mark_packets_entering_external_gateway_port = (
'mark', '-i %s -j MARK --set-xmark %s/%s' % 'mark', '-i %s -j MARK --set-xmark %s/%s' %
(interface_name, mark, EXTERNAL_INGRESS_MARK_MASK)) (interface_name, mark, l3_constants.ROUTER_MARK_MASK))
return [mark_packets_entering_external_gateway_port] return [mark_packets_entering_external_gateway_port]
def _empty_snat_chains(self, iptables_manager): def _empty_snat_chains(self, iptables_manager):

View File

@ -24,12 +24,12 @@ from neutron.agent.linux import utils
from neutron.callbacks import events from neutron.callbacks import events
from neutron.callbacks import registry from neutron.callbacks import registry
from neutron.callbacks import resources from neutron.callbacks import resources
from neutron.common import constants
from neutron.common import exceptions from neutron.common import exceptions
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
# Access with redirection to metadata proxy iptables mark mask # Access with redirection to metadata proxy iptables mark mask
METADATA_ACCESS_MARK_MASK = '0xffffffff'
METADATA_SERVICE_NAME = 'metadata-proxy' METADATA_SERVICE_NAME = 'metadata-proxy'
@ -45,7 +45,8 @@ class MetadataDriver(object):
@classmethod @classmethod
def metadata_filter_rules(cls, port, mark): def metadata_filter_rules(cls, port, mark):
return [('INPUT', '-m mark --mark %s -j ACCEPT' % mark), return [('INPUT', '-m mark --mark %s/%s -j ACCEPT' %
(mark, constants.ROUTER_MARK_MASK)),
('INPUT', '-p tcp -m tcp --dport %s ' ('INPUT', '-p tcp -m tcp --dport %s '
'-j DROP' % port)] '-j DROP' % port)]
@ -55,7 +56,7 @@ class MetadataDriver(object):
'-p tcp -m tcp --dport 80 ' '-p tcp -m tcp --dport 80 '
'-j MARK --set-xmark %(value)s/%(mask)s' % '-j MARK --set-xmark %(value)s/%(mask)s' %
{'value': mark, {'value': mark,
'mask': METADATA_ACCESS_MARK_MASK})] 'mask': constants.ROUTER_MARK_MASK})]
@classmethod @classmethod
def metadata_nat_rules(cls, port): def metadata_nat_rules(cls, port):

View File

@ -178,3 +178,5 @@ RPC_NAMESPACE_STATE = None
# Default network MTU value when not configured # Default network MTU value when not configured
DEFAULT_NETWORK_MTU = 0 DEFAULT_NETWORK_MTU = 0
ROUTER_MARK_MASK = "0xffff"

View File

@ -687,15 +687,17 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
'! -i %s ! -o %s -m conntrack ! --ctstate DNAT -j ACCEPT' % '! -i %s ! -o %s -m conntrack ! --ctstate DNAT -j ACCEPT' %
(interface_name, interface_name), (interface_name, interface_name),
'-o %s -j SNAT --to-source %s' % (interface_name, source_nat_ip), '-o %s -j SNAT --to-source %s' % (interface_name, source_nat_ip),
'-m mark ! --mark 0x2 -m conntrack --ctstate DNAT ' '-m mark ! --mark 0x2/%s -m conntrack --ctstate DNAT '
'-j SNAT --to-source %s' % source_nat_ip] '-j SNAT --to-source %s' %
(l3_constants.ROUTER_MARK_MASK, source_nat_ip)]
for r in nat_rules: for r in nat_rules:
if negate: if negate:
self.assertNotIn(r.rule, expected_rules) self.assertNotIn(r.rule, expected_rules)
else: else:
self.assertIn(r.rule, expected_rules) self.assertIn(r.rule, expected_rules)
expected_rules = [ expected_rules = [
'-i %s -j MARK --set-xmark 0x2/0xffffffff' % interface_name] '-i %s -j MARK --set-xmark 0x2/%s' %
(interface_name, l3_constants.ROUTER_MARK_MASK)]
for r in mangle_rules: for r in mangle_rules:
if negate: if negate:
self.assertNotIn(r.rule, expected_rules) self.assertNotIn(r.rule, expected_rules)
@ -1527,10 +1529,11 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
wrap_name) wrap_name)
snat_rule1 = ("-A %s-snat -o iface -j SNAT --to-source %s") % ( snat_rule1 = ("-A %s-snat -o iface -j SNAT --to-source %s") % (
wrap_name, ex_gw_port['fixed_ips'][0]['ip_address']) wrap_name, ex_gw_port['fixed_ips'][0]['ip_address'])
snat_rule2 = ("-A %s-snat -m mark ! --mark 0x2 " snat_rule2 = ("-A %s-snat -m mark ! --mark 0x2/%s "
"-m conntrack --ctstate DNAT " "-m conntrack --ctstate DNAT "
"-j SNAT --to-source %s") % ( "-j SNAT --to-source %s") % (
wrap_name, ex_gw_port['fixed_ips'][0]['ip_address']) wrap_name, l3_constants.ROUTER_MARK_MASK,
ex_gw_port['fixed_ips'][0]['ip_address'])
self.assertIn(jump_float_rule, nat_rules) self.assertIn(jump_float_rule, nat_rules)
@ -1541,7 +1544,8 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
mangle_rules = map(str, ri.iptables_manager.ipv4['mangle'].rules) mangle_rules = map(str, ri.iptables_manager.ipv4['mangle'].rules)
mangle_rule = ("-A %s-mark -i iface " mangle_rule = ("-A %s-mark -i iface "
"-j MARK --set-xmark 0x2/0xffffffff") % wrap_name "-j MARK --set-xmark 0x2/%s" %
(wrap_name, l3_constants.ROUTER_MARK_MASK))
self.assertIn(mangle_rule, mangle_rules) self.assertIn(mangle_rule, mangle_rules)
def test_process_router_delete_stale_internal_devices(self): def test_process_router_delete_stale_internal_devices(self):

View File

@ -22,6 +22,7 @@ import testtools
from neutron.agent.linux import iptables_comments as ic from neutron.agent.linux import iptables_comments as ic
from neutron.agent.linux import iptables_manager from neutron.agent.linux import iptables_manager
from neutron.common import constants
from neutron.common import exceptions as n_exc from neutron.common import exceptions as n_exc
from neutron.tests import base from neutron.tests import base
from neutron.tests import tools from neutron.tests import tools
@ -29,7 +30,8 @@ from neutron.tests import tools
IPTABLES_ARG = {'bn': iptables_manager.binary_name, IPTABLES_ARG = {'bn': iptables_manager.binary_name,
'snat_out_comment': ic.SNAT_OUT, 'snat_out_comment': ic.SNAT_OUT,
'filter_rules': ''} 'filter_rules': '',
'mark': constants.ROUTER_MARK_MASK}
NAT_TEMPLATE = ('# Generated by iptables_manager\n' NAT_TEMPLATE = ('# Generated by iptables_manager\n'
'*nat\n' '*nat\n'
@ -603,10 +605,9 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
'[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n' '[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
'[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n' '[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n'
'[0:0] -A %(bn)s-PREROUTING -j %(bn)s-mark\n' '[0:0] -A %(bn)s-PREROUTING -j %(bn)s-mark\n'
'[0:0] -A %(bn)s-PREROUTING -j MARK --set-xmark 0x1/0xffffffff\n' '[0:0] -A %(bn)s-PREROUTING -j MARK --set-xmark 0x1/%(mark)s\n'
'COMMIT\n' 'COMMIT\n'
'# Completed by iptables_manager\n' '# Completed by iptables_manager\n' % IPTABLES_ARG)
% IPTABLES_ARG)
expected_calls_and_values = [ expected_calls_and_values = [
(mock.call(['iptables-save', '-c'], (mock.call(['iptables-save', '-c'],
@ -635,13 +636,13 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
self.iptables.ipv4['mangle'].add_chain('mangle') self.iptables.ipv4['mangle'].add_chain('mangle')
self.iptables.ipv4['mangle'].add_rule( self.iptables.ipv4['mangle'].add_rule(
'PREROUTING', 'PREROUTING',
'-j MARK --set-xmark 0x1/0xffffffff') '-j MARK --set-xmark 0x1/%s' % constants.ROUTER_MARK_MASK)
self.iptables.apply() self.iptables.apply()
self.iptables.ipv4['mangle'].remove_rule( self.iptables.ipv4['mangle'].remove_rule(
'PREROUTING', 'PREROUTING',
'-j MARK --set-xmark 0x1/0xffffffff') '-j MARK --set-xmark 0x1/%s' % constants.ROUTER_MARK_MASK)
self.iptables.ipv4['mangle'].remove_chain('mangle') self.iptables.ipv4['mangle'].remove_chain('mangle')
self.iptables.apply() self.iptables.apply()

View File

@ -23,6 +23,7 @@ from neutron.agent.l3 import config as l3_config
from neutron.agent.l3 import ha as l3_ha_agent from neutron.agent.l3 import ha as l3_ha_agent
from neutron.agent.metadata import config from neutron.agent.metadata import config
from neutron.agent.metadata import driver as metadata_driver from neutron.agent.metadata import driver as metadata_driver
from neutron.common import constants
from neutron.tests import base from neutron.tests import base
@ -39,7 +40,8 @@ class TestMetadataDriverRules(base.BaseTestCase):
metadata_driver.MetadataDriver.metadata_nat_rules(8775)) metadata_driver.MetadataDriver.metadata_nat_rules(8775))
def test_metadata_filter_rules(self): def test_metadata_filter_rules(self):
rules = [('INPUT', '-m mark --mark 0x1 -j ACCEPT'), rules = [('INPUT', '-m mark --mark 0x1/%s -j ACCEPT' %
constants.ROUTER_MARK_MASK),
('INPUT', '-p tcp -m tcp --dport 8775 -j DROP')] ('INPUT', '-p tcp -m tcp --dport 8775 -j DROP')]
self.assertEqual( self.assertEqual(
rules, rules,
@ -49,7 +51,7 @@ class TestMetadataDriverRules(base.BaseTestCase):
rule = ('PREROUTING', '-d 169.254.169.254/32 ' rule = ('PREROUTING', '-d 169.254.169.254/32 '
'-p tcp -m tcp --dport 80 ' '-p tcp -m tcp --dport 80 '
'-j MARK --set-xmark 0x1/%s' % '-j MARK --set-xmark 0x1/%s' %
metadata_driver.METADATA_ACCESS_MARK_MASK) constants.ROUTER_MARK_MASK)
self.assertEqual( self.assertEqual(
[rule], [rule],
metadata_driver.MetadataDriver.metadata_mangle_rules('0x1')) metadata_driver.MetadataDriver.metadata_mangle_rules('0x1'))