[OVS] Allow custom ethertype traffic in the ingress table
This patch is a partial revert of [1], reinstantiating the code merged in [2]. This patch is the complementary to [1]: the traffic with custom ethertypes is allowed in the ingress processing tables, same as [1] is allowing all traffic from the virtual machine ports in this host to leave the node. Both, this patch and [1], are bypassing the OVS firewall just for the traffic with the configured allowed ethertypes and just for/to the local ports and MAC addresses. Any other traffic not coming from a local port or with destination a local port, will be blocked as is now. [1]https://review.opendev.org/c/openstack/neutron/+/678021 [2]https://review.opendev.org/c/openstack/neutron/+/668224/ Closes-Bug: #2009221 Related-Bug: #1832758 Change-Id: Ib8340d9430b946a446edf80886c49fbac729073c
This commit is contained in:
parent
962b4f9bb9
commit
008277b8c1
@ -175,6 +175,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
|
||||
~~~~~~~~~~
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
Loading…
x
Reference in New Issue
Block a user