diff --git a/config.yaml b/config.yaml index a8346f4b..a42fe5a1 100644 --- a/config.yaml +++ b/config.yaml @@ -111,3 +111,12 @@ options: which do not include a neutron-gateway (do not require l3, lbaas or vpnaas services) and should only be used in-conjunction with flat or VLAN provider networks configurations. + prevent-arp-spoofing: + type: boolean + default: true + description: | + Enable suppression of ARP responses that don't match an IP address that belongs + to the port from which they originate. + . + Only supported in OpenStack Liberty or newer, which as the required minimum version + of Open vSwitch. diff --git a/hooks/neutron_ovs_context.py b/hooks/neutron_ovs_context.py index 1ba8a84a..f2b0a7cc 100644 --- a/hooks/neutron_ovs_context.py +++ b/hooks/neutron_ovs_context.py @@ -58,6 +58,7 @@ class OVSPluginContext(context.NeutronContext): ovs_ctxt['use_syslog'] = conf['use-syslog'] ovs_ctxt['verbose'] = conf['verbose'] ovs_ctxt['debug'] = conf['debug'] + ovs_ctxt['prevent_arp_spoofing'] = conf['prevent-arp-spoofing'] net_dev_mtu = neutron_api_settings.get('network_device_mtu') if net_dev_mtu: diff --git a/templates/liberty/ml2_conf.ini b/templates/liberty/ml2_conf.ini index 32d2d8a4..08d52fad 100644 --- a/templates/liberty/ml2_conf.ini +++ b/templates/liberty/ml2_conf.ini @@ -30,12 +30,10 @@ bridge_mappings = {{ bridge_mappings }} tunnel_types = {{ overlay_network_type }} l2_population = {{ l2_population }} enable_distributed_routing = {{ distributed_routing }} +prevent_arp_spoofing = {{ prevent_arp_spoofing }} {% if veth_mtu -%} veth_mtu = {{ veth_mtu }} {% endif -%} -{% if not neutron_security_groups -%} -prevent_arp_spoofing = False -{% endif %} [securitygroup] {% if neutron_security_groups -%} diff --git a/unit_tests/test_neutron_ovs_context.py b/unit_tests/test_neutron_ovs_context.py index 85692811..43755fe0 100644 --- a/unit_tests/test_neutron_ovs_context.py +++ b/unit_tests/test_neutron_ovs_context.py @@ -95,7 +95,8 @@ class OVSPluginContextTest(CharmTestCase): 'verbose': True, 'debug': True, 'bridge-mappings': "physnet1:br-data physnet2:br-data", - 'flat-network-providers': 'physnet3 physnet4'} + 'flat-network-providers': 'physnet3 physnet4', + 'prevent-arp-spoofing': False} def mock_config(key=None): if key: @@ -140,6 +141,7 @@ class OVSPluginContextTest(CharmTestCase): 'network_providers': 'physnet3,physnet4', 'bridge_mappings': 'physnet1:br-data,physnet2:br-data', 'vlan_ranges': 'physnet1:1000:1500,physnet2:2000:2500', + 'prevent_arp_spoofing': False, } self.assertEquals(expect, napi_ctxt()) @@ -204,6 +206,7 @@ class OVSPluginContextTest(CharmTestCase): 'overlay_network_type': 'gre', 'bridge_mappings': 'physnet1:br-data', 'vlan_ranges': 'physnet1:1000:2000', + 'prevent_arp_spoofing': True, } self.assertEquals(expect, napi_ctxt())