NSXv: VDR interface operation performance
Change-Id: Ie36c6cbb8fc0a8055a8a3d84e8940b1c62fcba9e
This commit is contained in:
parent
a14b8a6f32
commit
625706119f
|
@ -0,0 +1,33 @@
|
|||
# Copyright 2019 VMware, 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 time
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def profile(func):
|
||||
def wrap(*args, **kwargs):
|
||||
f_name = '{}.{}'.format(func.__module__, func.__name__)
|
||||
|
||||
started_at = time.time()
|
||||
result = func(*args, **kwargs)
|
||||
LOG.debug(">>>>>>>>>>>>> Method %(method)s execution time %(time)f",
|
||||
{'method': f_name, 'time': time.time() - started_at})
|
||||
return result
|
||||
|
||||
return wrap
|
|
@ -116,8 +116,9 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
network = self.get_network(context, net_id)
|
||||
return network.get(ext_address_scope.IPV4_ADDRESS_SCOPE)
|
||||
|
||||
def _get_subnet_address_scope(self, context, subnet_id):
|
||||
subnet = self.get_subnet(context, subnet_id)
|
||||
def _get_subnet_address_scope(self, context, subnet_id, subnet=None):
|
||||
if not subnet:
|
||||
subnet = self.get_subnet(context, subnet_id)
|
||||
if not subnet['subnetpool_id']:
|
||||
return
|
||||
subnetpool = self.get_subnetpool(context, subnet['subnetpool_id'])
|
||||
|
@ -148,19 +149,24 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF]}
|
||||
return self.get_ports(context, filters=port_filters)
|
||||
|
||||
def _find_router_subnets_cidrs(self, context, router_id):
|
||||
def _find_router_subnets_cidrs(self, context, router_id, subnets=None):
|
||||
"""Retrieve cidrs of subnets attached to the specified router."""
|
||||
subnets = self._find_router_subnets(context, router_id)
|
||||
if not subnets:
|
||||
subnets = self._load_router_subnet_cidrs_from_db(context,
|
||||
router_id)
|
||||
return [subnet['cidr'] for subnet in subnets]
|
||||
|
||||
def _find_router_subnets_cidrs_per_addr_scope(self, context, router_id):
|
||||
def _find_router_subnets_cidrs_per_addr_scope(self, context, router_id,
|
||||
subnets=None):
|
||||
"""Generate a list of cidrs per address pool.
|
||||
|
||||
Go over all the router interface subnets.
|
||||
return a list of lists of subnets cidrs belonging to same
|
||||
address pool.
|
||||
"""
|
||||
subnets = self._find_router_subnets(context, router_id)
|
||||
if not subnets:
|
||||
subnets = self._load_router_subnet_cidrs_from_db(context,
|
||||
router_id)
|
||||
cidrs_map = {}
|
||||
for subnet in subnets:
|
||||
ads = self._get_subnetpool_address_scope(
|
||||
|
@ -195,22 +201,27 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
else:
|
||||
filters['id'] = [entry['port_id'] for entry in bindings]
|
||||
|
||||
def _find_router_subnets(self, context, router_id):
|
||||
def _load_router_subnet_cidrs_from_db(self, context, router_id):
|
||||
"""Retrieve subnets attached to the specified router."""
|
||||
ports = self._get_port_by_device_id(context, router_id,
|
||||
l3_db.DEVICE_OWNER_ROUTER_INTF)
|
||||
# No need to check for overlapping CIDRs
|
||||
subnets = []
|
||||
subnet_ids = []
|
||||
for port in ports:
|
||||
for ip in port.get('fixed_ips', []):
|
||||
subnet_qry = context.session.query(models_v2.Subnet)
|
||||
subnet = subnet_qry.filter_by(id=ip.subnet_id).one()
|
||||
subnets.append({'id': subnet.id, 'cidr': subnet.cidr,
|
||||
'subnetpool_id': subnet.subnetpool_id,
|
||||
'ip_version': subnet.ip_version,
|
||||
'network_id': subnet.network_id,
|
||||
'gateway_ip': subnet.gateway_ip,
|
||||
'ipv6_address_mode': subnet.ipv6_address_mode})
|
||||
subnet_ids.append(ip.subnet_id)
|
||||
|
||||
subnet_qry = context.session.query(models_v2.Subnet)
|
||||
db_subnets = subnet_qry.filter(
|
||||
models_v2.Subnet.id.in_(subnet_ids)).all()
|
||||
subnets = [{'id': subnet.id,
|
||||
'cidr': subnet.cidr,
|
||||
'subnetpool_id': subnet.subnetpool_id,
|
||||
'ip_version': subnet.ip_version,
|
||||
'network_id': subnet.network_id,
|
||||
'gateway_ip': subnet.gateway_ip,
|
||||
'ipv6_address_mode': subnet.ipv6_address_mode}
|
||||
for subnet in db_subnets]
|
||||
return subnets
|
||||
|
||||
def _find_router_gw_subnets(self, context, router):
|
||||
|
@ -253,8 +264,8 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
|
|||
LOG.info("Inspecting routers for potential configuration changes "
|
||||
"due to address scope change on subnetpool %s", subnetpool_id)
|
||||
for rtr in routers:
|
||||
subnets = self._find_router_subnets(elevated_context,
|
||||
rtr['id'])
|
||||
subnets = self._load_router_subnet_cidrs_from_db(elevated_context,
|
||||
rtr['id'])
|
||||
gw_subnets = self._find_router_gw_subnets(elevated_context,
|
||||
rtr)
|
||||
|
||||
|
|
|
@ -895,8 +895,9 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
profile_id = SLAAC_NDRA_PROFILE_ID
|
||||
|
||||
if delete:
|
||||
rtr_subnets = self._find_router_subnets(context.elevated(),
|
||||
router_id)
|
||||
|
||||
rtr_subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router_id)
|
||||
# check if there is another slaac overlay subnet that needs
|
||||
# advertising (vlan advertising is attached on interface level)
|
||||
slaac_subnets = [s for s in rtr_subnets
|
||||
|
@ -1618,7 +1619,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
orgaddr, orgmask, _orgnexthop = (
|
||||
self._get_external_attachment_info(
|
||||
context, router))
|
||||
router_subnets = self._find_router_subnets(
|
||||
router_subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router_id)
|
||||
self._validate_router_gw_and_tz(context, router_id, info,
|
||||
org_enable_snat, router_subnets)
|
||||
|
@ -1637,8 +1638,6 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
new_enable_snat = router.enable_snat
|
||||
newaddr, newmask, _newnexthop = self._get_external_attachment_info(
|
||||
context, router)
|
||||
router_subnets = self._find_router_subnets(
|
||||
context.elevated(), router_id)
|
||||
sr_currently_exists = self.verify_sr_at_backend(router_id)
|
||||
fw_exist = self._router_has_edge_fw_rules(context, router)
|
||||
# In this case the following operation must be executed regardless
|
||||
|
@ -1916,7 +1915,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
self._validate_interface_address_scope(context, router_db, info)
|
||||
|
||||
# Check GW & subnets TZ
|
||||
subnets = self._find_router_subnets(context.elevated(), router_id)
|
||||
subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router_id)
|
||||
tier0_uuid = self._get_tier0_uuid_by_router(
|
||||
context.elevated(), router_db)
|
||||
#TODO(asarfaty): it is enough to validate only the new subnet,
|
||||
|
@ -2013,8 +2013,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
|||
overlay_net = self._is_overlay_network(context, network_id)
|
||||
segment_id = self._get_network_nsx_segment_id(context, network_id)
|
||||
|
||||
subnets = self._find_router_subnets(context.elevated(),
|
||||
router_id)
|
||||
subnets = self._load_router_subnet_cidrs_from_db(context.elevated(),
|
||||
router_id)
|
||||
try:
|
||||
if overlay_net:
|
||||
# Remove the tier1 router from this segment on the NSX
|
||||
|
|
|
@ -3869,43 +3869,47 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
address_groups.append(address_group)
|
||||
return address_groups
|
||||
|
||||
def _get_nat_rules(self, context, router):
|
||||
def _get_dnat_rules(self, context, router):
|
||||
fip_qry = context.session.query(l3_db_models.FloatingIP)
|
||||
fip_db = fip_qry.filter_by(router_id=router['id']).all()
|
||||
|
||||
snat = []
|
||||
|
||||
dnat = [{'dst': fip.floating_ip_address,
|
||||
'translated': fip.fixed_ip_address}
|
||||
for fip in fip_db if fip.fixed_port_id]
|
||||
return dnat
|
||||
|
||||
def _get_nat_rules(self, context, router):
|
||||
snat = []
|
||||
|
||||
dnat = self._get_dnat_rules(context, router)
|
||||
|
||||
gw_port = router.gw_port
|
||||
if gw_port and gw_port.get('fixed_ips') and router.enable_snat:
|
||||
snat_ip = gw_port['fixed_ips'][0]['ip_address']
|
||||
subnets = self._find_router_subnets(context.elevated(),
|
||||
router['id'])
|
||||
for subnet in subnets:
|
||||
# Do not build NAT rules for v6
|
||||
if subnet.get('ip_version') == 6:
|
||||
continue
|
||||
# if the subnets address scope is the same as the gateways:
|
||||
# no need for SNAT
|
||||
gw_address_scope = self._get_network_address_scope(
|
||||
context.elevated(), gw_port['network_id'])
|
||||
subnet_address_scope = self._get_subnetpool_address_scope(
|
||||
context.elevated(), subnet['subnetpool_id'])
|
||||
if (gw_address_scope and
|
||||
gw_address_scope == subnet_address_scope):
|
||||
LOG.info("No need for SNAT rule for router %(router)s "
|
||||
"and subnet %(subnet)s because they use the "
|
||||
"same address scope %(addr_scope)s.",
|
||||
{'router': router['id'],
|
||||
'subnet': subnet['id'],
|
||||
'addr_scope': gw_address_scope})
|
||||
continue
|
||||
subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router['id'])
|
||||
gw_address_scope = self._get_network_address_scope(
|
||||
context.elevated(), gw_port['network_id'])
|
||||
if gw_address_scope:
|
||||
for subnet in subnets:
|
||||
# Do not build NAT rules for v6
|
||||
if subnet.get('ip_version') == 6:
|
||||
continue
|
||||
# if the subnets address scope is the same as the gateways:
|
||||
# no need for SNAT
|
||||
subnet_address_scope = self._get_subnetpool_address_scope(
|
||||
context.elevated(), subnet['subnetpool_id'])
|
||||
if gw_address_scope == subnet_address_scope:
|
||||
LOG.info("No need for SNAT rule for router %(router)s "
|
||||
"and subnet %(subnet)s because they use the "
|
||||
"same address scope %(addr_scope)s.",
|
||||
{'router': router['id'],
|
||||
'subnet': subnet['id'],
|
||||
'addr_scope': gw_address_scope})
|
||||
continue
|
||||
|
||||
snat.append(self._get_default_nat_rule(
|
||||
context, router['id'], subnet, snat_ip))
|
||||
snat.append(self._get_default_nat_rule(
|
||||
context, router['id'], subnet, snat_ip))
|
||||
return (snat, dnat)
|
||||
|
||||
def _get_default_nat_rule(self, context, router_id, subnet, snat_ip):
|
||||
|
@ -3921,13 +3925,14 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
rule['vnic_index'] = vcns_const.EXTERNAL_VNIC_INDEX
|
||||
return rule
|
||||
|
||||
def _get_nosnat_subnets_fw_rules(self, context, router):
|
||||
def _get_nosnat_subnets_fw_rules(self, context, router, subnets=None):
|
||||
"""Open edge firewall holes for nosnat subnets to do static routes."""
|
||||
no_snat_fw_rules = []
|
||||
gw_port = router.gw_port
|
||||
if gw_port and not router.enable_snat:
|
||||
subnet_cidrs = self._find_router_subnets_cidrs(context.elevated(),
|
||||
router['id'])
|
||||
router['id'],
|
||||
subnets)
|
||||
if subnet_cidrs:
|
||||
no_snat_fw_rules.append({
|
||||
'name': NO_SNAT_RULE_NAME,
|
||||
|
@ -3937,7 +3942,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
'destination_ip_address': subnet_cidrs})
|
||||
return no_snat_fw_rules
|
||||
|
||||
def _get_allocation_pools_fw_rule(self, context, router):
|
||||
def _get_allocation_pools_fw_rule(self, context, router, subnets=None):
|
||||
"""Get the firewall rule for the default gateway address pool
|
||||
|
||||
Return the firewall rule that should be added in order to allow
|
||||
|
@ -3953,8 +3958,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
if gw_address_scope is None:
|
||||
return
|
||||
|
||||
subnets = self._find_router_subnets(context.elevated(),
|
||||
router['id'])
|
||||
if not subnets:
|
||||
subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router['id'])
|
||||
no_nat_cidrs = []
|
||||
for subnet in subnets:
|
||||
# if the subnets address scope is the same as the gateways:
|
||||
|
@ -3973,7 +3979,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
|
||||
def _get_dnat_fw_rule(self, context, router):
|
||||
# Get FW rule to open dnat firewall flows
|
||||
_, dnat_rules = self._get_nat_rules(context, router)
|
||||
dnat_rules = self._get_dnat_rules(context, router)
|
||||
dnat_cidrs = [rule['dst'] for rule in dnat_rules]
|
||||
if dnat_cidrs:
|
||||
return {
|
||||
|
@ -3982,12 +3988,12 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
'enabled': True,
|
||||
'destination_ip_address': dnat_cidrs}
|
||||
|
||||
def _get_subnet_fw_rules(self, context, router):
|
||||
def _get_subnet_fw_rules(self, context, router, subnets=None):
|
||||
# Get FW rule/s to open subnets firewall flows and static routes
|
||||
# relative flows
|
||||
fw_rules = []
|
||||
subnet_cidrs_per_ads = self._find_router_subnets_cidrs_per_addr_scope(
|
||||
context.elevated(), router['id'])
|
||||
context.elevated(), router['id'], subnets=subnets)
|
||||
routes = self._get_extra_routes_by_router_id(context, router['id'])
|
||||
routes_dest = [route['destination'] for route in routes]
|
||||
for subnet_cidrs in subnet_cidrs_per_ads:
|
||||
|
@ -4244,7 +4250,10 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
|
||||
# Add FW rule/s to open subnets firewall flows and static routes
|
||||
# relative flows
|
||||
subnet_rules = self._get_subnet_fw_rules(context, router_db)
|
||||
subnets = self._load_router_subnet_cidrs_from_db(context.elevated(),
|
||||
router_id)
|
||||
subnet_rules = self._get_subnet_fw_rules(context, router_db,
|
||||
subnets=subnets)
|
||||
if subnet_rules:
|
||||
fw_rules.extend(subnet_rules)
|
||||
|
||||
|
@ -4271,13 +4280,13 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||
|
||||
# Add rule for not NAT-ed allocation pools
|
||||
alloc_pool_rule = self._get_allocation_pools_fw_rule(
|
||||
context, router_db)
|
||||
context, router_db, subnets=subnets)
|
||||
if alloc_pool_rule:
|
||||
fw_rules.append(alloc_pool_rule)
|
||||
|
||||
# Add no-snat rules
|
||||
nosnat_fw_rules = self._get_nosnat_subnets_fw_rules(
|
||||
context, router_db)
|
||||
context, router_db, subnets=subnets)
|
||||
fw_rules.extend(nosnat_fw_rules)
|
||||
|
||||
vpn_plugin = directory.get_plugin(plugin_const.VPN)
|
||||
|
|
|
@ -2170,7 +2170,7 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
|||
self._get_external_attachment_info(
|
||||
context, router))
|
||||
|
||||
router_subnets = self._find_router_subnets(
|
||||
router_subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router_id)
|
||||
self._validate_router_gw_and_tz(context, router_id, info,
|
||||
org_enable_snat, router_subnets)
|
||||
|
@ -2760,9 +2760,9 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
|||
resource_type = (None if overlay_net else
|
||||
nsxlib_consts.LROUTERPORT_CENTRALIZED)
|
||||
|
||||
# Check GW & subnets TZ
|
||||
subnets = self._find_router_subnets(context.elevated(),
|
||||
router_id)
|
||||
# If this is an ENS case - check GW & subnets
|
||||
subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router_id)
|
||||
tier0_uuid = self._get_tier0_uuid_by_router(context.elevated(),
|
||||
router_db)
|
||||
self._validate_router_tz(context.elevated(), tier0_uuid, subnets)
|
||||
|
|
|
@ -156,7 +156,8 @@ class EdgeLoadbalancerDriverV2(base_mgr.LoadbalancerBaseManager):
|
|||
|
||||
# Also check if there are any loadbalancers attached to this router
|
||||
# subnets
|
||||
router_subnets = self.loadbalancer.core_plugin._find_router_subnets(
|
||||
core_plugin = self.loadbalancer.core_plugin
|
||||
router_subnets = core_plugin._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router_id)
|
||||
subnet_ids = [subnet['id'] for subnet in router_subnets]
|
||||
if subnet_ids and self._get_lb_ports(context.elevated(), subnet_ids):
|
||||
|
|
Loading…
Reference in New Issue