Merge "Make floatingip reachable from the same network"
This commit is contained in:
commit
8305c85898
@ -82,6 +82,9 @@
|
||||
# Iptables mangle mark used to mark metadata valid requests
|
||||
# metadata_access_mark = 0x1
|
||||
|
||||
# Iptables mangle mark used to mark ingress from external network
|
||||
# external_ingress_mark = 0x2
|
||||
|
||||
# router_delete_namespaces, which is false by default, can be set to True if
|
||||
# namespaces can be deleted cleanly on the host running the L3 agent.
|
||||
# Do not enable this until you understand the problem with the Linux iproute
|
||||
|
@ -81,5 +81,9 @@ OPTS = [
|
||||
cfg.StrOpt('metadata_access_mark',
|
||||
default='0x1',
|
||||
help=_('Iptables mangle mark used to mark metadata valid '
|
||||
'requests'))
|
||||
'requests')),
|
||||
cfg.StrOpt('external_ingress_mark',
|
||||
default='0x2',
|
||||
help=_('Iptables mangle mark used to mark ingress from '
|
||||
'external network')),
|
||||
]
|
||||
|
@ -29,6 +29,8 @@ LOG = logging.getLogger(__name__)
|
||||
INTERNAL_DEV_PREFIX = namespaces.INTERNAL_DEV_PREFIX
|
||||
EXTERNAL_DEV_PREFIX = namespaces.EXTERNAL_DEV_PREFIX
|
||||
|
||||
EXTERNAL_INGRESS_MARK_MASK = '0xffffffff'
|
||||
|
||||
|
||||
class RouterInfo(object):
|
||||
|
||||
@ -489,17 +491,28 @@ class RouterInfo(object):
|
||||
interface_name)
|
||||
|
||||
def external_gateway_nat_rules(self, ex_gw_ip, interface_name):
|
||||
mark = self.agent_conf.external_ingress_mark
|
||||
rules = [('POSTROUTING', '! -i %(interface_name)s '
|
||||
'! -o %(interface_name)s -m conntrack ! '
|
||||
'--ctstate DNAT -j ACCEPT' %
|
||||
{'interface_name': interface_name}),
|
||||
('snat', '-o %s -j SNAT --to-source %s' %
|
||||
(interface_name, ex_gw_ip))]
|
||||
(interface_name, ex_gw_ip)),
|
||||
('snat', '-m mark ! --mark %s '
|
||||
'-m conntrack --ctstate DNAT '
|
||||
'-j SNAT --to-source %s' % (mark, ex_gw_ip))]
|
||||
return rules
|
||||
|
||||
def external_gateway_mangle_rules(self, interface_name):
|
||||
mark = self.agent_conf.external_ingress_mark
|
||||
rules = [('mark', '-i %s -j MARK --set-xmark %s/%s' %
|
||||
(interface_name, mark, EXTERNAL_INGRESS_MARK_MASK))]
|
||||
return rules
|
||||
|
||||
def _empty_snat_chains(self, iptables_manager):
|
||||
iptables_manager.ipv4['nat'].empty_chain('POSTROUTING')
|
||||
iptables_manager.ipv4['nat'].empty_chain('snat')
|
||||
iptables_manager.ipv4['mangle'].empty_chain('mark')
|
||||
|
||||
def _add_snat_rules(self, ex_gw_port, iptables_manager,
|
||||
interface_name, action):
|
||||
@ -513,6 +526,9 @@ class RouterInfo(object):
|
||||
interface_name)
|
||||
for rule in rules:
|
||||
iptables_manager.ipv4['nat'].add_rule(*rule)
|
||||
rules = self.external_gateway_mangle_rules(interface_name)
|
||||
for rule in rules:
|
||||
iptables_manager.ipv4['mangle'].add_rule(*rule)
|
||||
break
|
||||
|
||||
def _handle_router_snat_rules(self, ex_gw_port,
|
||||
|
@ -364,6 +364,11 @@ class IptablesManager(object):
|
||||
self.ipv4['nat'].add_chain('float-snat')
|
||||
self.ipv4['nat'].add_rule('snat', '-j $float-snat')
|
||||
|
||||
# Add a mark chain to mangle PREROUTING chain. It is used to
|
||||
# identify ingress packets from a certain interface.
|
||||
self.ipv4['mangle'].add_chain('mark')
|
||||
self.ipv4['mangle'].add_rule('PREROUTING', '-j $mark')
|
||||
|
||||
def get_chain(self, table, chain, ip_version=4, wrap=True):
|
||||
try:
|
||||
requested_table = {4: self.ipv4, 6: self.ipv6}[ip_version][table]
|
||||
|
@ -637,6 +637,43 @@ class L3AgentTestCase(L3AgentTestFramework):
|
||||
router1.ns_name,
|
||||
router1.get_ha_device_name()))
|
||||
|
||||
def test_fip_connection_from_same_subnet(self):
|
||||
'''Test connection to floatingip which is associated with
|
||||
fixed_ip on the same subnet of the source fixed_ip.
|
||||
In other words it confirms that return packets surely
|
||||
go through the router.
|
||||
'''
|
||||
router_info = self.generate_router_info(enable_ha=False)
|
||||
router = self.manage_router(self.agent, router_info)
|
||||
router_ip_cidr = self._port_first_ip_cidr(router.internal_ports[0])
|
||||
router_ip = router_ip_cidr.partition('/')[0]
|
||||
|
||||
src_ip_cidr = net_helpers.increment_ip_cidr(router_ip_cidr)
|
||||
dst_ip_cidr = net_helpers.increment_ip_cidr(src_ip_cidr)
|
||||
dst_ip = dst_ip_cidr.partition('/')[0]
|
||||
dst_fip = '19.4.4.10'
|
||||
router.router[l3_constants.FLOATINGIP_KEY] = []
|
||||
self._add_fip(router, dst_fip, fixed_address=dst_ip)
|
||||
router.process(self.agent)
|
||||
|
||||
src_ns = self._create_namespace(prefix='test-src-')
|
||||
dst_ns = self._create_namespace(prefix='test-dst-')
|
||||
br_int = get_ovs_bridge(self.agent.conf.ovs_integration_bridge)
|
||||
src_port = self.bind_namespace_to_cidr(src_ns, br_int, src_ip_cidr)
|
||||
net_helpers.set_namespace_gateway(src_port, router_ip)
|
||||
dst_port = self.bind_namespace_to_cidr(dst_ns, br_int, dst_ip_cidr)
|
||||
net_helpers.set_namespace_gateway(dst_port, router_ip)
|
||||
|
||||
protocol_port = helpers.get_free_namespace_port(dst_ns)
|
||||
# client sends to fip
|
||||
netcat = helpers.NetcatTester(src_ns, dst_ns, dst_ip,
|
||||
protocol_port,
|
||||
client_address=dst_fip,
|
||||
run_as_root=True,
|
||||
udp=False)
|
||||
self.addCleanup(netcat.stop_processes)
|
||||
self.assertTrue(netcat.test_connectivity())
|
||||
|
||||
|
||||
class L3HATestFramework(L3AgentTestFramework):
|
||||
|
||||
|
@ -203,11 +203,13 @@ def _generate_mangle_dump(iptables_args):
|
||||
':%(bn)s-OUTPUT - [0:0]\n'
|
||||
':%(bn)s-POSTROUTING - [0:0]\n'
|
||||
':%(bn)s-PREROUTING - [0:0]\n'
|
||||
':%(bn)s-mark - [0:0]\n'
|
||||
'[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
|
||||
'[0:0] -A INPUT -j %(bn)s-INPUT\n'
|
||||
'[0:0] -A FORWARD -j %(bn)s-FORWARD\n'
|
||||
'[0:0] -A OUTPUT -j %(bn)s-OUTPUT\n'
|
||||
'[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING\n'
|
||||
'[0:0] -A %(bn)s-PREROUTING -j %(bn)s-mark\n'
|
||||
'COMMIT\n'
|
||||
'# Completed by iptables_manager\n' % iptables_args)
|
||||
|
||||
@ -593,11 +595,13 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase):
|
||||
':%(bn)s-POSTROUTING - [0:0]\n'
|
||||
':%(bn)s-PREROUTING - [0:0]\n'
|
||||
':%(bn)s-mangle - [0:0]\n'
|
||||
':%(bn)s-mark - [0:0]\n'
|
||||
'[0:0] -A PREROUTING -j %(bn)s-PREROUTING\n'
|
||||
'[0:0] -A INPUT -j %(bn)s-INPUT\n'
|
||||
'[0:0] -A FORWARD -j %(bn)s-FORWARD\n'
|
||||
'[0:0] -A OUTPUT -j %(bn)s-OUTPUT\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 MARK --set-xmark 0x1/0xffffffff\n'
|
||||
'COMMIT\n'
|
||||
'# Completed by iptables_manager\n'
|
||||
|
@ -806,7 +806,8 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
router['gw_port_host'] = HOSTNAME
|
||||
self._test_external_gateway_action('remove', router, dual_stack=True)
|
||||
|
||||
def _verify_snat_rules(self, rules, router, negate=False):
|
||||
def _verify_snat_mangle_rules(self, nat_rules, mangle_rules, router,
|
||||
negate=False):
|
||||
interfaces = router[l3_constants.INTERFACE_KEY]
|
||||
source_cidrs = []
|
||||
for iface in interfaces:
|
||||
@ -820,8 +821,17 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
expected_rules = [
|
||||
'! -i %s ! -o %s -m conntrack ! --ctstate DNAT -j ACCEPT' %
|
||||
(interface_name, interface_name),
|
||||
'-o %s -j SNAT --to-source %s' % (interface_name, source_nat_ip)]
|
||||
for r in rules:
|
||||
'-o %s -j SNAT --to-source %s' % (interface_name, source_nat_ip),
|
||||
'-m mark ! --mark 0x2 -m conntrack --ctstate DNAT '
|
||||
'-j SNAT --to-source %s' % source_nat_ip]
|
||||
for r in nat_rules:
|
||||
if negate:
|
||||
self.assertNotIn(r.rule, expected_rules)
|
||||
else:
|
||||
self.assertIn(r.rule, expected_rules)
|
||||
expected_rules = [
|
||||
'-i %s -j MARK --set-xmark 0x2/0xffffffff' % interface_name]
|
||||
for r in mangle_rules:
|
||||
if negate:
|
||||
self.assertNotIn(r.rule, expected_rules)
|
||||
else:
|
||||
@ -1191,6 +1201,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
# Process with NAT
|
||||
ri.process(agent)
|
||||
orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
|
||||
orig_mangle_rules = ri.iptables_manager.ipv4['mangle'].rules[:]
|
||||
# Reprocess without NAT
|
||||
router['enable_snat'] = False
|
||||
# Reassign the router object to RouterInfo
|
||||
@ -1200,8 +1211,13 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
# IpTablesRule instances
|
||||
nat_rules_delta = [r for r in orig_nat_rules
|
||||
if r not in ri.iptables_manager.ipv4['nat'].rules]
|
||||
self.assertEqual(len(nat_rules_delta), 2)
|
||||
self._verify_snat_rules(nat_rules_delta, router)
|
||||
self.assertEqual(len(nat_rules_delta), 3)
|
||||
mangle_rules_delta = [
|
||||
r for r in orig_mangle_rules
|
||||
if r not in ri.iptables_manager.ipv4['mangle'].rules]
|
||||
self.assertEqual(len(mangle_rules_delta), 1)
|
||||
self._verify_snat_mangle_rules(nat_rules_delta, mangle_rules_delta,
|
||||
router)
|
||||
self.assertEqual(self.send_arp.call_count, 1)
|
||||
|
||||
def test_process_router_snat_enabled(self):
|
||||
@ -1212,6 +1228,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
# Process without NAT
|
||||
ri.process(agent)
|
||||
orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
|
||||
orig_mangle_rules = ri.iptables_manager.ipv4['mangle'].rules[:]
|
||||
# Reprocess with NAT
|
||||
router['enable_snat'] = True
|
||||
# Reassign the router object to RouterInfo
|
||||
@ -1221,8 +1238,13 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
# IpTablesRule instances
|
||||
nat_rules_delta = [r for r in ri.iptables_manager.ipv4['nat'].rules
|
||||
if r not in orig_nat_rules]
|
||||
self.assertEqual(len(nat_rules_delta), 2)
|
||||
self._verify_snat_rules(nat_rules_delta, router)
|
||||
self.assertEqual(len(nat_rules_delta), 3)
|
||||
mangle_rules_delta = [
|
||||
r for r in ri.iptables_manager.ipv4['mangle'].rules
|
||||
if r not in orig_mangle_rules]
|
||||
self.assertEqual(len(mangle_rules_delta), 1)
|
||||
self._verify_snat_mangle_rules(nat_rules_delta, mangle_rules_delta,
|
||||
router)
|
||||
self.assertEqual(self.send_arp.call_count, 1)
|
||||
|
||||
def test_process_router_interface_added(self):
|
||||
@ -1560,14 +1582,24 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
|
||||
jump_float_rule = "-A %s-snat -j %s-float-snat" % (wrap_name,
|
||||
wrap_name)
|
||||
snat_rule = ("-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'])
|
||||
snat_rule2 = ("-A %s-snat -m mark ! --mark 0x2 "
|
||||
"-m conntrack --ctstate DNAT "
|
||||
"-j SNAT --to-source %s") % (
|
||||
wrap_name, ex_gw_port['fixed_ips'][0]['ip_address'])
|
||||
|
||||
self.assertIn(jump_float_rule, nat_rules)
|
||||
|
||||
self.assertIn(snat_rule, nat_rules)
|
||||
self.assertIn(snat_rule1, nat_rules)
|
||||
self.assertIn(snat_rule2, nat_rules)
|
||||
self.assertThat(nat_rules.index(jump_float_rule),
|
||||
matchers.LessThan(nat_rules.index(snat_rule)))
|
||||
matchers.LessThan(nat_rules.index(snat_rule1)))
|
||||
|
||||
mangle_rules = map(str, ri.iptables_manager.ipv4['mangle'].rules)
|
||||
mangle_rule = ("-A %s-mark -i iface "
|
||||
"-j MARK --set-xmark 0x2/0xffffffff") % wrap_name
|
||||
self.assertIn(mangle_rule, mangle_rules)
|
||||
|
||||
def test_process_router_delete_stale_internal_devices(self):
|
||||
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
||||
|
@ -1673,7 +1673,7 @@ IPTABLES_ARG = {'bn': iptables_manager.binary_name,
|
||||
'physdev_mod': PHYSDEV_MOD,
|
||||
'physdev_is_bridged': PHYSDEV_IS_BRIDGED}
|
||||
|
||||
CHAINS_MANGLE = 'FORWARD|INPUT|OUTPUT|POSTROUTING|PREROUTING'
|
||||
CHAINS_MANGLE = 'FORWARD|INPUT|OUTPUT|POSTROUTING|PREROUTING|mark'
|
||||
IPTABLES_ARG['chains'] = CHAINS_MANGLE
|
||||
|
||||
IPTABLES_MANGLE = """# Generated by iptables_manager
|
||||
@ -1683,11 +1683,13 @@ IPTABLES_MANGLE = """# Generated by iptables_manager
|
||||
:%(bn)s-(%(chains)s) - [0:0]
|
||||
:%(bn)s-(%(chains)s) - [0:0]
|
||||
:%(bn)s-(%(chains)s) - [0:0]
|
||||
:%(bn)s-(%(chains)s) - [0:0]
|
||||
[0:0] -A PREROUTING -j %(bn)s-PREROUTING
|
||||
[0:0] -A INPUT -j %(bn)s-INPUT
|
||||
[0:0] -A FORWARD -j %(bn)s-FORWARD
|
||||
[0:0] -A OUTPUT -j %(bn)s-OUTPUT
|
||||
[0:0] -A POSTROUTING -j %(bn)s-POSTROUTING
|
||||
[0:0] -A %(bn)s-PREROUTING -j %(bn)s-mark
|
||||
COMMIT
|
||||
# Completed by iptables_manager
|
||||
""" % IPTABLES_ARG
|
||||
|
Loading…
Reference in New Issue
Block a user