]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Add support for unaddressed port
authorYalei Wang <yalei.wang@intel.com>
Fri, 7 Aug 2015 14:43:30 +0000 (22:43 +0800)
committerYalei Wang <yalei.wang@intel.com>
Thu, 20 Aug 2015 13:34:50 +0000 (21:34 +0800)
Neutron could create a port without the IP address when the network doesn't
have a subnet. In this case, neutron will have no L3 knowledgee and we need
remove the L3 filter on it but reserve the L2 filter if there is.
This patch will make L2 agent verify the fixed_ips before converting the
security-group-rules into firewall rules, L3 rules in it will be removed.
And filter like arp-spoofing will be disabled for this port.

Partially Implements: blueprint vm-without-l3-address
Change-Id: I5cd1fdfa13a7e57258be7251768eaa8ba64d486e

neutron/agent/linux/iptables_firewall.py
neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py
neutron/tests/unit/agent/linux/test_iptables_firewall.py
neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py

index a080e6ef20e9992807a9d145be78cc3a9ddd4a27..6b6ffe1f190fc93b6fc044bdc3e441202ac9ec39 100644 (file)
@@ -45,6 +45,13 @@ LINUX_DEV_LEN = 14
 comment_rule = iptables_manager.comment_rule
 
 
+def port_needs_l3_security(port):
+    if port['fixed_ips'] or port.get('allowed_address_pairs'):
+        return True
+    else:
+        return False
+
+
 class IptablesFirewallDriver(firewall.FirewallDriver):
     """Driver which enforces security groups through iptables rules."""
     IPTABLES_DIRECTION = {firewall.INGRESS_DIRECTION: 'physdev-out',
@@ -367,17 +374,20 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
             mac_ipv6_pairs.append((mac, ip_address))
 
     def _spoofing_rule(self, port, ipv4_rules, ipv6_rules):
-        # Allow dhcp client packets
-        ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 '
-                                    '-j RETURN', comment=ic.DHCP_CLIENT)]
-        # Drop Router Advts from the port.
-        ipv6_rules += [comment_rule('-p icmpv6 --icmpv6-type %s '
-                                    '-j DROP' % constants.ICMPV6_TYPE_RA,
-                                    comment=ic.IPV6_RA_DROP)]
-        ipv6_rules += [comment_rule('-p icmpv6 -j RETURN',
-                                    comment=ic.IPV6_ICMP_ALLOW)]
-        ipv6_rules += [comment_rule('-p udp -m udp --sport 546 --dport 547 '
-                                    '-j RETURN', comment=ic.DHCP_CLIENT)]
+        if port_needs_l3_security(port):
+            # Allow dhcp client packets
+            ipv4_rules += [comment_rule('-p udp -m udp --sport 68 --dport 67 '
+                                        '-j RETURN', comment=ic.DHCP_CLIENT)]
+            # Drop Router Advts from the port.
+            ipv6_rules += [comment_rule('-p icmpv6 --icmpv6-type %s '
+                                        '-j DROP' % constants.ICMPV6_TYPE_RA,
+                                        comment=ic.IPV6_RA_DROP)]
+            ipv6_rules += [comment_rule('-p icmpv6 -j RETURN',
+                                        comment=ic.IPV6_ICMP_ALLOW)]
+            ipv6_rules += [comment_rule('-p udp -m udp --sport 546 --dport '
+                                        '547 -j RETURN',
+                                        comment=ic.DHCP_CLIENT)]
+
         mac_ipv4_pairs = []
         mac_ipv6_pairs = []
 
@@ -483,11 +493,14 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
                                          ipv6_iptables_rules)
         elif direction == firewall.INGRESS_DIRECTION:
             ipv6_iptables_rules += self._accept_inbound_icmpv6()
-        # include IPv4 and IPv6 iptable rules from security group
-        ipv4_iptables_rules += self._convert_sgr_to_iptables_rules(
-            ipv4_sg_rules)
-        ipv6_iptables_rules += self._convert_sgr_to_iptables_rules(
-            ipv6_sg_rules)
+
+        if port_needs_l3_security(port):
+            # include IPv4 and IPv6 iptable rules from security group
+            ipv4_iptables_rules += self._convert_sgr_to_iptables_rules(
+                ipv4_sg_rules)
+            ipv6_iptables_rules += self._convert_sgr_to_iptables_rules(
+                ipv6_sg_rules)
+
         # finally add the rules to the port chain for a given direction
         self._add_rules_to_chain_v4v6(self._port_chain_name(port, direction),
                                       ipv4_iptables_rules,
@@ -498,7 +511,8 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
         self._spoofing_rule(port,
                             ipv4_iptables_rules,
                             ipv6_iptables_rules)
-        self._drop_dhcp_rule(ipv4_iptables_rules, ipv6_iptables_rules)
+        if port_needs_l3_security(port):
+            self._drop_dhcp_rule(ipv4_iptables_rules, ipv6_iptables_rules)
 
     def _update_ipset_members(self, security_group_ids):
         for ip_version, sg_ids in security_group_ids.items():
index 28d4735a6af5cb937fa4c4cfcde976c679bc1d52..ea5ac9c2b7f2795672f12315a529e5c979c2d909 100644 (file)
@@ -30,6 +30,7 @@ from neutron.agent.common import ovs_lib
 from neutron.agent.common import polling
 from neutron.agent.common import utils
 from neutron.agent.linux import ip_lib
+from neutron.agent.linux.iptables_firewall import port_needs_l3_security
 from neutron.agent import rpc as agent_rpc
 from neutron.agent import securitygroups_rpc as sg_rpc
 from neutron.api.rpc.handlers import dvr_rpc
@@ -807,6 +808,9 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
             addresses |= {p['ip_address']
                           for p in port_details['allowed_address_pairs']}
 
+        if not port_needs_l3_security(port_details):
+            return
+
         addresses = {ip for ip in addresses
                      if netaddr.IPNetwork(ip).version == 4}
         if any(netaddr.IPNetwork(ip).prefixlen == 0 for ip in addresses):
index 3f878ecb14dd71fde56d921b8f3c318ea2d07392..dd458029c8b2db09166aa2cc8c56f586ec70a556 100644 (file)
@@ -1453,15 +1453,6 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
                                     '--physdev-is-bridged '
                                     '-j $ifake_dev',
                                     comment=ic.SG_TO_VM_SG),
-                 mock.call.add_rule(
-                     'ifake_dev',
-                     '-m state --state INVALID -j DROP', comment=None),
-                 mock.call.add_rule(
-                     'ifake_dev',
-                     '-m state --state RELATED,ESTABLISHED -j RETURN',
-                     comment=None),
-                 mock.call.add_rule('ifake_dev', '-j $sg-fallback',
-                                    comment=None),
                  mock.call.add_chain('ofake_dev'),
                  mock.call.add_rule('FORWARD',
                                     '-m physdev --physdev-in tapfake_dev '
@@ -1483,26 +1474,8 @@ class IptablesFirewallTestCase(BaseIptablesFirewallTestCase):
                  mock.call.add_rule(
                      'sfake_dev', '-j DROP',
                      comment=ic.PAIR_DROP),
-                 mock.call.add_rule(
-                     'ofake_dev',
-                     '-p udp -m udp --sport 68 --dport 67 -j RETURN',
-                     comment=None),
                  mock.call.add_rule('ofake_dev', '-j $sfake_dev',
                                     comment=None),
-                 mock.call.add_rule(
-                     'ofake_dev',
-                     '-p udp -m udp --sport 67 --dport 68 -j DROP',
-                     comment=None),
-                 mock.call.add_rule(
-                     'ofake_dev',
-                     '-m state --state INVALID -j DROP',
-                     comment=None),
-                 mock.call.add_rule(
-                     'ofake_dev',
-                     '-m state --state RELATED,ESTABLISHED -j RETURN',
-                     comment=None),
-                 mock.call.add_rule('ofake_dev', '-j $sg-fallback',
-                                    comment=None),
                  mock.call.add_rule('sg-chain', '-j ACCEPT')]
         self.v4filter_inst.assert_has_calls(calls)
 
index 527f8ab39d90b1379829985bbfbe1c1b8affc0ec..eae21aa23f46b21a6340952823c3282896d7ec9d 100644 (file)
@@ -1102,7 +1102,7 @@ class TestOvsNeutronAgent(object):
         self.assertTrue(int_br.delete_arp_spoofing_protection.called)
         self.assertFalse(int_br.install_arp_spoofing_protection.called)
 
-    def test_arp_spoofing_basic_rule_setup(self):
+    def test_arp_spoofing_basic_rule_setup_without_ip(self):
         vif = FakeVif()
         fake_details = {'fixed_ips': []}
         self.agent.prevent_arp_spoofing = True
@@ -1111,9 +1111,18 @@ class TestOvsNeutronAgent(object):
         self.assertEqual(
             [mock.call(port=vif.ofport)],
             int_br.delete_arp_spoofing_protection.mock_calls)
+        self.assertFalse(int_br.install_arp_spoofing_protection.called)
+
+    def test_arp_spoofing_basic_rule_setup_fixed_ip(self):
+        vif = FakeVif()
+        fake_details = {'fixed_ips': [{'ip_address': '192.168.44.100'}]}
+        self.agent.prevent_arp_spoofing = True
+        int_br = mock.create_autospec(self.agent.int_br)
+        self.agent.setup_arp_spoofing_protection(int_br, vif, fake_details)
         self.assertEqual(
-            [mock.call(ip_addresses=set(), port=vif.ofport)],
-            int_br.install_arp_spoofing_protection.mock_calls)
+            [mock.call(port=vif.ofport)],
+            int_br.delete_arp_spoofing_protection.mock_calls)
+        self.assertTrue(int_br.install_arp_spoofing_protection.called)
 
     def test_arp_spoofing_fixed_and_allowed_addresses(self):
         vif = FakeVif()