Strictly delete arp_spoofing_protection flows

Port arp_spoofing_protection will install flows like this:
table=0, priority=9,in_port=2 actions=goto_table:25
table=25, priority=2,in_port=2,dl_src=fa:16:3e:54:f0:71 actions=goto_table:60

For network ports or port_security_enabled = False, those flows
will be delete by setup_arp_spoofing_protection in _bind_devices.

But the delete actions are a bit rough because it will delete any
flows with "table=0 in_port=2" and "table=25 in_port=2".

Besides, the ovs_agent extension handle_port will be run before
these actions [5]. So network or no security ports, if any flows
added by agent extesnion in table=0 with "in_port=2" will be delete
unexpectedly. Which also means any flows added before this call of
"uninstall_flows(table=0, in_port=2)" will be deleted.

This patch changes the uninstall flows to strict mode. Let it
delete the arp_spoofing_protection related flows only by verifying
the priority.

Closes-Bug: #2000046
Change-Id: Ifdd47b2ce8610e4b4b527fc3279e0bd7a8b21a1d
This commit is contained in:
LIU Yulong 2022-12-19 14:26:47 +08:00
parent faa4803302
commit dad23fdcdb
2 changed files with 62 additions and 2 deletions

View File

@ -384,9 +384,11 @@ class OVSIntegrationBridge(ovs_bridge.OVSAgentBridge,
allow_all=False):
if allow_all:
self.uninstall_flows(table_id=constants.LOCAL_SWITCHING,
in_port=port)
in_port=port,
strict=True, priority=9)
self.uninstall_flows(table_id=constants.MAC_SPOOF_TABLE,
in_port=port)
in_port=port,
strict=True, priority=2)
return
mac_addresses = mac_addresses or []
for address in mac_addresses:

View File

@ -630,6 +630,64 @@ class OVSIntegrationBridgeTest(ovs_bridge_test_base.OVSBridgeTestBase):
]
self.assertEqual(expected, self.mock.mock_calls)
def _test_set_allowed_macs_for_port(self, port, mac_addresses,
allow_all=False):
mock_dump_flows = mock.patch.object(self.br, 'dump_flows').start()
mock_dump_flows.return_value = []
self.br.set_allowed_macs_for_port(port, mac_addresses, allow_all)
(dp, ofp, ofpp) = self._get_dp()
expected = []
if allow_all:
expected += [
call.uninstall_flows(
table_id=ovs_constants.LOCAL_SWITCHING,
in_port=port, strict=True, priority=9),
call.uninstall_flows(
table_id=ovs_constants.MAC_SPOOF_TABLE,
in_port=port, strict=True, priority=2),
]
self.assertEqual(expected, self.mock.mock_calls)
return
mac_addresses = mac_addresses or []
for address in mac_addresses:
expected.append(
call._send_msg(ofpp.OFPFlowMod(dp,
cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(
table_id=ovs_constants.LOCAL_EGRESS_TABLE),
],
match=ofpp.OFPMatch(
eth_src=address,
in_port=port,
),
priority=2,
table_id=ovs_constants.MAC_SPOOF_TABLE),
active_bundle=None))
expected.append(
call._send_msg(ofpp.OFPFlowMod(dp,
cookie=self.stamp,
instructions=[
ofpp.OFPInstructionGotoTable(
table_id=ovs_constants.MAC_SPOOF_TABLE),
],
match=ofpp.OFPMatch(
in_port=port,
),
priority=9,
table_id=ovs_constants.LOCAL_SWITCHING),
active_bundle=None))
self.assertEqual(expected, self.mock.mock_calls)
def test_set_allowed_macs_for_port(self):
self._test_set_allowed_macs_for_port(1, ["11:22:33:44:55:66"])
def test_set_allowed_macs_for_port_allow_all(self):
self._test_set_allowed_macs_for_port(None, None, allow_all=True)
def _test_delete_dvr_dst_mac_for_arp(self, network_type):
if network_type in (p_const.TYPE_VLAN, p_const.TYPE_FLAT):
table_id = ovs_constants.DVR_TO_SRC_MAC_PHYSICAL