From b71ce99ff680d56779d4b702ab7c57e93ad6fd62 Mon Sep 17 00:00:00 2001 From: jayjahns Date: Fri, 7 Jun 2024 07:39:01 -0500 Subject: [PATCH] Announce lrp ip if advertisement method is subnet In the case of the subnet advertisement method, we do not announce the route to the tenant subnet via BGP. While the routes in br-ex are good, they do not fully expose the subnet. This change exposes the router interface that connects the tenant subnet. Closes-Bug: 2068730 Change-Id: Id7dd902e5e2010ba41052cc9316db8518349c755 (cherry picked from commit bc1dc8ec9ea2438fe89ad0d9535dfddd05c463d9) --- ovn_bgp_agent/drivers/openstack/utils/wire.py | 24 ++++++++ .../unit/drivers/openstack/utils/test_wire.py | 60 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/ovn_bgp_agent/drivers/openstack/utils/wire.py b/ovn_bgp_agent/drivers/openstack/utils/wire.py index 86f5fe09..38894aa8 100644 --- a/ovn_bgp_agent/drivers/openstack/utils/wire.py +++ b/ovn_bgp_agent/drivers/openstack/utils/wire.py @@ -790,6 +790,18 @@ def _wire_lrp_port_underlay(routing_tables_routes, ip, bridge_device, vlan=bridge_vlan, mask=ip.split("/")[1], via=cr_lrp_ip) + + if (CONF.advertisement_method_tenant_networks == + constants.ADVERTISEMENT_METHOD_SUBNET): + # NOTE(jayjahns): The route for the tenant subnet needs to be + # added to the bgp_nic in order to announce the network. + linux_net.add_ip_route( + routing_tables_routes, + ip.split("/")[0], + CONF.bgp_vrf_table_id, + CONF.bgp_nic, + mask=ip.split("/")[1], + via=cr_lrp_ip) break LOG.debug("Added IP Routes for network %s", ip) return True @@ -854,6 +866,18 @@ def _unwire_lrp_port_underlay(routing_tables_routes, ip, bridge_device, vlan=bridge_vlan, mask=ip.split("/")[1], via=cr_lrp_ip) + + if (CONF.advertisement_method_tenant_networks == + constants.ADVERTISEMENT_METHOD_SUBNET): + # NOTE(jayjahns): We need to delete the route to the + # tenant subnet from the bgp_nic interface. + linux_net.del_ip_route( + routing_tables_routes, + ip.split("/")[0], + CONF.bgp_vrf_table_id, + CONF.bgp_nic, + mask=ip.split("/")[1], + via=cr_lrp_ip) LOG.debug("Deleted IP Routes for network %s", ip) return True diff --git a/ovn_bgp_agent/tests/unit/drivers/openstack/utils/test_wire.py b/ovn_bgp_agent/tests/unit/drivers/openstack/utils/test_wire.py index 4c0c8d61..dc89e4bb 100644 --- a/ovn_bgp_agent/tests/unit/drivers/openstack/utils/test_wire.py +++ b/ovn_bgp_agent/tests/unit/drivers/openstack/utils/test_wire.py @@ -749,6 +749,36 @@ class TestWire(test_base.TestCase): m_ip_rule.assert_called_once_with(ip, 5) m_ip_version.assert_not_called() + @mock.patch.object(linux_net, 'add_ip_route') + @mock.patch.object(linux_net, 'get_ip_version') + @mock.patch.object(linux_net, 'add_ip_rule') + def test__wire_lrp_port_underlay_advertisement_subnet( + self, m_ip_rule, m_ip_version, m_ip_route): + CONF.set_override( + 'advertisement_method_tenant_networks', + constants.ADVERTISEMENT_METHOD_SUBNET) + routing_tables_routes = {} + ip = '10.0.0.1/24' + bridge_device = 'fake-bridge' + bridge_vlan = None + routing_tables = {'fake-bridge': 5} + cr_lrp_ips = ['fake-crlrp-ip'] + ret = wire._wire_lrp_port_underlay( + routing_tables_routes, ip, bridge_device, + bridge_vlan, routing_tables, cr_lrp_ips) + self.assertTrue(ret) + m_ip_rule.assert_called_once_with(ip, 5) + expected_ip_route_calls = [ + mock.call( + routing_tables_routes, ip.split('/')[0], + routing_tables[bridge_device], bridge_device, + vlan=bridge_vlan, mask=ip.split('/')[1], via=cr_lrp_ips[0]), + mock.call( + routing_tables_routes, ip.split('/')[0], + CONF.bgp_vrf_table_id, CONF.bgp_nic, + mask=ip.split('/')[1], via=cr_lrp_ips[0])] + m_ip_route.assert_has_calls(expected_ip_route_calls) + @mock.patch.object(linux_net, 'del_ip_route') @mock.patch.object(linux_net, 'get_ip_version') @mock.patch.object(linux_net, 'del_ip_rule') @@ -805,3 +835,33 @@ class TestWire(test_base.TestCase): self.assertFalse(ret) m_ip_rule.assert_called_once_with(ip, 5) m_ip_version.assert_not_called() + + @mock.patch.object(linux_net, 'del_ip_route') + @mock.patch.object(linux_net, 'get_ip_version') + @mock.patch.object(linux_net, 'del_ip_rule') + def test__unwire_lrp_port_underlay_advertisement_subnet( + self, m_ip_rule, m_ip_version, m_ip_route): + CONF.set_override( + 'advertisement_method_tenant_networks', + constants.ADVERTISEMENT_METHOD_SUBNET) + routing_tables_routes = {} + ip = '10.0.0.1/24' + bridge_device = 'fake-bridge' + bridge_vlan = None + routing_tables = {'fake-bridge': 5} + cr_lrp_ips = ['fake-crlrp-ip'] + ret = wire._unwire_lrp_port_underlay( + routing_tables_routes, ip, bridge_device, bridge_vlan, + routing_tables, cr_lrp_ips) + self.assertTrue(ret) + m_ip_rule.assert_called_once_with(ip, 5) + expected_ip_route_calls = [ + mock.call( + routing_tables_routes, ip.split('/')[0], + routing_tables[bridge_device], bridge_device, + vlan=bridge_vlan, mask=ip.split('/')[1], via=cr_lrp_ips[0]), + mock.call( + routing_tables_routes, ip.split('/')[0], + CONF.bgp_vrf_table_id, CONF.bgp_nic, + mask=ip.split('/')[1], via=cr_lrp_ips[0])] + m_ip_route.assert_has_calls(expected_ip_route_calls)