Browse Source

NSXv: VDR interface operation performance

Change-Id: Ie36c6cbb8fc0a8055a8a3d84e8940b1c62fcba9e
changes/79/679079/1
Kobi Samoray 1 month ago
parent
commit
625706119f

+ 33
- 0
vmware_nsx/common/profile.py View File

@@ -0,0 +1,33 @@
1
+# Copyright 2019 VMware, Inc.
2
+# All Rights Reserved
3
+#
4
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+#    not use this file except in compliance with the License. You may obtain
6
+#    a copy of the License at
7
+#
8
+#         http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+#    Unless required by applicable law or agreed to in writing, software
11
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+#    License for the specific language governing permissions and limitations
14
+#    under the License.
15
+
16
+import time
17
+
18
+from oslo_log import log as logging
19
+
20
+LOG = logging.getLogger(__name__)
21
+
22
+
23
+def profile(func):
24
+    def wrap(*args, **kwargs):
25
+        f_name = '{}.{}'.format(func.__module__, func.__name__)
26
+
27
+        started_at = time.time()
28
+        result = func(*args, **kwargs)
29
+        LOG.debug(">>>>>>>>>>>>> Method %(method)s execution time %(time)f",
30
+                  {'method': f_name, 'time': time.time() - started_at})
31
+        return result
32
+
33
+    return wrap

+ 29
- 18
vmware_nsx/plugins/common/plugin.py View File

@@ -116,8 +116,9 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
116 116
         network = self.get_network(context, net_id)
117 117
         return network.get(ext_address_scope.IPV4_ADDRESS_SCOPE)
118 118
 
119
-    def _get_subnet_address_scope(self, context, subnet_id):
120
-        subnet = self.get_subnet(context, subnet_id)
119
+    def _get_subnet_address_scope(self, context, subnet_id, subnet=None):
120
+        if not subnet:
121
+            subnet = self.get_subnet(context, subnet_id)
121 122
         if not subnet['subnetpool_id']:
122 123
             return
123 124
         subnetpool = self.get_subnetpool(context, subnet['subnetpool_id'])
@@ -148,19 +149,24 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
148 149
                         'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF]}
149 150
         return self.get_ports(context, filters=port_filters)
150 151
 
151
-    def _find_router_subnets_cidrs(self, context, router_id):
152
+    def _find_router_subnets_cidrs(self, context, router_id, subnets=None):
152 153
         """Retrieve cidrs of subnets attached to the specified router."""
153
-        subnets = self._find_router_subnets(context, router_id)
154
+        if not subnets:
155
+            subnets = self._load_router_subnet_cidrs_from_db(context,
156
+                                                             router_id)
154 157
         return [subnet['cidr'] for subnet in subnets]
155 158
 
156
-    def _find_router_subnets_cidrs_per_addr_scope(self, context, router_id):
159
+    def _find_router_subnets_cidrs_per_addr_scope(self, context, router_id,
160
+                                                  subnets=None):
157 161
         """Generate a list of cidrs per address pool.
158 162
 
159 163
         Go over all the router interface subnets.
160 164
         return a list of lists of subnets cidrs belonging to same
161 165
         address pool.
162 166
         """
163
-        subnets = self._find_router_subnets(context, router_id)
167
+        if not subnets:
168
+            subnets = self._load_router_subnet_cidrs_from_db(context,
169
+                                                             router_id)
164 170
         cidrs_map = {}
165 171
         for subnet in subnets:
166 172
             ads = self._get_subnetpool_address_scope(
@@ -195,22 +201,27 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
195 201
                 else:
196 202
                     filters['id'] = [entry['port_id'] for entry in bindings]
197 203
 
198
-    def _find_router_subnets(self, context, router_id):
204
+    def _load_router_subnet_cidrs_from_db(self, context, router_id):
199 205
         """Retrieve subnets attached to the specified router."""
200 206
         ports = self._get_port_by_device_id(context, router_id,
201 207
                                             l3_db.DEVICE_OWNER_ROUTER_INTF)
202 208
         # No need to check for overlapping CIDRs
203
-        subnets = []
209
+        subnet_ids = []
204 210
         for port in ports:
205 211
             for ip in port.get('fixed_ips', []):
206
-                subnet_qry = context.session.query(models_v2.Subnet)
207
-                subnet = subnet_qry.filter_by(id=ip.subnet_id).one()
208
-                subnets.append({'id': subnet.id, 'cidr': subnet.cidr,
209
-                                'subnetpool_id': subnet.subnetpool_id,
210
-                                'ip_version': subnet.ip_version,
211
-                                'network_id': subnet.network_id,
212
-                                'gateway_ip': subnet.gateway_ip,
213
-                                'ipv6_address_mode': subnet.ipv6_address_mode})
212
+                subnet_ids.append(ip.subnet_id)
213
+
214
+        subnet_qry = context.session.query(models_v2.Subnet)
215
+        db_subnets = subnet_qry.filter(
216
+            models_v2.Subnet.id.in_(subnet_ids)).all()
217
+        subnets = [{'id': subnet.id,
218
+                    'cidr': subnet.cidr,
219
+                    'subnetpool_id': subnet.subnetpool_id,
220
+                    'ip_version': subnet.ip_version,
221
+                    'network_id': subnet.network_id,
222
+                    'gateway_ip': subnet.gateway_ip,
223
+                    'ipv6_address_mode': subnet.ipv6_address_mode}
224
+                   for subnet in db_subnets]
214 225
         return subnets
215 226
 
216 227
     def _find_router_gw_subnets(self, context, router):
@@ -253,8 +264,8 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
253 264
         LOG.info("Inspecting routers for potential configuration changes "
254 265
                  "due to address scope change on subnetpool %s", subnetpool_id)
255 266
         for rtr in routers:
256
-            subnets = self._find_router_subnets(elevated_context,
257
-                                                rtr['id'])
267
+            subnets = self._load_router_subnet_cidrs_from_db(elevated_context,
268
+                                                             rtr['id'])
258 269
             gw_subnets = self._find_router_gw_subnets(elevated_context,
259 270
                                                       rtr)
260 271
 

+ 8
- 8
vmware_nsx/plugins/nsx_p/plugin.py View File

@@ -895,8 +895,9 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
895 895
             profile_id = SLAAC_NDRA_PROFILE_ID
896 896
 
897 897
         if delete:
898
-            rtr_subnets = self._find_router_subnets(context.elevated(),
899
-                                                    router_id)
898
+
899
+            rtr_subnets = self._load_router_subnet_cidrs_from_db(
900
+                context.elevated(), router_id)
900 901
             # check if there is another slaac overlay subnet that needs
901 902
             # advertising (vlan advertising is attached on interface level)
902 903
             slaac_subnets = [s for s in rtr_subnets
@@ -1618,7 +1619,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
1618 1619
         orgaddr, orgmask, _orgnexthop = (
1619 1620
             self._get_external_attachment_info(
1620 1621
                 context, router))
1621
-        router_subnets = self._find_router_subnets(
1622
+        router_subnets = self._load_router_subnet_cidrs_from_db(
1622 1623
             context.elevated(), router_id)
1623 1624
         self._validate_router_gw_and_tz(context, router_id, info,
1624 1625
                                         org_enable_snat, router_subnets)
@@ -1637,8 +1638,6 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
1637 1638
         new_enable_snat = router.enable_snat
1638 1639
         newaddr, newmask, _newnexthop = self._get_external_attachment_info(
1639 1640
             context, router)
1640
-        router_subnets = self._find_router_subnets(
1641
-            context.elevated(), router_id)
1642 1641
         sr_currently_exists = self.verify_sr_at_backend(router_id)
1643 1642
         fw_exist = self._router_has_edge_fw_rules(context, router)
1644 1643
         # In this case the following operation must be executed regardless
@@ -1916,7 +1915,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
1916 1915
             self._validate_interface_address_scope(context, router_db, info)
1917 1916
 
1918 1917
             # Check GW & subnets TZ
1919
-            subnets = self._find_router_subnets(context.elevated(), router_id)
1918
+            subnets = self._load_router_subnet_cidrs_from_db(
1919
+                context.elevated(), router_id)
1920 1920
             tier0_uuid = self._get_tier0_uuid_by_router(
1921 1921
                 context.elevated(), router_db)
1922 1922
             #TODO(asarfaty): it is enough to validate only the new subnet,
@@ -2013,8 +2013,8 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
2013 2013
         overlay_net = self._is_overlay_network(context, network_id)
2014 2014
         segment_id = self._get_network_nsx_segment_id(context, network_id)
2015 2015
 
2016
-        subnets = self._find_router_subnets(context.elevated(),
2017
-                                            router_id)
2016
+        subnets = self._load_router_subnet_cidrs_from_db(context.elevated(),
2017
+                                                         router_id)
2018 2018
         try:
2019 2019
             if overlay_net:
2020 2020
                 # Remove the tier1 router from this segment on the NSX

+ 47
- 38
vmware_nsx/plugins/nsx_v/plugin.py View File

@@ -3869,43 +3869,47 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
3869 3869
             address_groups.append(address_group)
3870 3870
         return address_groups
3871 3871
 
3872
-    def _get_nat_rules(self, context, router):
3872
+    def _get_dnat_rules(self, context, router):
3873 3873
         fip_qry = context.session.query(l3_db_models.FloatingIP)
3874 3874
         fip_db = fip_qry.filter_by(router_id=router['id']).all()
3875 3875
 
3876
-        snat = []
3877
-
3878 3876
         dnat = [{'dst': fip.floating_ip_address,
3879 3877
                  'translated': fip.fixed_ip_address}
3880 3878
                 for fip in fip_db if fip.fixed_port_id]
3879
+        return dnat
3880
+
3881
+    def _get_nat_rules(self, context, router):
3882
+        snat = []
3883
+
3884
+        dnat = self._get_dnat_rules(context, router)
3881 3885
 
3882 3886
         gw_port = router.gw_port
3883 3887
         if gw_port and gw_port.get('fixed_ips') and router.enable_snat:
3884 3888
             snat_ip = gw_port['fixed_ips'][0]['ip_address']
3885
-            subnets = self._find_router_subnets(context.elevated(),
3886
-                                                router['id'])
3887
-            for subnet in subnets:
3888
-                # Do not build NAT rules for v6
3889
-                if subnet.get('ip_version') == 6:
3890
-                    continue
3891
-                # if the subnets address scope is the same as the gateways:
3892
-                # no need for SNAT
3893
-                gw_address_scope = self._get_network_address_scope(
3894
-                    context.elevated(), gw_port['network_id'])
3895
-                subnet_address_scope = self._get_subnetpool_address_scope(
3896
-                    context.elevated(), subnet['subnetpool_id'])
3897
-                if (gw_address_scope and
3898
-                    gw_address_scope == subnet_address_scope):
3899
-                    LOG.info("No need for SNAT rule for router %(router)s "
3900
-                             "and subnet %(subnet)s because they use the "
3901
-                             "same address scope %(addr_scope)s.",
3902
-                             {'router': router['id'],
3903
-                              'subnet': subnet['id'],
3904
-                              'addr_scope': gw_address_scope})
3905
-                    continue
3906
-
3907
-                snat.append(self._get_default_nat_rule(
3908
-                    context, router['id'], subnet, snat_ip))
3889
+            subnets = self._load_router_subnet_cidrs_from_db(
3890
+                context.elevated(), router['id'])
3891
+            gw_address_scope = self._get_network_address_scope(
3892
+                context.elevated(), gw_port['network_id'])
3893
+            if gw_address_scope:
3894
+                for subnet in subnets:
3895
+                    # Do not build NAT rules for v6
3896
+                    if subnet.get('ip_version') == 6:
3897
+                        continue
3898
+                    # if the subnets address scope is the same as the gateways:
3899
+                    # no need for SNAT
3900
+                    subnet_address_scope = self._get_subnetpool_address_scope(
3901
+                        context.elevated(), subnet['subnetpool_id'])
3902
+                    if gw_address_scope == subnet_address_scope:
3903
+                        LOG.info("No need for SNAT rule for router %(router)s "
3904
+                                 "and subnet %(subnet)s because they use the "
3905
+                                 "same address scope %(addr_scope)s.",
3906
+                                 {'router': router['id'],
3907
+                                  'subnet': subnet['id'],
3908
+                                  'addr_scope': gw_address_scope})
3909
+                        continue
3910
+
3911
+                    snat.append(self._get_default_nat_rule(
3912
+                        context, router['id'], subnet, snat_ip))
3909 3913
         return (snat, dnat)
3910 3914
 
3911 3915
     def _get_default_nat_rule(self, context, router_id, subnet, snat_ip):
@@ -3921,13 +3925,14 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
3921 3925
             rule['vnic_index'] = vcns_const.EXTERNAL_VNIC_INDEX
3922 3926
         return rule
3923 3927
 
3924
-    def _get_nosnat_subnets_fw_rules(self, context, router):
3928
+    def _get_nosnat_subnets_fw_rules(self, context, router, subnets=None):
3925 3929
         """Open edge firewall holes for nosnat subnets to do static routes."""
3926 3930
         no_snat_fw_rules = []
3927 3931
         gw_port = router.gw_port
3928 3932
         if gw_port and not router.enable_snat:
3929 3933
             subnet_cidrs = self._find_router_subnets_cidrs(context.elevated(),
3930
-                                                           router['id'])
3934
+                                                           router['id'],
3935
+                                                           subnets)
3931 3936
             if subnet_cidrs:
3932 3937
                 no_snat_fw_rules.append({
3933 3938
                     'name': NO_SNAT_RULE_NAME,
@@ -3937,7 +3942,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
3937 3942
                     'destination_ip_address': subnet_cidrs})
3938 3943
         return no_snat_fw_rules
3939 3944
 
3940
-    def _get_allocation_pools_fw_rule(self, context, router):
3945
+    def _get_allocation_pools_fw_rule(self, context, router, subnets=None):
3941 3946
         """Get the firewall rule for the default gateway address pool
3942 3947
 
3943 3948
         Return the firewall rule that should be added in order to allow
@@ -3953,8 +3958,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
3953 3958
         if gw_address_scope is None:
3954 3959
             return
3955 3960
 
3956
-        subnets = self._find_router_subnets(context.elevated(),
3957
-                                            router['id'])
3961
+        if not subnets:
3962
+            subnets = self._load_router_subnet_cidrs_from_db(
3963
+                context.elevated(), router['id'])
3958 3964
         no_nat_cidrs = []
3959 3965
         for subnet in subnets:
3960 3966
             # if the subnets address scope is the same as the gateways:
@@ -3973,7 +3979,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
3973 3979
 
3974 3980
     def _get_dnat_fw_rule(self, context, router):
3975 3981
         # Get FW rule to open dnat firewall flows
3976
-        _, dnat_rules = self._get_nat_rules(context, router)
3982
+        dnat_rules = self._get_dnat_rules(context, router)
3977 3983
         dnat_cidrs = [rule['dst'] for rule in dnat_rules]
3978 3984
         if dnat_cidrs:
3979 3985
             return {
@@ -3982,12 +3988,12 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
3982 3988
                 'enabled': True,
3983 3989
                 'destination_ip_address': dnat_cidrs}
3984 3990
 
3985
-    def _get_subnet_fw_rules(self, context, router):
3991
+    def _get_subnet_fw_rules(self, context, router, subnets=None):
3986 3992
         # Get FW rule/s to open subnets firewall flows and static routes
3987 3993
         # relative flows
3988 3994
         fw_rules = []
3989 3995
         subnet_cidrs_per_ads = self._find_router_subnets_cidrs_per_addr_scope(
3990
-            context.elevated(), router['id'])
3996
+            context.elevated(), router['id'], subnets=subnets)
3991 3997
         routes = self._get_extra_routes_by_router_id(context, router['id'])
3992 3998
         routes_dest = [route['destination'] for route in routes]
3993 3999
         for subnet_cidrs in subnet_cidrs_per_ads:
@@ -4244,7 +4250,10 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
4244 4250
 
4245 4251
         # Add FW rule/s to open subnets firewall flows and static routes
4246 4252
         # relative flows
4247
-        subnet_rules = self._get_subnet_fw_rules(context, router_db)
4253
+        subnets = self._load_router_subnet_cidrs_from_db(context.elevated(),
4254
+                                                         router_id)
4255
+        subnet_rules = self._get_subnet_fw_rules(context, router_db,
4256
+                                                 subnets=subnets)
4248 4257
         if subnet_rules:
4249 4258
             fw_rules.extend(subnet_rules)
4250 4259
 
@@ -4271,13 +4280,13 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
4271 4280
 
4272 4281
         # Add rule for not NAT-ed allocation pools
4273 4282
         alloc_pool_rule = self._get_allocation_pools_fw_rule(
4274
-            context, router_db)
4283
+            context, router_db, subnets=subnets)
4275 4284
         if alloc_pool_rule:
4276 4285
             fw_rules.append(alloc_pool_rule)
4277 4286
 
4278 4287
         # Add no-snat rules
4279 4288
         nosnat_fw_rules = self._get_nosnat_subnets_fw_rules(
4280
-            context, router_db)
4289
+            context, router_db, subnets=subnets)
4281 4290
         fw_rules.extend(nosnat_fw_rules)
4282 4291
 
4283 4292
         vpn_plugin = directory.get_plugin(plugin_const.VPN)

+ 4
- 4
vmware_nsx/plugins/nsx_v3/plugin.py View File

@@ -2170,7 +2170,7 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
2170 2170
             self._get_external_attachment_info(
2171 2171
                 context, router))
2172 2172
 
2173
-        router_subnets = self._find_router_subnets(
2173
+        router_subnets = self._load_router_subnet_cidrs_from_db(
2174 2174
             context.elevated(), router_id)
2175 2175
         self._validate_router_gw_and_tz(context, router_id, info,
2176 2176
                                         org_enable_snat, router_subnets)
@@ -2760,9 +2760,9 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
2760 2760
             resource_type = (None if overlay_net else
2761 2761
                              nsxlib_consts.LROUTERPORT_CENTRALIZED)
2762 2762
 
2763
-            # Check GW & subnets TZ
2764
-            subnets = self._find_router_subnets(context.elevated(),
2765
-                                                router_id)
2763
+            # If this is an ENS case - check GW & subnets
2764
+            subnets = self._load_router_subnet_cidrs_from_db(
2765
+                context.elevated(), router_id)
2766 2766
             tier0_uuid = self._get_tier0_uuid_by_router(context.elevated(),
2767 2767
                                                         router_db)
2768 2768
             self._validate_router_tz(context.elevated(), tier0_uuid, subnets)

+ 2
- 1
vmware_nsx/services/lbaas/nsx_v3/v2/lb_driver_v2.py View File

@@ -156,7 +156,8 @@ class EdgeLoadbalancerDriverV2(base_mgr.LoadbalancerBaseManager):
156 156
 
157 157
         # Also check if there are any loadbalancers attached to this router
158 158
         # subnets
159
-        router_subnets = self.loadbalancer.core_plugin._find_router_subnets(
159
+        core_plugin = self.loadbalancer.core_plugin
160
+        router_subnets = core_plugin._load_router_subnet_cidrs_from_db(
160 161
             context.elevated(), router_id)
161 162
         subnet_ids = [subnet['id'] for subnet in router_subnets]
162 163
         if subnet_ids and self._get_lb_ports(context.elevated(), subnet_ids):

Loading…
Cancel
Save