Merge "[OVS] Allow custom ethertype traffic in the ingress table" into stable/yoga
This commit is contained in:
commit
55880650e8
|
@ -88,6 +88,18 @@ not true and there may be slight differences between those drivers.
|
||||||
| (please check [3]_ for details) | | rule. |
|
| (please check [3]_ for details) | | rule. |
|
||||||
+----------------------------------------+-----------------------+-----------------------+
|
+----------------------------------------+-----------------------+-----------------------+
|
||||||
|
|
||||||
|
|
||||||
|
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
|
References
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -1371,6 +1371,25 @@ class OVSFirewallDriver(firewall.FirewallDriver):
|
||||||
actions='output:{:d}'.format(port.ofport)
|
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)
|
self._initialize_ingress_ipv6_icmp(port)
|
||||||
|
|
||||||
# DHCP offers
|
# DHCP offers
|
||||||
|
|
|
@ -30,6 +30,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 exceptions
|
||||||
from neutron.agent.linux.openvswitch_firewall import firewall as ovsfw
|
from neutron.agent.linux.openvswitch_firewall import firewall as ovsfw
|
||||||
from neutron.conf.agent import securitygroups_rpc
|
from neutron.conf.agent import securitygroups_rpc
|
||||||
|
from neutron.conf.plugins.ml2.drivers import ovs_conf
|
||||||
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \
|
from neutron.plugins.ml2.drivers.openvswitch.agent.common import constants \
|
||||||
as ovs_consts
|
as ovs_consts
|
||||||
from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \
|
from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \
|
||||||
|
@ -514,6 +515,7 @@ class FakeOVSPort(object):
|
||||||
class TestOVSFirewallDriver(base.BaseTestCase):
|
class TestOVSFirewallDriver(base.BaseTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestOVSFirewallDriver, self).setUp()
|
super(TestOVSFirewallDriver, self).setUp()
|
||||||
|
ovs_conf.register_ovs_agent_opts(cfg=cfg.CONF)
|
||||||
mock_bridge = mock.patch.object(
|
mock_bridge = mock.patch.object(
|
||||||
ovs_lib, 'OVSBridge', autospec=True).start()
|
ovs_lib, 'OVSBridge', autospec=True).start()
|
||||||
securitygroups_rpc.register_securitygroups_opts()
|
securitygroups_rpc.register_securitygroups_opts()
|
||||||
|
@ -840,6 +842,26 @@ class TestOVSFirewallDriver(base.BaseTestCase):
|
||||||
return_value={"vlan1": "br-vlan1"}):
|
return_value={"vlan1": "br-vlan1"}):
|
||||||
self.firewall.initialize_port_flows(port)
|
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):
|
def test_delete_all_port_flows(self):
|
||||||
port_dict = {
|
port_dict = {
|
||||||
'device': 'port-id',
|
'device': 'port-id',
|
||||||
|
|
Loading…
Reference in New Issue