diff --git a/doc/source/contributor/bgp_mode_design.rst b/doc/source/contributor/bgp_mode_design.rst index 877fa3c2..b4f29fcd 100644 --- a/doc/source/contributor/bgp_mode_design.rst +++ b/doc/source/contributor/bgp_mode_design.rst @@ -258,9 +258,9 @@ To do that, when the agent starts, it ensures that: - There is a VRF created (the one leaked in the previous step), by default - with name ``ovn-bgp-vrf``. + with name ``bgp_vrf``. -- There is a dummy interface type (by default named ``ovn``), associated to +- There is a dummy interface type (by default named ``bgp-nic``), associated to the previously created VRF device. - Ensure ARP/NDP is enabled at OVS provider bridges by adding an IP to it @@ -269,15 +269,15 @@ To do that, when the agent starts, it ensures that: Then, to expose the VMs/LB IPs as they are created (or upon initialization or re-sync), since the FRR configuration has the ``redistribute connected`` option enabled, the only action needed to expose it -(or withdraw it) is to add it (or remove it) from the ``ovn`` dummy interface. +(or withdraw it) is to add it (or remove it) from the ``bgp-nic`` dummy interface. Then it relies on Zebra to do the BGP advertisemant, as Zebra detects the addition/deletion of the IP on the local interface and advertises/withdraw the route: .. code-block:: ini - $ ip addr add IPv4/32 dev ovn - $ ip addr add IPv6/128 dev ovn + $ ip addr add IPv4/32 dev bgp-nic + $ ip addr add IPv6/128 dev bgp-nic .. note:: diff --git a/ovn_bgp_agent/config.py b/ovn_bgp_agent/config.py index ea5d4911..7af1fedd 100644 --- a/ovn_bgp_agent/config.py +++ b/ovn_bgp_agent/config.py @@ -71,6 +71,19 @@ agent_opts = [ default=4789, help='The UDP port used for EVPN VXLAN communication. By ' 'default 4789 is being used.'), + cfg.StrOpt('bgp_nic', + default='bgp-nic', + help='The name of the interface used within the VRF ' + '(bgp_vrf option) to expose the IPs and/or Networks.'), + cfg.StrOpt('bgp_vrf', + default='bgp-vrf', + help='The name of the VRF to be used to expose the IPs ' + 'and/or Networks through BGP.'), + cfg.IntOpt('bgp_vrf_table_id', + default=10, + help='The Routing Table ID that the VRF (bgp_vrf option) ' + 'should use. If it does not exist, this table will be ' + 'created.'), ] root_helper_opts = [ diff --git a/ovn_bgp_agent/constants.py b/ovn_bgp_agent/constants.py index 6a2c138a..e219c093 100644 --- a/ovn_bgp_agent/constants.py +++ b/ovn_bgp_agent/constants.py @@ -22,9 +22,6 @@ OVN_LOCALNET_VIF_PORT_TYPE = "localnet" OVN_CIDRS_EXT_ID_KEY = 'neutron:cidrs' -OVN_BGP_NIC = "ovn" -OVN_BGP_VRF = "ovn-bgp-vrf" -OVN_BGP_VRF_TABLE = 10 OVS_RULE_COOKIE = "999" OVS_VRF_RULE_COOKIE = "998" diff --git a/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py b/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py index c5ae6583..0950738d 100644 --- a/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py +++ b/ovn_bgp_agent/drivers/openstack/ovn_bgp_driver.py @@ -70,7 +70,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): # Ensure FRR is configure to leak the routes # NOTE: If we want to recheck this every X time, we should move it # inside the sync function instead - frr.vrf_leak(constants.OVN_BGP_VRF, CONF.bgp_AS, CONF.bgp_router_id) + frr.vrf_leak(CONF.bgp_vrf, CONF.bgp_AS, CONF.bgp_router_id) self.ovs_idl = ovs.OvsIdl() self.ovs_idl.start(CONF.ovsdb_connection) @@ -127,11 +127,11 @@ class OVNBGPDriver(driver_api.AgentDriverBase): LOG.debug("Ensuring VRF configuration for advertising routes") # Create VRF - linux_net.ensure_vrf(constants.OVN_BGP_VRF, - constants.OVN_BGP_VRF_TABLE) + linux_net.ensure_vrf(CONF.bgp_vrf, + CONF.bgp_vrf_table_id) # Create OVN dummy device - linux_net.ensure_ovn_device(constants.OVN_BGP_NIC, - constants.OVN_BGP_VRF) + linux_net.ensure_ovn_device(CONF.bgp_nic, + CONF.bgp_vrf) LOG.debug("Configuring br-ex default rule and routing tables for " "each provider network") @@ -174,7 +174,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): ovs.remove_extra_ovs_flows(flows_info, constants.OVS_RULE_COOKIE) LOG.debug("Syncing current routes.") - exposed_ips = linux_net.get_exposed_ips(constants.OVN_BGP_NIC) + exposed_ips = linux_net.get_exposed_ips(CONF.bgp_nic) # get the rules pointing to ovn bridges ovn_ip_rules = linux_net.get_ovn_ip_rules( self.ovn_routing_tables.values()) @@ -236,7 +236,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): # remove extra routes/ips # remove all the leftovers on the list of current ips on dev OVN - linux_net.delete_exposed_ips(exposed_ips, constants.OVN_BGP_NIC) + linux_net.delete_exposed_ips(exposed_ips, CONF.bgp_nic) # remove all the leftovers on the list of current ip rules for ovn # bridges linux_net.delete_ip_rules(ovn_ip_rules) @@ -343,7 +343,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): if ext_n_cidr: ovn_lb_ip = ext_n_cidr.split(" ")[0].split("/")[0] linux_net.add_ips_to_dev( - constants.OVN_BGP_NIC, [ovn_lb_ip]) + CONF.bgp_nic, [ovn_lb_ip]) if ovn_lb_ip in exposed_ips: exposed_ips.remove(ovn_lb_ip) elif (not port.mac or @@ -366,7 +366,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): port_ip_version = linux_net.get_ip_version(port_ip) if port_ip_version == router_port_ip_version: linux_net.add_ips_to_dev( - constants.OVN_BGP_NIC, [port_ip]) + CONF.bgp_nic, [port_ip]) if port_ip in exposed_ips: exposed_ips.remove(port_ip) if router_port_ip_version == constants.IP_VERSION_6: @@ -415,9 +415,9 @@ class OVNBGPDriver(driver_api.AgentDriverBase): # Check if there are VMs on the network # and if so withdraw the routes vms_on_net = linux_net.get_exposed_ips_on_network( - constants.OVN_BGP_NIC, net) + CONF.bgp_nic, net) if vms_on_net: - linux_net.delete_exposed_ips(vms_on_net, constants.OVN_BGP_NIC) + linux_net.delete_exposed_ips(vms_on_net, CONF.bgp_nic) def _get_bridge_for_datapath(self, datapath): network_name, network_tag = self.sb_idl.get_network_name_and_tag( @@ -437,7 +437,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): self.ovn_lb_vips.setdefault(ovn_lb, []).append(ip) LOG.debug("Adding BGP route for loadbalancer VIP %s", ip) - linux_net.add_ips_to_dev(constants.OVN_BGP_NIC, [ip]) + linux_net.add_ips_to_dev(CONF.bgp_nic, [ip]) rule_bridge, vlan_tag = self._get_bridge_for_datapath(provider_dp) try: @@ -457,7 +457,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): def withdraw_ovn_lb_on_provider(self, ovn_lb, provider_dp, cr_lrp): for ip in self.ovn_lb_vips[ovn_lb].copy(): LOG.debug("Deleting BGP route for loadbalancer VIP %s", ip) - linux_net.del_ips_from_dev(constants.OVN_BGP_NIC, [ip]) + linux_net.del_ips_from_dev(CONF.bgp_nic, [ip]) rule_bridge, vlan_tag = self._get_bridge_for_datapath(provider_dp) @@ -496,7 +496,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): row.type == constants.OVN_VIRTUAL_VIF_PORT_TYPE) and self.sb_idl.is_provider_network(row.datapath)): LOG.debug("Adding BGP route for logical port with ip %s", ips) - linux_net.add_ips_to_dev(constants.OVN_BGP_NIC, ips) + linux_net.add_ips_to_dev(CONF.bgp_nic, ips) rule_bridge, vlan_tag = self._get_bridge_for_datapath(row.datapath) for ip in ips: @@ -521,7 +521,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): row.logical_port) if fip_address: LOG.debug("Adding BGP route for FIP with ip %s", fip_address) - linux_net.add_ips_to_dev(constants.OVN_BGP_NIC, + linux_net.add_ips_to_dev(CONF.bgp_nic, [fip_address]) rule_bridge, vlan_tag = self._get_bridge_for_datapath( @@ -550,7 +550,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): if (associated_port and self.sb_idl.is_port_on_chassis( associated_port, self.chassis)): LOG.debug("Adding BGP route for FIP with ip %s", ips) - linux_net.add_ips_to_dev(constants.OVN_BGP_NIC, ips) + linux_net.add_ips_to_dev(CONF.bgp_nic, ips) rule_bridge, vlan_tag = self._get_bridge_for_datapath( row.datapath) @@ -589,7 +589,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): 'ovn_lbs': [] } ips_without_mask = [ip.split("/")[0] for ip in ips] - linux_net.add_ips_to_dev(constants.OVN_BGP_NIC, ips_without_mask) + linux_net.add_ips_to_dev(CONF.bgp_nic, ips_without_mask) rule_bridge, vlan_tag = self._get_bridge_for_datapath( cr_lrp_datapath) @@ -669,7 +669,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): row.type == constants.OVN_VIRTUAL_VIF_PORT_TYPE) and self.sb_idl.is_provider_network(row.datapath)): LOG.debug("Deleting BGP route for logical port with ip %s", ips) - linux_net.del_ips_from_dev(constants.OVN_BGP_NIC, ips) + linux_net.del_ips_from_dev(CONF.bgp_nic, ips) rule_bridge, vlan_tag = self._get_bridge_for_datapath(row.datapath) for ip in ips: @@ -692,7 +692,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): return LOG.debug("Delete BGP route for FIP with ip %s", fip_address) - linux_net.del_ips_from_dev(constants.OVN_BGP_NIC, + linux_net.del_ips_from_dev(CONF.bgp_nic, [fip_address]) rule_bridge, vlan_tag = self._get_bridge_for_datapath( @@ -713,7 +713,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): associated_port, self.chassis) or self.sb_idl.is_port_deleted(associated_port))): LOG.debug("Deleting BGP route for FIP with ip %s", ips) - linux_net.del_ips_from_dev(constants.OVN_BGP_NIC, ips) + linux_net.del_ips_from_dev(CONF.bgp_nic, ips) rule_bridge, vlan_tag = self._get_bridge_for_datapath( row.datapath) @@ -739,7 +739,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): # Removing information about the associated network for # tenant network advertisement ips_without_mask = [ip.split("/")[0] for ip in ips] - linux_net.del_ips_from_dev(constants.OVN_BGP_NIC, + linux_net.del_ips_from_dev(CONF.bgp_nic, ips_without_mask) rule_bridge, vlan_tag = self._get_bridge_for_datapath( @@ -800,7 +800,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): if port_lrp in self.ovn_local_lrps: LOG.debug("Adding BGP route for tenant IP %s on chassis %s", ips, self.chassis) - linux_net.add_ips_to_dev(constants.OVN_BGP_NIC, ips) + linux_net.add_ips_to_dev(CONF.bgp_nic, ips) LOG.debug("Added BGP route for tenant IP %s on chassis %s", ips, self.chassis) @@ -813,7 +813,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): if port_lrp in self.ovn_local_lrps: LOG.debug("Deleting BGP route for tenant IP %s on chassis %s", ips, self.chassis) - linux_net.del_ips_from_dev(constants.OVN_BGP_NIC, ips) + linux_net.del_ips_from_dev(CONF.bgp_nic, ips) LOG.debug("Deleted BGP route for tenant IP %s on chassis %s", ips, self.chassis) @@ -893,7 +893,7 @@ class OVNBGPDriver(driver_api.AgentDriverBase): # IP version port_ip_version = linux_net.get_ip_version(port_ip) if port_ip_version == ip_version: - linux_net.add_ips_to_dev(constants.OVN_BGP_NIC, [port_ip]) + linux_net.add_ips_to_dev(CONF.bgp_nic, [port_ip]) @lockutils.synchronized('bgp') def withdraw_subnet(self, ip, row): @@ -952,5 +952,5 @@ class OVNBGPDriver(driver_api.AgentDriverBase): # Check if there are VMs on the network # and if so withdraw the routes vms_on_net = linux_net.get_exposed_ips_on_network( - constants.OVN_BGP_NIC, net) - linux_net.delete_exposed_ips(vms_on_net, constants.OVN_BGP_NIC) + CONF.bgp_nic, net) + linux_net.delete_exposed_ips(vms_on_net, CONF.bgp_nic) diff --git a/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py b/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py index 6a5d0b69..07a346a7 100644 --- a/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py +++ b/ovn_bgp_agent/tests/unit/drivers/openstack/test_ovn_bgp_driver.py @@ -75,7 +75,7 @@ class TestOVNBGPDriver(test_base.TestCase): self.bgp_driver.start() mock_vrf.assert_called_once_with( - constants.OVN_BGP_VRF, CONF.bgp_AS, CONF.bgp_router_id) + CONF.bgp_vrf, CONF.bgp_AS, CONF.bgp_router_id) # Assert connections were started self.mock_ovs_idl().start.assert_called_once_with( CONF.ovsdb_connection) @@ -119,9 +119,9 @@ class TestOVNBGPDriver(test_base.TestCase): self.bgp_driver.sync() mock_ensure_vrf.assert_called_once_with( - constants.OVN_BGP_VRF, constants.OVN_BGP_VRF_TABLE) + CONF.bgp_vrf, CONF.bgp_vrf_table_id) mock_ensure_ovn_dev.assert_called_once_with( - constants.OVN_BGP_NIC, constants.OVN_BGP_VRF) + CONF.bgp_nic, CONF.bgp_vrf) expected_calls = [mock.call('bridge0', 1, 10), mock.call('bridge1', 2, 11)] @@ -159,7 +159,7 @@ class TestOVNBGPDriver(test_base.TestCase): mock_ensure_cr_port_exposed.assert_has_calls(expected_calls) mock_del_exposed_ips.assert_called_once_with( - ips, constants.OVN_BGP_NIC) + ips, CONF.bgp_nic) mock_del_ip_riles.assert_called_once_with(fake_ip_rules) moock_del_ip_routes.assert_called_once_with( {self.bridge: 'fake-table'}, mock.ANY, @@ -287,9 +287,9 @@ class TestOVNBGPDriver(test_base.TestCase): mock_add_route.assert_called_once_with( mock.ANY, self.ipv4, 'fake-table', self.bridge, vlan=10, mask='32', via=self.fip) - expected_calls = [mock.call(constants.OVN_BGP_NIC, ['192.168.1.10']), - mock.call(constants.OVN_BGP_NIC, ['192.168.1.11']), - mock.call(constants.OVN_BGP_NIC, ['192.168.1.13'])] + expected_calls = [mock.call(CONF.bgp_nic, ['192.168.1.10']), + mock.call(CONF.bgp_nic, ['192.168.1.11']), + mock.call(CONF.bgp_nic, ['192.168.1.13'])] mock_add_ips_dev.assert_has_calls(expected_calls) @mock.patch.object(linux_net, 'add_ip_route') @@ -382,7 +382,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the add methods were called mock_add_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, [self.ipv4]) + CONF.bgp_nic, [self.ipv4]) mock_add_rule.assert_called_once_with( self.ipv4, 'fake-table', self.bridge) mock_add_route.assert_called_once_with( @@ -405,7 +405,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the add methods were called mock_add_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, [self.ipv4]) + CONF.bgp_nic, [self.ipv4]) mock_add_rule.assert_called_once_with( self.ipv4, 'fake-table', self.bridge) mock_add_route.assert_not_called() @@ -423,8 +423,8 @@ class TestOVNBGPDriver(test_base.TestCase): self.loadbalancer, 'fake-provider-dp', self.cr_lrp0) # Assert that the del methods were called - expected_calls = [mock.call(constants.OVN_BGP_NIC, [self.ipv4]), - mock.call(constants.OVN_BGP_NIC, [self.ipv6])] + expected_calls = [mock.call(CONF.bgp_nic, [self.ipv4]), + mock.call(CONF.bgp_nic, [self.ipv6])] mock_del_ip_dev.assert_has_calls(expected_calls) expected_calls = [mock.call(self.ipv4, 'fake-table', self.bridge), @@ -456,7 +456,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the add methods were called mock_add_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, ips) + CONF.bgp_nic, ips) expected_calls = [mock.call(self.ipv4, 'fake-table', self.bridge), mock.call(self.ipv6, 'fake-table', self.bridge)] @@ -490,7 +490,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the add methods were called mock_add_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, [self.fip]) + CONF.bgp_nic, [self.fip]) mock_add_rule.assert_called_once_with( self.fip, 'fake-table', self.bridge) mock_add_route.assert_called_once_with( @@ -544,7 +544,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the add methods were called mock_add_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, ips) + CONF.bgp_nic, ips) expected_calls = [mock.call(self.ipv4, 'fake-table', self.bridge), mock.call(self.ipv6, 'fake-table', self.bridge)] @@ -615,7 +615,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the add methods were called mock_add_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, ips) + CONF.bgp_nic, ips) expected_calls = [mock.call(self.ipv4, 'fake-table', self.bridge, lladdr=self.mac), @@ -663,7 +663,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the del methods were called mock_del_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, ips) + CONF.bgp_nic, ips) expected_calls = [mock.call(self.ipv4, 'fake-table', self.bridge), mock.call(self.ipv6, 'fake-table', self.bridge)] @@ -697,7 +697,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the del methods were called mock_del_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, [self.fip]) + CONF.bgp_nic, [self.fip]) mock_del_rule.assert_called_once_with( self.fip, 'fake-table', self.bridge) mock_del_route.assert_called_once_with( @@ -745,7 +745,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the del methods were called mock_del_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, ips) + CONF.bgp_nic, ips) expected_calls = [mock.call(self.ipv4, 'fake-table', self.bridge), mock.call(self.ipv6, 'fake-table', self.bridge)] @@ -799,7 +799,7 @@ class TestOVNBGPDriver(test_base.TestCase): # Assert that the del methods were called mock_del_ip_dev.assert_called_once_with( - constants.OVN_BGP_NIC, ips) + CONF.bgp_nic, ips) expected_calls = [mock.call('{}/32'.format(self.ipv4), 'fake-table', self.bridge, lladdr=self.mac), @@ -832,7 +832,7 @@ class TestOVNBGPDriver(test_base.TestCase): ips = [self.ipv4, self.ipv6] self.bgp_driver.expose_remote_ip(ips, row) - mock_add_ip_dev.assert_called_once_with(constants.OVN_BGP_NIC, ips) + mock_add_ip_dev.assert_called_once_with(CONF.bgp_nic, ips) @mock.patch.object(linux_net, 'add_ips_to_dev') def test_expose_remote_ip_is_provider_network(self, mock_add_ip_dev): @@ -871,7 +871,7 @@ class TestOVNBGPDriver(test_base.TestCase): ips = [self.ipv4, self.ipv6] self.bgp_driver.withdraw_remote_ip(ips, row) - mock_del_ip_dev.assert_called_once_with(constants.OVN_BGP_NIC, ips) + mock_del_ip_dev.assert_called_once_with(CONF.bgp_nic, ips) @mock.patch.object(linux_net, 'del_ips_from_dev') def test_withdraw_remote_ip_is_provider_network(self, mock_del_ip_dev): @@ -941,8 +941,8 @@ class TestOVNBGPDriver(test_base.TestCase): mock_add_route.assert_called_once_with( mock.ANY, self.ipv4, 'fake-table', self.bridge, vlan=10, mask='32', via=self.fip) - expected_calls = [mock.call(constants.OVN_BGP_NIC, ['192.168.1.10']), - mock.call(constants.OVN_BGP_NIC, ['192.168.1.11'])] + expected_calls = [mock.call(CONF.bgp_nic, ['192.168.1.10']), + mock.call(CONF.bgp_nic, ['192.168.1.11'])] mock_add_ip_dev.assert_has_calls(expected_calls) @mock.patch.object(linux_net, 'get_exposed_ips_on_network') @@ -973,4 +973,4 @@ class TestOVNBGPDriver(test_base.TestCase): mock.ANY, self.ipv4, 'fake-table', self.bridge, vlan=10, mask='32', via=self.fip) mock_del_exposed_ips.assert_called_once_with( - [self.ipv4], constants.OVN_BGP_NIC) + [self.ipv4], CONF.bgp_nic)