[openstack-neutron/f20] Install SNAT rules for ipv4 only
Ihar Hrachyshka
ihrachyshka at fedoraproject.org
Tue Jun 17 08:52:20 UTC 2014
commit 4698b9650ea17bd164d4255304d7513cbdcd6391
Author: Ihar Hrachyshka <ihrachys at redhat.com>
Date: Tue Jun 17 10:49:01 2014 +0200
Install SNAT rules for ipv4 only
0006-Install-SNAT-rules-for-ipv4-only.patch | 209 +++++++++++++++++++++++++++
openstack-neutron.spec | 7 +-
2 files changed, 215 insertions(+), 1 deletions(-)
---
diff --git a/0006-Install-SNAT-rules-for-ipv4-only.patch b/0006-Install-SNAT-rules-for-ipv4-only.patch
new file mode 100644
index 0000000..7a27b65
--- /dev/null
+++ b/0006-Install-SNAT-rules-for-ipv4-only.patch
@@ -0,0 +1,209 @@
+From ed91f4a26827778aec9ba0baf1cd8a0f6fb9b1e9 Mon Sep 17 00:00:00 2001
+From: Baodong Li <baoli at cisco.com>
+Date: Thu, 24 Apr 2014 01:47:13 +0000
+Subject: [PATCH] Install SNAT rules for ipv4 only
+
+Change-Id: I37bd770aa0d54a985ac2bec708c571785084e0ec
+Closes-Bug: #1309195
+(cherry picked from commit d23bc8fa6e2d8a735a2aa75224b1bc96a3b992f5)
+(cherry picked from commit e5fed4812633b0e7cbcb4107b6dc04710e007edf)
+---
+ neutron/agent/l3_agent.py | 19 ++++--
+ neutron/tests/unit/test_l3_agent.py | 123 +++++++++++++++++++++++++++++++++---
+ 2 files changed, 128 insertions(+), 14 deletions(-)
+
+diff --git a/neutron/agent/l3_agent.py b/neutron/agent/l3_agent.py
+index ebef907..e7e7ed2 100644
+--- a/neutron/agent/l3_agent.py
++++ b/neutron/agent/l3_agent.py
+@@ -387,7 +387,9 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
+ ri.internal_ports.remove(p)
+ self.internal_network_removed(ri, p['id'], p['ip_cidr'])
+
+- internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports]
++ # Get IPv4 only internal CIDRs
++ internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports
++ if netaddr.IPNetwork(p['ip_cidr']).version == 4]
+ # TODO(salv-orlando): RouterInfo would be a better place for
+ # this logic too
+ ex_gw_port_id = (ex_gw_port and ex_gw_port['id'] or
+@@ -432,11 +434,16 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
+ # And add them back if the action if add_rules
+ if action == 'add_rules' and ex_gw_port:
+ # ex_gw_port should not be None in this case
+- ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
+- for rule in self.external_gateway_nat_rules(ex_gw_ip,
+- internal_cidrs,
+- interface_name):
+- ri.iptables_manager.ipv4['nat'].add_rule(*rule)
++ # NAT rules are added only if ex_gw_port has an IPv4 address
++ for ip_addr in ex_gw_port['fixed_ips']:
++ ex_gw_ip = ip_addr['ip_address']
++ if netaddr.IPAddress(ex_gw_ip).version == 4:
++ rules = self.external_gateway_nat_rules(ex_gw_ip,
++ internal_cidrs,
++ interface_name)
++ for rule in rules:
++ ri.iptables_manager.ipv4['nat'].add_rule(*rule)
++ break
+ ri.iptables_manager.apply()
+
+ def process_router_floating_ips(self, ri, ex_gw_port):
+diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py
+index eb93047..e1289ab 100644
+--- a/neutron/tests/unit/test_l3_agent.py
++++ b/neutron/tests/unit/test_l3_agent.py
+@@ -18,6 +18,7 @@
+ import copy
+
+ import mock
++import netaddr
+ from oslo.config import cfg
+
+ from neutron.agent.common import config as agent_config
+@@ -303,24 +304,37 @@ class TestBasicRouterOperations(base.BaseTestCase):
+ '! -i %s ! -o %s -m conntrack ! --ctstate DNAT -j ACCEPT' %
+ (interface_name, interface_name)]
+ for source_cidr in source_cidrs:
+- value_dict = {'source_cidr': source_cidr,
+- 'source_nat_ip': source_nat_ip}
+- expected_rules.append('-s %(source_cidr)s -j SNAT --to-source '
+- '%(source_nat_ip)s' % value_dict)
++ # Create SNAT rules for IPv4 only
++ if (netaddr.IPNetwork(source_cidr).version == 4 and
++ netaddr.IPNetwork(source_nat_ip).version == 4):
++ value_dict = {'source_cidr': source_cidr,
++ 'source_nat_ip': source_nat_ip}
++ expected_rules.append('-s %(source_cidr)s -j SNAT --to-source '
++ '%(source_nat_ip)s' % value_dict)
+ for r in rules:
+ if negate:
+ self.assertNotIn(r.rule, expected_rules)
+ else:
+ self.assertIn(r.rule, expected_rules)
+
+- def _prepare_router_data(self, enable_snat=None, num_internal_ports=1):
++ def _prepare_router_data(self, ip_version=4,
++ enable_snat=None, num_internal_ports=1):
++ if ip_version == 4:
++ ip_addr = '19.4.4.4'
++ cidr = '19.4.4.0/24'
++ gateway_ip = '19.4.4.1'
++ elif ip_version == 6:
++ ip_addr = 'fd00::4'
++ cidr = 'fd00::/64'
++ gateway_ip = 'fd00::1'
++
+ router_id = _uuid()
+ ex_gw_port = {'id': _uuid(),
+ 'network_id': _uuid(),
+- 'fixed_ips': [{'ip_address': '19.4.4.4',
++ 'fixed_ips': [{'ip_address': ip_addr,
+ 'subnet_id': _uuid()}],
+- 'subnet': {'cidr': '19.4.4.0/24',
+- 'gateway_ip': '19.4.4.1'}}
++ 'subnet': {'cidr': cidr,
++ 'gateway_ip': gateway_ip}}
+ int_ports = []
+ for i in range(0, num_internal_ports):
+ int_ports.append({'id': _uuid(),
+@@ -525,6 +539,99 @@ class TestBasicRouterOperations(base.BaseTestCase):
+ self.assertEqual(len(nat_rules_delta), 1)
+ self._verify_snat_rules(nat_rules_delta, router)
+
++ def test_process_ipv6_only_gw(self):
++ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
++ router = self._prepare_router_data(ip_version=6)
++ # Get NAT rules without the gw_port
++ gw_port = router['gw_port']
++ router['gw_port'] = None
++ ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++ self.conf.use_namespaces, router=router)
++ agent.external_gateway_added = mock.Mock()
++ agent.process_router(ri)
++ orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++
++ # Get NAT rules with the gw_port
++ router['gw_port'] = gw_port
++ ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++ self.conf.use_namespaces, router=router)
++ with mock.patch.object(
++ agent,
++ 'external_gateway_nat_rules') as external_gateway_nat_rules:
++ agent.process_router(ri)
++ new_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++
++ # There should be no change with the NAT rules
++ self.assertFalse(external_gateway_nat_rules.called)
++ self.assertEqual(orig_nat_rules, new_nat_rules)
++
++ def test_process_router_ipv6_interface_added(self):
++ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
++ router = self._prepare_router_data()
++ ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++ self.conf.use_namespaces, router=router)
++ agent.external_gateway_added = mock.Mock()
++ # Process with NAT
++ agent.process_router(ri)
++ orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++ # Add an IPv6 interface and reprocess
++ router[l3_constants.INTERFACE_KEY].append(
++ {'id': _uuid(),
++ 'network_id': _uuid(),
++ 'admin_state_up': True,
++ 'fixed_ips': [{'ip_address': 'fd00::2',
++ 'subnet_id': _uuid()}],
++ 'mac_address': 'ca:fe:de:ad:be:ef',
++ 'subnet': {'cidr': 'fd00::/64',
++ 'gateway_ip': 'fd00::1'}})
++ # Reassign the router object to RouterInfo
++ ri.router = router
++ agent.process_router(ri)
++ # For some reason set logic does not work well with
++ # IpTablesRule instances
++ nat_rules_delta = [r for r in ri.iptables_manager.ipv4['nat'].rules
++ if r not in orig_nat_rules]
++ self.assertFalse(nat_rules_delta)
++
++ def test_process_router_ipv6v4_interface_added(self):
++ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
++ router = self._prepare_router_data()
++ ri = l3_agent.RouterInfo(router['id'], self.conf.root_helper,
++ self.conf.use_namespaces, router=router)
++ agent.external_gateway_added = mock.Mock()
++ # Process with NAT
++ agent.process_router(ri)
++ orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
++ # Add an IPv4 and IPv6 interface and reprocess
++ router[l3_constants.INTERFACE_KEY].append(
++ {'id': _uuid(),
++ 'network_id': _uuid(),
++ 'admin_state_up': True,
++ 'fixed_ips': [{'ip_address': '35.4.1.4',
++ 'subnet_id': _uuid()}],
++ 'mac_address': 'ca:fe:de:ad:be:ef',
++ 'subnet': {'cidr': '35.4.1.0/24',
++ 'gateway_ip': '35.4.1.1'}})
++
++ router[l3_constants.INTERFACE_KEY].append(
++ {'id': _uuid(),
++ 'network_id': _uuid(),
++ 'admin_state_up': True,
++ 'fixed_ips': [{'ip_address': 'fd00::2',
++ 'subnet_id': _uuid()}],
++ 'mac_address': 'ca:fe:de:ad:be:ef',
++ 'subnet': {'cidr': 'fd00::/64',
++ 'gateway_ip': 'fd00::1'}})
++ # Reassign the router object to RouterInfo
++ ri.router = router
++ agent.process_router(ri)
++ # For some reason set logic does not work well with
++ # IpTablesRule instances
++ nat_rules_delta = [r for r in ri.iptables_manager.ipv4['nat'].rules
++ if r not in orig_nat_rules]
++ self.assertEqual(1, len(nat_rules_delta))
++ self._verify_snat_rules(nat_rules_delta, router)
++
+ def test_process_router_interface_removed(self):
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ router = self._prepare_router_data(num_internal_ports=2)
diff --git a/openstack-neutron.spec b/openstack-neutron.spec
index 8979131..e5a64f9 100644
--- a/openstack-neutron.spec
+++ b/openstack-neutron.spec
@@ -2,7 +2,7 @@
Name: openstack-neutron
Version: 2013.2.3
-Release: 8%{?dist}
+Release: 9%{?dist}
Provides: openstack-quantum = %{version}-%{release}
Obsoletes: openstack-quantum < 2013.2-0.4.b3
Summary: OpenStack Networking Service
@@ -41,6 +41,7 @@ Patch0002: 0002-Removed-signing_dir-from-neutron.conf.patch
Patch0003: 0003-Validate-CIDR-given-as-ip-prefix-in-security-group-r.patch
Patch0004: 0004-netaddr-0.7.10-raises-ValueError-instead-of-AddrForm.patch
Patch0005: 0005-Ensure-routing-key-is-specified-in-the-address-for-a.patch
+Patch0006: 0006-Install-SNAT-rules-for-ipv4-only.patch
BuildArch: noarch
@@ -401,6 +402,7 @@ IPSec.
%patch0003 -p1
%patch0004 -p1
%patch0005 -p1
+%patch0006 -p1
find neutron -name \*.py -exec sed -i '/\/usr\/bin\/env python/{d;q}' {} +
@@ -929,6 +931,9 @@ fi
%changelog
+* Tue Jun 17 2014 Ihar Hrachyshka <ihrachys at redhat.com> 2013.2.3-9
+- Install SNAT rules for ipv4 only, bz#1110142
+
* Wed Jun 11 2014 Ihar Hrachyshka <ihrachys at redhat.com> 2013.2.3-8
- Ensure routing key is specified in the address for a direct producer, bz#1108025
More information about the scm-commits
mailing list