From 959c93f6d3572a189fc3fe73f1811c12323db857 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 10 Sep 2012 11:37:39 -0700 Subject: Fixes snat rules in complex networking configs There is currently no way to disable nova's snat rule, which causes problems for some network configurations with an external gateway. This patch allows the snat to be completely disabled by setting a blank value for routing_source_ip. This patch also makes the snat rule a little more specific, only snatting traffic that is destined for the public interface (or the floating interface if it is defined). This allows the snat to work without changing routing_source_ip and also ensures that an instance assigned multiple ips from different floating pools will connect from the appropriate address for each pool Fixes bug 1048765 Change-Id: I18be88a3dbb7a9f4762db7beefc94e07b8310100 --- nova/network/l3.py | 6 ++++-- nova/network/linux_net.py | 28 ++++++++++++++++------------ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/nova/network/l3.py b/nova/network/l3.py index e098c1e8f..e41e6312f 100644 --- a/nova/network/l3.py +++ b/nova/network/l3.py @@ -101,11 +101,13 @@ class LinuxNetL3(L3Driver): def add_floating_ip(self, floating_ip, fixed_ip, l3_interface_id): linux_net.bind_floating_ip(floating_ip, l3_interface_id) - linux_net.ensure_floating_forward(floating_ip, fixed_ip) + linux_net.ensure_floating_forward(floating_ip, fixed_ip, + l3_interface_id) def remove_floating_ip(self, floating_ip, fixed_ip, l3_interface_id): linux_net.unbind_floating_ip(floating_ip, l3_interface_id) - linux_net.remove_floating_forward(floating_ip, fixed_ip) + linux_net.remove_floating_forward(floating_ip, fixed_ip, + l3_interface_id) def add_vpn(self, public_ip, port, private_ip): linux_net.ensure_vpn_forward(public_ip, port, private_ip) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 207c15783..f991b3659 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -533,11 +533,13 @@ def metadata_accept(): def add_snat_rule(ip_range): - iptables_manager.ipv4['nat'].add_rule('snat', - '-s %s -j SNAT --to-source %s' % - (ip_range, - FLAGS.routing_source_ip)) - iptables_manager.apply() + if FLAGS.routing_source_ip: + rule = '-s %s -j SNAT --to-source %s' % (ip_range, + FLAGS.routing_source_ip) + if FLAGS.public_interface: + rule += ' -o %s' % FLAGS.public_interface + iptables_manager.ipv4['nat'].add_rule('snat', rule) + iptables_manager.apply() def init_host(ip_range=None): @@ -617,25 +619,27 @@ def ensure_vpn_forward(public_ip, port, private_ip): iptables_manager.apply() -def ensure_floating_forward(floating_ip, fixed_ip): +def ensure_floating_forward(floating_ip, fixed_ip, device): """Ensure floating ip forwarding rule.""" - for chain, rule in floating_forward_rules(floating_ip, fixed_ip): + for chain, rule in floating_forward_rules(floating_ip, fixed_ip, device): iptables_manager.ipv4['nat'].add_rule(chain, rule) iptables_manager.apply() -def remove_floating_forward(floating_ip, fixed_ip): +def remove_floating_forward(floating_ip, fixed_ip, device): """Remove forwarding for floating ip.""" - for chain, rule in floating_forward_rules(floating_ip, fixed_ip): + for chain, rule in floating_forward_rules(floating_ip, fixed_ip, device): iptables_manager.ipv4['nat'].remove_rule(chain, rule) iptables_manager.apply() -def floating_forward_rules(floating_ip, fixed_ip): +def floating_forward_rules(floating_ip, fixed_ip, device): + rule = '-s %s -j SNAT --to %s' % (fixed_ip, floating_ip) + if device: + rule += ' -o %s' % device return [('PREROUTING', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)), ('OUTPUT', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)), - ('float-snat', - '-s %s -j SNAT --to %s' % (fixed_ip, floating_ip))] + ('float-snat', rule)] def initialize_gateway_device(dev, network_ref): -- cgit