Jakub Libosvar df6be866e7 Remove re-typing lists to sets at initialization
The patch removes code where lists are generated and immediatelly
converted to sets. It also uses set comprehension where applicable.

Change-Id: I4f96a88e100593cfaf2a95f3aa409eed531c2ed4
2024-01-11 21:33:17 +00:00

663 lines
28 KiB
Python

# Copyright 2023 Red Hat, Inc.
#
# 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.
from oslo_config import cfg
from oslo_log import log as logging
from ovn_bgp_agent import constants
from ovn_bgp_agent.drivers.openstack.utils import ovs
from ovn_bgp_agent import exceptions as agent_exc
from ovn_bgp_agent.utils import helpers
from ovn_bgp_agent.utils import linux_net
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
def ensure_base_wiring_config(idl, ovs_idl, ovn_idl=None, routing_tables={}):
if CONF.exposing_method == constants.EXPOSE_METHOD_UNDERLAY:
return _ensure_base_wiring_config_underlay(idl, ovs_idl,
routing_tables)
elif CONF.exposing_method == constants.EXPOSE_METHOD_OVN:
return _ensure_base_wiring_config_ovn(ovs_idl, ovn_idl)
def _ensure_base_wiring_config_underlay(idl, ovs_idl, routing_tables):
# Get bridge mappings: xxxx:br-ex,yyyy:br-ex2
bridge_mappings = ovs_idl.get_ovn_bridge_mappings()
ovn_bridge_mappings = {}
flows_info = {}
for bridge_index, bridge_mapping in enumerate(bridge_mappings, 1):
network, bridge = helpers.parse_bridge_mapping(bridge_mapping)
if not network:
continue
ovn_bridge_mappings[network] = bridge
linux_net.ensure_routing_table_for_bridge(
routing_tables, bridge, CONF.bgp_vrf_table_id)
vlan_tags = idl.get_network_vlan_tag_by_network_name(network)
for vlan_tag in vlan_tags:
linux_net.ensure_vlan_device_for_network(bridge,
vlan_tag)
linux_net.ensure_arp_ndp_enabled_for_bridge(bridge,
bridge_index,
vlan_tags)
if not flows_info.get(bridge):
mac = linux_net.get_interface_address(bridge)
flows_info[bridge] = {'mac': mac, 'in_port': set()}
flows_info[bridge]['in_port'] = ovs.get_ovs_patch_ports_info(
bridge)
ovs.ensure_mac_tweak_flows(bridge, mac,
flows_info[bridge]['in_port'],
constants.OVS_RULE_COOKIE)
return ovn_bridge_mappings, flows_info
def _ensure_base_wiring_config_ovn(ovs_idl, ovn_idl):
"""Base configuration for extra OVN cluster instead of kernel networking
This function is in charge of the steps to ensure the in-node OVN cluster
is properly configured by:
1. Get the information about the OpenStack provider bridge(s) and the flows
info, such as the mac and the in_port
2. Add the egress ovs flows so that the destination mac is the one on the
extra ovn-cluster, in the LR
3. Create the LR in the in-node OVN cluster
4. Create the LR policy in the in-node OVN cluster to redirect the traffic
(with ECMP support) to the nexthops
5. Create the LR routes in the in-node OVN cluster to route any traffic the
peers IPs
6. Create the LS (+ Localnet port) for the connection between the router
and the OpenStack OVN networks. then it connects it to the LR
7. Create the LS (+ Localnet port) for the connection between the router
and the external network. Then it connects it to the LR
8. Create the ingress_flow at the external OVN provider bridges to
redirect the needed traffic to the in-cluster OVN networks
:param ovs_idl: The idl to communicate with local ovs DB
:param ovn_idl: The idl to communicate with local (in-node) NB DB
:return: ovn_bridge_mappings (network and bridges association) and the
flows_info per bridge
"""
# OpenStack Egress part
# Get bridge mappings: xxxx:br-ex,yyyy:br-ex2
bridge_mappings = ovs_idl.get_ovn_bridge_mappings()
ovn_bridge_mappings = {}
flows_info = {}
for bridge_mapping in bridge_mappings:
network, bridge = helpers.parse_bridge_mapping(bridge_mapping)
if not network:
continue
ovn_bridge_mappings[network] = bridge
if not flows_info.get(bridge):
mac = linux_net.get_interface_address(bridge)
flows_info[bridge] = {'mac': mac, 'in_port': set()}
flows_info[bridge]['in_port'] = ovs.get_ovs_patch_ports_info(
bridge)
_ensure_egress_flows(bridge, flows_info[bridge]['in_port'])
# Extra OVN cluster configuration
provider_cidrs = CONF.local_ovn_cluster.provider_networks_pool_prefixes
# LR
cmds = []
cmds.extend(_ensure_ovn_router(ovn_idl))
# FIXME(ltomasbo): we need to firsts create the router and then the
# policies and routes in a different transaction until ovsdbapp
# allows it to do it in one transaction. Once that happen the next
# 2 lines can be removed
_execute_commands(ovn_idl, cmds)
cmds = []
cmds.extend(_ensure_ovn_policies(ovn_idl, CONF.local_ovn_cluster.peer_ips))
cmds.extend(_ensure_ovn_routes(ovn_idl, CONF.local_ovn_cluster.peer_ips))
# Creation of all router related cmds in a single transaction
_execute_commands(ovn_idl, cmds)
# LS
bgp_bridge_mappings = ovs_idl.get_ovn_bridge_mappings(
bridge=constants.OVN_CLUSTER_BRIDGE)
for bridge_mapping in bgp_bridge_mappings:
network, bridge = helpers.parse_bridge_mapping(bridge_mapping)
if not network:
continue
# Create LS + Localnet port on it
_ensure_ovn_switch(ovn_idl, network)
# differentiate between internal LS (connecting to OpenStack)
# and external LS (connecting to the NICs)
if bridge in ovn_bridge_mappings.values():
# Internal Bridge connecting to OpenStack OVN cluster
_ensure_ovn_network_link(ovn_idl, network, 'internal',
provider_cidrs=provider_cidrs)
else:
ip, mac = linux_net.get_nic_info(bridge)
# External Bridge connecting to the external networks
_ensure_ovn_network_link(ovn_idl, network, 'external',
ip=ip, mac=mac)
_ensure_ingress_flows(bridge, mac, network, provider_cidrs)
return ovn_bridge_mappings, flows_info
def _ensure_ovn_router(ovn_idl):
return [ovn_idl.lr_add(constants.OVN_CLUSTER_ROUTER, may_exist=True)]
def _ensure_ovn_switch(ovn_idl, switch_name):
ovn_idl.ls_add(switch_name, may_exist=True).execute(check_error=True)
# Add localnet port to them
localnet_port = "{}-localnet".format(switch_name)
options = {'network_name': switch_name}
cmds = _ensure_lsp_cmds(ovn_idl, localnet_port, switch_name, 'localnet',
'unknown', **options)
_execute_commands(ovn_idl, cmds)
def _execute_commands(idl, cmds):
with idl.transaction(check_error=True) as txn:
for command in cmds:
txn.add(command)
def _ensure_ovn_network_link(ovn_idl, switch_name, direction,
provider_cidrs=None, ip=None, mac=None):
"""Base configuration for connecting LR and LSs
This function is in charge of connecting the LR to the external or internal
LS
For the internal LS it configures:
1. Creates LRP to connect to the internal switch
2. If networks (provider_cidrs) are different, adding the new networks
3. Create LSP related to the LRP with the right options, including the
arp_proxy
4. Bind the LRP to the local chassis
For the external LS it configures:
1. Creates LRP to connect to the external switch
2. If networks (ip) is different than the nic network add the nic network
and remove the extra ones
3. Create LSP related to the LRP with the right options
:param ovn_idl: The idl to communicate with local (in-node) NB DB
:param switch_name: the name of the logical switch to configure
:param direction: can be 'internal' or 'external'
:param provider_cidrs (optional): CIDRs to configure the networks of the
LRP, as well as to configure the ARP
proxy on the internal LSP
(only for the internal)
:param ip (optional): IP to configure in the LRP connected to the external
switch (only for the external)
:param mac (optional): MAC to configure in the LRP connected to the
external switch (only for the external)
"""
# It accepts 2 values for direction: internal or external
cmds = []
if direction == 'internal':
# Connect BGP router to the internal logical switch
r_port_name = "{}-openstack".format(constants.OVN_CLUSTER_ROUTER)
try:
ovn_idl.lrp_add(constants.OVN_CLUSTER_ROUTER, r_port_name,
constants.OVN_CLUSTER_ROUTER_INTERNAL_MAC,
provider_cidrs, peer=[], may_exist=True).execute(
check_error=True)
except RuntimeError as rte:
# TODO(ltomasbo): Change OVSDBAPP to return a different error for
# this to avoid having to compare strings as this is error prone
networks_message = 'with different networks'
if networks_message not in str(rte):
raise
# Trying to sync the networks by adding them
cmds.append(ovn_idl.lrp_add_networks(r_port_name, provider_cidrs,
may_exist=True))
s_port_name = "openstack-{}".format(constants.OVN_CLUSTER_ROUTER)
# NOTE(ltomasbo): require v23.06.0 so that proxy-arp works as expected.
# If older version the provider_cidrs should contain all the provider
# network cidrs, pointing to the gateway IP of the network.
cidrs = ','.join(provider_cidrs) if provider_cidrs else '0.0.0.0/0'
options = {'router-port': r_port_name, 'arp_proxy': cidrs}
cmds.extend(_ensure_lsp_cmds(ovn_idl, s_port_name, switch_name,
'router', 'router', **options))
# bind to local chassis
# ovn-nbctl lrp-set-gateway-chassis bgp-router-public bgp 1
cmds.append(ovn_idl.lrp_set_gateway_chassis(
r_port_name, constants.OVN_CLUSTER_BRIDGE, 1))
else: # direction == 'external'
# Connect BGP router to the external logical switch
r_port_name = "{}-{}".format(constants.OVN_CLUSTER_ROUTER, switch_name)
# LRP
try:
ovn_idl.lrp_add(constants.OVN_CLUSTER_ROUTER, r_port_name,
mac, [ip], peer=[], may_exist=True).execute(
check_error=True)
except RuntimeError as rte:
# TODO(ltomasbo): Change OVSDBAPP to return a different error for
# this to avoid having to compare strings as this is error prone
networks_message = 'with different networks'
if networks_message not in str(rte):
raise
# Trying to sync the networks by adding them
cmds.append(ovn_idl.lrp_add_networks(r_port_name,
[ip],
may_exist=True))
lrp = ovn_idl.lrp_get(r_port_name).execute(check_error=True)
for net in lrp.networks:
if net != ip:
cmds.append(ovn_idl.lrp_del_networks(r_port_name,
[net],
if_exists=True))
# LSP
s_port_name = "{}-{}".format(switch_name, constants.OVN_CLUSTER_ROUTER)
options = {'router-port': r_port_name}
cmds.extend(_ensure_lsp_cmds(ovn_idl, s_port_name, switch_name,
'router', 'router', **options))
if cmds:
_execute_commands(ovn_idl, cmds)
def _ensure_lsp_cmds(ovn_idl, port_name, switch, port_type, addresses,
**options):
cmds = []
cmds.append(ovn_idl.lsp_add(switch, port_name, may_exist=True))
cmds.append(ovn_idl.lsp_set_type(port_name, port_type))
cmds.append(ovn_idl.lsp_set_addresses(port_name,
addresses=[addresses]))
cmds.append(ovn_idl.lsp_set_options(port_name, **options))
return cmds
def _ensure_ovn_policies(ovn_idl, next_hops):
priority = 10
match = 'inport=="{}-openstack"'.format(constants.OVN_CLUSTER_ROUTER)
action = 'reroute'
columns = {}
if len(next_hops) > 1:
columns = {'nexthops': next_hops}
elif len(next_hops) == 1:
columns = {'nexthop': next_hops[0]}
return [ovn_idl.lr_policy_add(constants.OVN_CLUSTER_ROUTER, priority,
match, action, may_exist=True, **columns)]
def _ensure_ovn_routes(ovn_idl, peer_ips):
prefix = '0.0.0.0/0'
cmds = []
for ip in peer_ips:
cmds.append(ovn_idl.lr_route_add(constants.OVN_CLUSTER_ROUTER, prefix,
ip, ecmp=True, may_exist=True))
return cmds
def _ensure_ingress_flows(bridge, mac, switch_name, provider_cidrs):
# incomming traffic flows
# patch=`ovs-ofctl show br-ex | grep patch | cut -d "(" -f1 | xargs`
# ovs-ofctl add-flow br-ex
# "cookie=0xbadcaf2,ip,nw_dst=$PROVIDER_NET,in_port=enp2s0,priority=100,
# actions=mod_dl_dst:$ENP2S0_MAC,output=$patch"
if not provider_cidrs:
return
patch_port_prefix = 'patch-{}-'.format(switch_name)
patch_ports = ovs.get_ovs_patch_ports_info(bridge,
prefix=patch_port_prefix)
if not patch_ports:
return
bridge_ports = set(ovs.get_ovs_ports_info(bridge))
external_nic = list(bridge_ports.intersection(
set(CONF.local_ovn_cluster.external_nics)))
if not external_nic:
LOG.warning("NIC ports (%s) not found for bridge %s. Not possible to "
"create the ingress flows. It will be retried if "
"reconcile cycle is not disabled",
CONF.local_ovn_cluster.external_nics, bridge)
return
else:
# only one external_nic expected per bridge
external_nic = external_nic[0]
for provider_cidr in provider_cidrs:
ip_version = linux_net.get_ip_version(provider_cidr)
if ip_version == constants.IP_VERSION_6:
ip = 'ipv6'
else:
ip = 'ip'
flow = (
"cookie={},priority=1000,{},nw_dst={},in_port={},"
" actions=mod_dl_dst:{},output={}".format(
constants.OVS_RULE_COOKIE, ip, provider_cidr, external_nic,
mac, patch_ports[0]))
ovs.ensure_flow(bridge, flow)
def _ensure_egress_flows(bridge, patch_ports):
# outcomming traffic flows
# patch=`ovs-ofctl show br-provider | grep patch | grep provnet |
# cut -d "(" -f1 | xargs`
# ovs-ofctl add-flow br-provider "cookie=0xbadcaf3,ip,in_port=$patch,
# actions=mod_dl_dst:$ROUTER_MAC,NORMAL"
for patch_port in patch_ports:
flow = (
"cookie={},priority=1000,ip,in_port={},"
" actions=mod_dl_dst:{},NORMAL".format(
constants.OVS_RULE_COOKIE, patch_port,
constants.OVN_CLUSTER_ROUTER_INTERNAL_MAC))
flow_v6 = (
"cookie={},priority=1000,ipv6,in_port={},"
" actions=mod_dl_dst:{},NORMAL".format(
constants.OVS_RULE_COOKIE, patch_port,
constants.OVN_CLUSTER_ROUTER_INTERNAL_MAC))
ovs.ensure_flow(bridge, flow)
ovs.ensure_flow(bridge, flow_v6)
def cleanup_wiring(idl, bridge_mappings, ovs_flows, exposed_ips,
routing_tables, routing_tables_routes):
if CONF.exposing_method == constants.EXPOSE_METHOD_UNDERLAY:
return _cleanup_wiring_underlay(idl, bridge_mappings, ovs_flows,
exposed_ips, routing_tables,
routing_tables_routes)
elif CONF.exposing_method == constants.EXPOSE_METHOD_OVN:
# TODO(ltomasbo): clean up old policies, routes and proxy_arps cidrs
return True
def _cleanup_wiring_underlay(idl, bridge_mappings, ovs_flows, exposed_ips,
routing_tables, routing_tables_routes):
current_ips = linux_net.get_exposed_ips(CONF.bgp_nic)
expected_ips = [ip for ip_dict in exposed_ips.values()
for ip in ip_dict.keys()]
ips_to_delete = [ip for ip in current_ips if ip not in expected_ips]
linux_net.delete_exposed_ips(ips_to_delete, CONF.bgp_nic)
extra_routes = {}
for bridge in bridge_mappings.values():
extra_routes[bridge] = (
linux_net.get_extra_routing_table_for_bridge(routing_tables,
bridge))
# delete extra ovs flows
ovs.remove_extra_ovs_flows(ovs_flows, bridge,
constants.OVS_RULE_COOKIE)
# get rules and delete the old ones
ovn_ip_rules = linux_net.get_ovn_ip_rules(routing_tables.values())
if ovn_ip_rules:
for ip in expected_ips:
if len(ip.split("/")) == 1:
ip_version = linux_net.get_ip_version(ip)
if ip_version == constants.IP_VERSION_6:
ip_dst = "{}/128".format(ip)
else:
ip_dst = "{}/32".format(ip)
else:
ip_dst = ip
ovn_ip_rules.pop(ip_dst, None)
linux_net.delete_ip_rules(ovn_ip_rules)
# remove all the extra routes not needed
linux_net.delete_bridge_ip_routes(routing_tables, routing_tables_routes,
extra_routes)
# delete leaked vlan devices from previous vlan provider networks
delete_vlan_devices_leftovers(idl, bridge_mappings)
def delete_vlan_devices_leftovers(idl, bridge_mappings):
vlan_tags = idl.get_network_vlan_tags()
ovs_devices = set(bridge_mappings.values())
for ovs_device in ovs_devices:
vlans = linux_net.get_bridge_vlans(ovs_device)
for vlan in vlans:
if vlan and vlan not in vlan_tags:
linux_net.delete_vlan_device_for_network(ovs_device, vlan)
def wire_provider_port(routing_tables_routes, ovs_flows, port_ips,
bridge_device, bridge_vlan, localnet, routing_table,
proxy_cidrs, lladdr=None, mac=None, ovn_idl=None):
if CONF.exposing_method == constants.EXPOSE_METHOD_UNDERLAY:
return _wire_provider_port_underlay(routing_tables_routes, ovs_flows,
port_ips, bridge_device,
bridge_vlan, localnet,
routing_table, proxy_cidrs,
lladdr=lladdr)
elif CONF.exposing_method == constants.EXPOSE_METHOD_OVN:
# We need to add a static mac binding due to proxy-arp issue in
# core ovn that would reply on the incomming traffic from the LR,
# while it should not
return _wire_provider_port_ovn(ovn_idl, port_ips, mac)
def unwire_provider_port(routing_tables_routes, port_ips, bridge_device,
bridge_vlan, routing_table, proxy_cidrs, lladdr=None,
ovn_idl=None):
if CONF.exposing_method == constants.EXPOSE_METHOD_UNDERLAY:
return _unwire_provider_port_underlay(routing_tables_routes, port_ips,
bridge_device, bridge_vlan,
routing_table, proxy_cidrs,
lladdr=lladdr)
elif CONF.exposing_method == constants.EXPOSE_METHOD_OVN:
# We need to remove thestatic mac binding added due to proxy-arp issue
# in core ovn that would reply on the incomming traffic from the LR,
# while it should not
return _unwire_provider_port_ovn(ovn_idl, port_ips)
def _ensure_updated_mac_tweak_flows(localnet, bridge_device, ovs_flows):
ofport = ovs.get_ovs_patch_port_ofport(localnet)
if ofport not in ovs_flows[bridge_device]['in_port']:
ovs_flows[bridge_device]['in_port'].append(ofport)
ovs.ensure_mac_tweak_flows(bridge_device,
ovs_flows[bridge_device]['mac'],
[ofport],
constants.OVS_RULE_COOKIE)
def _wire_provider_port_underlay(routing_tables_routes, ovs_flows, port_ips,
bridge_device, bridge_vlan, localnet,
routing_table, proxy_cidrs, lladdr=None):
if not bridge_device:
return False
for ip in port_ips:
try:
if lladdr:
dev = bridge_device
if bridge_vlan:
dev = '{}.{}'.format(dev, bridge_vlan)
linux_net.add_ip_rule(ip, routing_table[bridge_device],
dev=dev, lladdr=lladdr)
else:
linux_net.add_ip_rule(ip, routing_table[bridge_device])
except agent_exc.InvalidPortIP:
LOG.exception("Invalid IP to create a rule for port on the "
"provider network: %s", ip)
return False
linux_net.add_ip_route(routing_tables_routes, ip,
routing_table[bridge_device], bridge_device,
vlan=bridge_vlan)
# add proxy ndp config for ipv6
for n_cidr in proxy_cidrs:
if linux_net.get_ip_version(n_cidr) == constants.IP_VERSION_6:
linux_net.add_ndp_proxy(n_cidr, bridge_device, bridge_vlan)
# NOTE(ltomasbo): This is needed as the patch ports are not created
# until the first VM/FIP in that provider network is created in a node
try:
_ensure_updated_mac_tweak_flows(localnet, bridge_device, ovs_flows)
except agent_exc.PatchPortNotFound:
LOG.warning("Patch port %s for bridge %s not found. Not possible to "
"create the needed ovs flows for the outgoing traffic. "
"It will be retried at the resync.", localnet,
bridge_device)
return False
return True
def _wire_provider_port_ovn(ovn_idl, port_ips, mac):
cmds = []
port = "{}-openstack".format(constants.OVN_CLUSTER_ROUTER)
for port_ip in port_ips:
cmds.append(ovn_idl.static_mac_binding_add(
port, port_ip, mac, override_dynamic_mac=True, may_exist=True))
if cmds:
_execute_commands(ovn_idl, cmds)
# to keep it consisten with the underlay method
return True
def _unwire_provider_port_underlay(routing_tables_routes, port_ips,
bridge_device, bridge_vlan, routing_table,
proxy_cidrs, lladdr=None):
if not bridge_device:
return False
for ip in port_ips:
if lladdr:
if linux_net.get_ip_version(ip) == constants.IP_VERSION_6:
cr_lrp_ip = '{}/128'.format(ip)
else:
cr_lrp_ip = '{}/32'.format(ip)
try:
dev = bridge_device
if bridge_vlan:
dev = '{}.{}'.format(dev, bridge_vlan)
linux_net.del_ip_rule(cr_lrp_ip, routing_table[bridge_device],
dev=dev, lladdr=lladdr)
except agent_exc.InvalidPortIP:
LOG.exception("Invalid IP to delete a rule for the "
"provider port: %s", cr_lrp_ip)
return False
else:
try:
linux_net.del_ip_rule(ip, routing_table[bridge_device])
except agent_exc.InvalidPortIP:
LOG.exception("Invalid IP to delete a rule for the "
"provider port: %s", ip)
return False
linux_net.del_ip_route(routing_tables_routes, ip,
routing_table[bridge_device], bridge_device,
vlan=bridge_vlan)
for n_cidr in proxy_cidrs:
if linux_net.get_ip_version(n_cidr) == constants.IP_VERSION_6:
linux_net.del_ndp_proxy(n_cidr, bridge_device, bridge_vlan)
return True
def _unwire_provider_port_ovn(ovn_idl, port_ips):
cmds = []
port = "{}-openstack".format(constants.OVN_CLUSTER_ROUTER)
for port_ip in port_ips:
cmds.append(ovn_idl.static_mac_binding_del(
port, port_ip, if_exists=True))
if cmds:
_execute_commands(ovn_idl, cmds)
# to keep it consisten with the underlay method
return True
def wire_lrp_port(routing_tables_routes, ip, bridge_device, bridge_vlan,
routing_tables, cr_lrp_ips):
if CONF.exposing_method == constants.EXPOSE_METHOD_UNDERLAY:
return _wire_lrp_port_underlay(routing_tables_routes, ip,
bridge_device, bridge_vlan,
routing_tables, cr_lrp_ips)
elif CONF.exposing_method == constants.EXPOSE_METHOD_OVN:
# TODO(ltomasbo): Add flow on br-ex(-X)
# ovs-ofctl add-flow br-ex
# "cookie=0xbadcaf2,ip,nw_dst=20.0.0.0/24,in_port=enp2s0,priority=100,
# actions=mod_dl_dst:$ENP2S0_MAC,output=$patch"
# Add router route to go through cr-lrp ip:
# ovn-nbctl lr-route-add bgp-router 20.0.0.0/24 172.16.100.143
# bgp-router-public
return
def _wire_lrp_port_underlay(routing_tables_routes, ip, bridge_device,
bridge_vlan, routing_tables, cr_lrp_ips):
if not bridge_device:
return False
LOG.debug("Adding IP Rules for network %s", ip)
try:
linux_net.add_ip_rule(ip, routing_tables[bridge_device])
except agent_exc.InvalidPortIP:
LOG.exception("Invalid IP to create a rule for the lrp (network "
"router interface) port: %s", ip)
return False
LOG.debug("Added IP Rules for network %s", ip)
LOG.debug("Adding IP Routes for network %s", ip)
# NOTE(ltomasbo): This assumes the provider network can only have
# (at most) 2 subnets, one for IPv4, one for IPv6
ip_version = linux_net.get_ip_version(ip)
for cr_lrp_ip in cr_lrp_ips:
if linux_net.get_ip_version(cr_lrp_ip) == ip_version:
linux_net.add_ip_route(
routing_tables_routes,
ip.split("/")[0],
routing_tables[bridge_device],
bridge_device,
vlan=bridge_vlan,
mask=ip.split("/")[1],
via=cr_lrp_ip)
break
LOG.debug("Added IP Routes for network %s", ip)
return True
def unwire_lrp_port(routing_tables_routes, ip, bridge_device, bridge_vlan,
routing_tables, cr_lrp_ips):
if CONF.exposing_method == constants.EXPOSE_METHOD_UNDERLAY:
return _unwire_lrp_port_underlay(routing_tables_routes, ip,
bridge_device, bridge_vlan,
routing_tables, cr_lrp_ips)
elif CONF.exposing_method == constants.EXPOSE_METHOD_OVN:
# TODO(ltomasbo): Remove flow(s) and router route
return
def _unwire_lrp_port_underlay(routing_tables_routes, ip, bridge_device,
bridge_vlan, routing_tables, cr_lrp_ips):
if not bridge_device:
return False
LOG.debug("Deleting IP Rules for network %s", ip)
try:
linux_net.del_ip_rule(ip, routing_tables[bridge_device])
except agent_exc.InvalidPortIP:
LOG.exception("Invalid IP to delete a rule for the "
"lrp (network router interface) port: %s", ip)
return False
LOG.debug("Deleted IP Rules for network %s", ip)
LOG.debug("Deleting IP Routes for network %s", ip)
ip_version = linux_net.get_ip_version(ip)
for cr_lrp_ip in cr_lrp_ips:
if linux_net.get_ip_version(cr_lrp_ip) == ip_version:
linux_net.del_ip_route(
routing_tables_routes,
ip.split("/")[0],
routing_tables[bridge_device],
bridge_device,
vlan=bridge_vlan,
mask=ip.split("/")[1],
via=cr_lrp_ip)
LOG.debug("Deleted IP Routes for network %s", ip)
return True