
Without a static entry in the FDB the MAC address we use both for the internal port of the bridge and the bgp-router LRP is re-learned using the normal Ethernet switch FDB learning logic: whenever the guest traffic is sent out via the bgp-router LR, the port is set to the patch port leading to br-bgp. Sending traffic from the internal port then rewrites that back. Until then the traffic destined to the internal port is being sent to br-bgp which results in flow table misses and drop flows being cached. Adding a static entry to the FDB effectively disables learning based on the traffic coming out of the patch port leading to br-bgp. Closes-Bug: #2089297 Change-Id: I8563adb49db8fa94c51f9ba47275e8c7812997ea
113 lines
4.3 KiB
Python
113 lines
4.3 KiB
Python
# Copyright 2022 Red Hat, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import importlib
|
|
from unittest import mock
|
|
|
|
from oslo_concurrency import processutils
|
|
|
|
from ovn_bgp_agent.privileged import ovs_vsctl
|
|
from ovn_bgp_agent.tests import base as test_base
|
|
|
|
# Mock the privsep decorator and reload the module
|
|
mock.patch('ovn_bgp_agent.privileged.ovs_vsctl_cmd.entrypoint',
|
|
lambda x: x).start()
|
|
importlib.reload(ovs_vsctl)
|
|
|
|
|
|
class FakeException(Exception):
|
|
stderr = ''
|
|
|
|
|
|
class TestPrivilegedOvsVsctl(test_base.TestCase):
|
|
|
|
def setUp(self):
|
|
super(TestPrivilegedOvsVsctl, self).setUp()
|
|
# Mock processutils.execute()
|
|
self.mock_exc = mock.patch.object(processutils, 'execute').start()
|
|
|
|
def test_ovs_vsctl(self):
|
|
ovs_vsctl.ovs_vsctl(
|
|
['--if-exists', 'del-port', 'fake-port'])
|
|
self.mock_exc.assert_called_once_with(
|
|
'ovs-vsctl', '--if-exists', 'del-port', 'fake-port')
|
|
|
|
def test_ovs_ofctl(self):
|
|
ovs_vsctl.ovs_ofctl(
|
|
['dump-flows', 'dummy-br'])
|
|
self.mock_exc.assert_called_once_with(
|
|
'ovs-ofctl', 'dump-flows', 'dummy-br')
|
|
|
|
def test_ovs_vsctl_timeout(self):
|
|
ovs_vsctl.ovs_vsctl(
|
|
['--if-exists', 'del-port', 'fake-port'], timeout=10)
|
|
self.mock_exc.assert_called_once_with(
|
|
'ovs-vsctl', '--timeout=10', '--if-exists', 'del-port',
|
|
'fake-port')
|
|
|
|
def test_ovs_ofctl_timeout(self):
|
|
ovs_vsctl.ovs_ofctl(
|
|
['dump-flows', 'dummy-br'], timeout=10)
|
|
self.mock_exc.assert_called_once_with(
|
|
'ovs-ofctl', '--timeout=10', 'dump-flows', 'dummy-br')
|
|
|
|
def test_ovs_ofctl_fallback_OF_version(self):
|
|
# fallback only applies to ovs-ofctl command
|
|
self.mock_exc.side_effect = (
|
|
processutils.ProcessExecutionError(), None)
|
|
ovs_vsctl.ovs_ofctl(
|
|
['--strict', 'del-flows', 'br-ex', 'dummy-flow'])
|
|
|
|
calls = [mock.call('ovs-ofctl', '--strict', 'del-flows',
|
|
'br-ex', 'dummy-flow'),
|
|
mock.call('ovs-ofctl', '--strict', 'del-flows',
|
|
'br-ex', 'dummy-flow', '-O', 'OpenFlow13')]
|
|
self.mock_exc.assert_has_calls(calls)
|
|
|
|
def test_ovs_vsctl_process_execution_error_no_fallback(self):
|
|
# fallback does not apply to ovs-vsctl command
|
|
self.mock_exc.side_effect = processutils.ProcessExecutionError()
|
|
self.assertRaises(
|
|
processutils.ProcessExecutionError, ovs_vsctl.ovs_vsctl,
|
|
['--if-exists', 'del-port', 'fake-port'])
|
|
self.mock_exc.assert_called_once_with(
|
|
'ovs-vsctl', '--if-exists', 'del-port', 'fake-port')
|
|
|
|
def test_ovs_ofctl_exception(self):
|
|
self.mock_exc.side_effect = FakeException()
|
|
self.assertRaises(
|
|
FakeException, ovs_vsctl.ovs_ofctl,
|
|
['add-flow', 'br-ex', 'dummy-flow'])
|
|
self.mock_exc.assert_called_once_with(
|
|
'ovs-ofctl', 'add-flow', 'br-ex', 'dummy-flow')
|
|
|
|
def test_ovs_cmd_fallback_exception(self):
|
|
self.mock_exc.side_effect = (
|
|
processutils.ProcessExecutionError(), FakeException())
|
|
self.assertRaises(
|
|
FakeException, ovs_vsctl.ovs_ofctl,
|
|
['add-flow', 'br-ex', 'dummy-flow'])
|
|
calls = [mock.call('ovs-ofctl', 'add-flow', 'br-ex', 'dummy-flow'),
|
|
mock.call('ovs-ofctl', 'add-flow', 'br-ex', 'dummy-flow',
|
|
'-O', 'OpenFlow13')]
|
|
self.mock_exc.assert_has_calls(calls)
|
|
|
|
def test_ovs_appctl(self):
|
|
ovs_vsctl.ovs_appctl(
|
|
['fdb/add', 'br-fabric', 'br-fabric', '0', 'de:ad:be:ef:ca:fe'])
|
|
self.mock_exc.assert_called_once_with(
|
|
'ovs-appctl', 'fdb/add', 'br-fabric', 'br-fabric',
|
|
'0', 'de:ad:be:ef:ca:fe')
|