NSXv: VDR interface operation performance
Change-Id: Ie36c6cbb8fc0a8055a8a3d84e8940b1c62fcba9e
This commit is contained in:
parent
e06238a2b4
commit
f11709dba5
33
vmware_nsx/common/profile.py
Normal file
33
vmware_nsx/common/profile.py
Normal file
@ -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
|
@ -150,19 +150,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(
|
||||
@ -197,22 +202,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):
|
||||
@ -255,8 +265,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)
|
||||
|
||||
|
@ -892,6 +892,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
profile_id = SLAAC_NDRA_PROFILE_ID
|
||||
|
||||
if delete:
|
||||
router_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 router_subnets
|
||||
@ -1624,7 +1626,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)
|
||||
@ -1966,8 +1968,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
self._validate_router_tz(context.elevated(), tier0_uuid, [subnet])
|
||||
|
||||
segment_id = self._get_network_nsx_segment_id(context, network_id)
|
||||
rtr_subnets = self._find_router_subnets(context.elevated(),
|
||||
router_id)
|
||||
rtr_subnets = self._load_router_subnet_cidrs_from_db(
|
||||
context.elevated(), router_id)
|
||||
if overlay_net:
|
||||
# overlay interface
|
||||
pol_subnets = []
|
||||
@ -2055,8 +2057,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)
|
||||
|
||||
rtr_subnets = self._find_router_subnets(context.elevated(),
|
||||
router_id)
|
||||
rtr_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)
|
||||
|
@ -2152,7 +2152,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)
|
||||
|
Loading…
Reference in New Issue
Block a user