ovs-fw: Handle only known trusted ports

Similarly to filtered ports this patch caches so called trusted ports to
avoid processing in case of unknown port is passed down to firewall
driver. The cached ofport is used for removal as the cache reflects
currently installed flows.

The patch also catches exception caused by inconsistency coming from
ovsdb.

Closes-bug: #1707339

Change-Id: I15cdb28072835fcb8c37ae4b56fc8754375a807c
This commit is contained in:
Jakub Libosvar 2017-08-01 17:04:30 +00:00 committed by Ihar Hrachyshka
parent 927edca4fd
commit 1d80c960f6
2 changed files with 37 additions and 8 deletions

View File

@ -145,6 +145,8 @@ class SGPortMap(object):
def __init__(self):
self.ports = {}
self.sec_groups = {}
# Maps port_id to ofport number
self.unfiltered = {}
def get_sg(self, sg_id):
return self.sec_groups.get(sg_id, None)
@ -615,12 +617,19 @@ class OVSFirewallDriver(firewall.FirewallDriver):
)
def _initialize_egress_no_port_security(self, port_id):
ovs_port = self.get_ovs_port(port_id)
try:
ovs_port = self.get_ovs_port(port_id)
vlan_tag = self._get_port_vlan_tag(ovs_port.port_name)
except exceptions.OVSFWTagNotFound:
# It's a patch port, don't set anything
return
except exceptions.OVSFWPortNotFound as not_found_e:
LOG.error("Initializing unfiltered port %(port_id)s that does not "
"exist in ovsdb: %(err)s.",
{'port_id': port_id,
'err': not_found_e})
return
self.sg_port_map.unfiltered[port_id] = ovs_port.ofport
self._add_flow(
table=ovs_consts.TRANSIENT_TABLE,
priority=100,
@ -642,21 +651,20 @@ class OVSFirewallDriver(firewall.FirewallDriver):
)
def _remove_egress_no_port_security(self, port_id):
ovs_port = self.get_ovs_port(port_id)
try:
# Test if it's a patch port
self._get_port_vlan_tag(ovs_port.port_name)
except exceptions.OVSFWTagNotFound:
# It's a patch port, don't do anything
ofport = self.sg_port_map.unfiltered[port_id]
except KeyError:
LOG.debug("Port %s is not handled by the firewall.", port_id)
return
self._delete_flows(
table=ovs_consts.TRANSIENT_TABLE,
in_port=ovs_port.ofport
in_port=ofport
)
self._delete_flows(
table=ovs_consts.ACCEPT_OR_INGRESS_TABLE,
reg_port=ovs_port.ofport
reg_port=ofport
)
del self.sg_port_map.unfiltered[port_id]
def _initialize_egress(self, port):
"""Identify egress traffic and send it to egress base"""

View File

@ -639,6 +639,7 @@ class TestOVSFirewallDriver(base.BaseTestCase):
def test__remove_egress_no_port_security_deletes_flow(self):
self.mock_bridge.br.db_get_val.return_value = {'tag': TESTING_VLAN_TAG}
self.firewall.sg_port_map.unfiltered['port_id'] = 1
self.firewall._remove_egress_no_port_security('port_id')
expected_call = mock.call(
table=ovs_consts.TRANSIENT_TABLE,
@ -651,3 +652,23 @@ class TestOVSFirewallDriver(base.BaseTestCase):
self.mock_bridge.br.db_get_val.return_value = {}
self.firewall._remove_egress_no_port_security('port_id')
self.assertFalse(self.mock_bridge.br.delete_flows.called)
def test_process_trusted_ports_caches_port_id(self):
self.firewall.process_trusted_ports(['port_id'])
self.assertIn('port_id', self.firewall.sg_port_map.unfiltered)
def test_process_trusted_ports_port_not_found(self):
"""Check that exception is not propagated outside."""
self.mock_bridge.br.get_vif_port_by_id.return_value = None
self.firewall.process_trusted_ports(['port_id'])
# Processing should have failed so port is not cached
self.assertNotIn('port_id', self.firewall.sg_port_map.unfiltered)
def test_remove_trusted_ports_clears_cached_port_id(self):
self.firewall.sg_port_map.unfiltered['port_id'] = 1
self.firewall.remove_trusted_ports(['port_id'])
self.assertNotIn('port_id', self.firewall.sg_port_map.unfiltered)
def test_remove_trusted_ports_not_managed_port(self):
"""Check that exception is not propagated outside."""
self.firewall.remove_trusted_ports(['port_id'])