summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2023-03-20 10:49:39 +0000
committerGerrit Code Review <review@openstack.org>2023-03-20 10:49:39 +0000
commit67b4ff3850c90bc73f5536f8a14d803144bbb700 (patch)
treec29b64ece83b0844ef48aafbae661631d24ab02c
parent6a69019fb5bed6ac490a64d4f5357e7a68c3975c (diff)
parent138a47bfd62252ddea8ff7ccdedff265e99cfb0e (diff)
downloadneutron-67b4ff3850c90bc73f5536f8a14d803144bbb700.tar.gz
Merge "[OVS] Allow custom ethertype traffic in the ingress table" into stable/zed
-rw-r--r--doc/source/admin/config-ovsfwdriver.rst10
-rw-r--r--neutron/agent/linux/openvswitch_firewall/firewall.py19
-rw-r--r--neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py22
3 files changed, 51 insertions, 0 deletions
diff --git a/doc/source/admin/config-ovsfwdriver.rst b/doc/source/admin/config-ovsfwdriver.rst
index 594a5e8536..59af75d03c 100644
--- a/doc/source/admin/config-ovsfwdriver.rst
+++ b/doc/source/admin/config-ovsfwdriver.rst
@@ -168,6 +168,16 @@ the default ``_constants.AGENT_RES_PROCESSING_STEP``:
# (6) Check the OVS agent restart time, checking the "iteration" time and
# number.
+Permitted ethertypes
+~~~~~~~~~~~~~~~~~~~~
+
+The OVS Firewall blocks traffic that does not have either the IPv4 or IPv6
+ethertypes at present. This is a behavior change compared to the
+"iptables_hybrid" firewall, which only operates on IP packets and thus does
+not address other ethertypes. With the configuration option
+``permitted_ethertypes`` it is possible to define a set of allowed ethertypes.
+Any traffic with these allowed ethertypes with destination to a local port or
+generated from a local port and MAC address, will be allowed.
References
~~~~~~~~~~
diff --git a/neutron/agent/linux/openvswitch_firewall/firewall.py b/neutron/agent/linux/openvswitch_firewall/firewall.py
index 3f24dab9ce..a08d4fa24a 100644
--- a/neutron/agent/linux/openvswitch_firewall/firewall.py
+++ b/neutron/agent/linux/openvswitch_firewall/firewall.py
@@ -1388,6 +1388,25 @@ class OVSFirewallDriver(firewall.FirewallDriver):
actions='output:{:d}'.format(port.ofport)
)
+ # Allow custom ethertypes
+ for permitted_ethertype in self.permitted_ethertypes:
+ if permitted_ethertype[:2] == '0x':
+ try:
+ hex_ethertype = hex(int(permitted_ethertype, base=16))
+ self._add_flow(
+ table=ovs_consts.BASE_INGRESS_TABLE,
+ priority=100,
+ dl_type=hex_ethertype,
+ reg_port=port.ofport,
+ actions='output:{:d}'.format(port.ofport)
+ )
+ continue
+ except ValueError:
+ pass
+ LOG.warning('Custom ethertype %(permitted_ethertype)s is not '
+ 'a hexadecimal number.',
+ {'permitted_ethertype': permitted_ethertype})
+
self._initialize_ingress_ipv6_icmp(port)
# DHCP offers
diff --git a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py
index abc3942e49..8eee3a4bf3 100644
--- a/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py
+++ b/neutron/tests/unit/agent/linux/openvswitch_firewall/test_firewall.py
@@ -31,6 +31,7 @@ from neutron.agent.linux.openvswitch_firewall import constants as ovsfw_consts
from neutron.agent.linux.openvswitch_firewall import exceptions
from neutron.agent.linux.openvswitch_firewall import firewall as ovsfw
from neutron.conf.agent import securitygroups_rpc
+from neutron.conf.plugins.ml2.drivers import ovs_conf
from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \
import ovs_bridge
from neutron.tests import base
@@ -518,6 +519,7 @@ class FakeOVSPort(object):
class TestOVSFirewallDriver(base.BaseTestCase):
def setUp(self):
super(TestOVSFirewallDriver, self).setUp()
+ ovs_conf.register_ovs_agent_opts(cfg=cfg.CONF)
mock_bridge = mock.patch.object(
ovs_lib, 'OVSBridge', autospec=True).start()
securitygroups_rpc.register_securitygroups_opts()
@@ -844,6 +846,26 @@ class TestOVSFirewallDriver(base.BaseTestCase):
return_value={"vlan1": "br-vlan1"}):
self.firewall.initialize_port_flows(port)
+ def test_initialize_port_flows_permitted_ethertypes(self):
+ self.firewall.permitted_ethertypes = ['0x1234', '0x5678']
+ port_dict = {'device': 'port-id',
+ 'security_groups': [1]}
+ of_port = create_ofport(port_dict,
+ network_type=constants.TYPE_VLAN,
+ physical_network='vlan1')
+ self.firewall.sg_port_map.ports[of_port.id] = of_port
+ port = self.firewall.get_or_create_ofport(port_dict)
+ with mock.patch.object(self.firewall, '_add_flow') as mock_add_flow:
+ self.firewall.initialize_port_flows(port)
+
+ calls = [mock.call(table=ovs_consts.BASE_INGRESS_TABLE,
+ priority=100, dl_type='0x1234',
+ reg_port=1, actions='output:1'),
+ mock.call(table=ovs_consts.BASE_INGRESS_TABLE,
+ priority=100, dl_type='0x5678',
+ reg_port=1, actions='output:1')]
+ mock_add_flow.assert_has_calls(calls, any_order=True)
+
def test_delete_all_port_flows(self):
port_dict = {
'device': 'port-id',