Merge "Unset "router:external" in subnet tests"
diff --git a/neutron_tempest_plugin/api/admin/test_ports.py b/neutron_tempest_plugin/api/admin/test_ports.py
index e26e122..88c35c6 100644
--- a/neutron_tempest_plugin/api/admin/test_ports.py
+++ b/neutron_tempest_plugin/api/admin/test_ports.py
@@ -65,6 +65,42 @@
         self.assertNotEqual(current_mac, new_mac)
         self.assertTrue(netaddr.valid_mac(new_mac))
 
+    @decorators.idempotent_id('4d75cc60-99d0-4949-b3ce-5826b81aa0a9')
+    @utils.requires_ext(extension="port-trusted-vif",
+                        service="network")
+    def test_port_create_with_trusted_attr_set(self):
+        port = self.admin_client.create_port(
+            network_id=self.network['id'], trusted=True)['port']
+        self.ports.append(port)
+        self.assertTrue(port['trusted'])
+        self.assertTrue(port['binding:profile']['trusted'])
+
+        port = self.admin_client.create_port(
+            network_id=self.network['id'], trusted=False)['port']
+        self.ports.append(port)
+        self.assertFalse(port['trusted'])
+        self.assertFalse(port['binding:profile']['trusted'])
+
+    @decorators.idempotent_id('26c15e2a-55b2-410f-8ed3-84db9406ff3f')
+    @utils.requires_ext(extension="port-trusted-vif",
+                        service="network")
+    def test_port_set_trusted_attr(self):
+        port = self.admin_client.create_port(
+            network_id=self.network['id'])['port']
+        self.ports.append(port)
+        self.assertIsNone(port['trusted'])
+        self.assertNotIn('trusted', port['binding:profile'])
+
+        updated_port = self.admin_client.update_port(
+            port['id'], trusted=True)['port']
+        self.assertTrue(updated_port['trusted'])
+        self.assertTrue(updated_port['binding:profile']['trusted'])
+
+        updated_port = self.admin_client.update_port(
+            port['id'], trusted=False)['port']
+        self.assertFalse(updated_port['trusted'])
+        self.assertFalse(updated_port['binding:profile']['trusted'])
+
 
 class PortTestCasesResourceRequest(base.BaseAdminNetworkTest):
 
diff --git a/neutron_tempest_plugin/api/admin/test_quotas.py b/neutron_tempest_plugin/api/admin/test_quotas.py
index 0cf474e..eb47fa5 100644
--- a/neutron_tempest_plugin/api/admin/test_quotas.py
+++ b/neutron_tempest_plugin/api/admin/test_quotas.py
@@ -87,7 +87,7 @@
         new_quotas = {'network': 0, 'security_group': 0}
 
         # Change quotas for tenant
-        quota_set = self._setup_quotas(tenant_id, **new_quotas)
+        quota_set = self._setup_quotas(tenant_id, force=True, **new_quotas)
         for key, value in new_quotas.items():
             self.assertEqual(value, quota_set[key])
 
@@ -112,6 +112,23 @@
         for q in non_default_quotas['quotas']:
             self.assertNotEqual(tenant_id, q['tenant_id'])
 
+    @decorators.idempotent_id('43d01327-d8be-4773-a8f0-1d2e9664fda2')
+    @decorators.attr(type='gate')
+    @utils.requires_ext(extension='quota-check-limit-default',
+                        service='network')
+    def test_quotas_force_false(self):
+        project_id = self.create_project()['id']
+        self._create_network(project_id)
+
+        new_quotas = {'network': 0}
+        # force=false (by default)
+        self.assertRaises(lib_exc.BadRequest, self.admin_client.update_quotas,
+                          project_id, **new_quotas)
+
+        new_quotas['network'] = 100
+        quota_set = self._setup_quotas(project_id, **new_quotas)
+        self.assertEqual(new_quotas['network'], quota_set['network'])
+
     @decorators.idempotent_id('e974b5ba-090a-452c-a578-f9710151d9fc')
     @decorators.attr(type='gate')
     @utils.requires_ext(extension="quota_details", service="network")
diff --git a/neutron_tempest_plugin/api/admin/test_tag.py b/neutron_tempest_plugin/api/admin/test_tag.py
index eae7977..31b2b96 100644
--- a/neutron_tempest_plugin/api/admin/test_tag.py
+++ b/neutron_tempest_plugin/api/admin/test_tag.py
@@ -26,53 +26,55 @@
         super(TagTestJSON, cls).resource_setup()
         cls.res_id = cls._create_resource()
 
-    def _get_and_compare_tags(self, tags):
-        res_body = self.client.get_tags(self.resource, self.res_id)
+    def _get_and_compare_tags(self, tags, client):
+        res_body = client.get_tags(self.resource, self.res_id)
         self.assertCountEqual(tags, res_body['tags'])
 
-    def _test_tag_operations(self):
+    def _test_tag_operations(self, client=None):
+        client = client or self.client
         # create and get tags
         tags = ['red', 'blue']
-        res_body = self.client.update_tags(self.resource, self.res_id, tags)
+        res_body = client.update_tags(self.resource, self.res_id, tags)
         self.assertCountEqual(tags, res_body['tags'])
-        self._get_and_compare_tags(tags)
+        self._get_and_compare_tags(tags, client)
 
         # add a tag
-        self.client.update_tag(self.resource, self.res_id, 'green')
-        self._get_and_compare_tags(['red', 'blue', 'green'])
+        client.update_tag(self.resource, self.res_id, 'green')
+        self._get_and_compare_tags(['red', 'blue', 'green'], client)
 
         # update tag exist
-        self.client.update_tag(self.resource, self.res_id, 'red')
-        self._get_and_compare_tags(['red', 'blue', 'green'])
+        client.update_tag(self.resource, self.res_id, 'red')
+        self._get_and_compare_tags(['red', 'blue', 'green'], client)
 
         # add a tag with a dot
-        self.client.update_tag(self.resource, self.res_id, 'black.or.white')
-        self._get_and_compare_tags(['red', 'blue', 'green', 'black.or.white'])
+        client.update_tag(self.resource, self.res_id, 'black.or.white')
+        self._get_and_compare_tags(['red', 'blue', 'green', 'black.or.white'],
+                                   client)
 
         # replace tags
         tags = ['red', 'yellow', 'purple']
-        res_body = self.client.update_tags(self.resource, self.res_id, tags)
+        res_body = client.update_tags(self.resource, self.res_id, tags)
         self.assertCountEqual(tags, res_body['tags'])
-        self._get_and_compare_tags(tags)
+        self._get_and_compare_tags(tags, client)
 
         # get tag
-        self.client.get_tag(self.resource, self.res_id, 'red')
+        client.get_tag(self.resource, self.res_id, 'red')
 
         # get tag not exist
-        self.assertRaises(lib_exc.NotFound, self.client.get_tag,
+        self.assertRaises(lib_exc.NotFound, client.get_tag,
                           self.resource, self.res_id, 'green')
 
         # delete tag
-        self.client.delete_tag(self.resource, self.res_id, 'red')
-        self._get_and_compare_tags(['yellow', 'purple'])
+        client.delete_tag(self.resource, self.res_id, 'red')
+        self._get_and_compare_tags(['yellow', 'purple'], client)
 
         # delete tag not exist
-        self.assertRaises(lib_exc.NotFound, self.client.delete_tag,
+        self.assertRaises(lib_exc.NotFound, client.delete_tag,
                           self.resource, self.res_id, 'green')
 
         # delete tags
-        self.client.delete_tags(self.resource, self.res_id)
-        self._get_and_compare_tags([])
+        client.delete_tags(self.resource, self.res_id)
+        self._get_and_compare_tags([], client)
 
 
 class TagNetworkTestJSON(TagTestJSON):
@@ -198,7 +200,7 @@
     @decorators.idempotent_id('e9bac15e-c8bc-4317-8295-4bf1d8d522b8')
     @utils.requires_ext(extension="standard-attr-tag", service="network")
     def test_qos_policy_tags(self):
-        self._test_tag_operations()
+        self._test_tag_operations(client=self.admin_client)
 
 
 class TagTrunkTestJSON(TagTestJSON):
@@ -225,16 +227,20 @@
     @classmethod
     def resource_setup(cls):
         super(TagFilterTestJSON, cls).resource_setup()
+        try:
+            client = cls.tag_client
+        except AttributeError:
+            client = cls.client
 
         cls.res_ids = []
         for i in range(5):
             cls.res_ids.append(cls._create_resource())
 
-        cls.client.update_tags(cls.resource, cls.res_ids[0], ['red'])
-        cls.client.update_tags(cls.resource, cls.res_ids[1], ['red', 'blue'])
-        cls.client.update_tags(cls.resource, cls.res_ids[2],
-                               ['red', 'blue', 'green'])
-        cls.client.update_tags(cls.resource, cls.res_ids[3], ['green'])
+        client.update_tags(cls.resource, cls.res_ids[0], ['red'])
+        client.update_tags(cls.resource, cls.res_ids[1], ['red', 'blue'])
+        client.update_tags(cls.resource, cls.res_ids[2],
+                           ['red', 'blue', 'green'])
+        client.update_tags(cls.resource, cls.res_ids[3], ['green'])
         # 5th resource: no tags
 
     @classmethod
@@ -441,6 +447,11 @@
         res = self.client.list_qos_policies(**filters)
         return res[self.resource]
 
+    @classmethod
+    def resource_setup(cls):
+        cls.tag_client = cls.admin_client
+        super().resource_setup()
+
     @decorators.attr(type='smoke')
     @decorators.idempotent_id('c2f9a6ae-2529-4cb9-a44b-b16f8ba27832')
     @utils.requires_ext(extension="standard-attr-tag", service="network")
diff --git a/neutron_tempest_plugin/api/base.py b/neutron_tempest_plugin/api/base.py
index 99fa946..4bcc6d2 100644
--- a/neutron_tempest_plugin/api/base.py
+++ b/neutron_tempest_plugin/api/base.py
@@ -595,15 +595,11 @@
             # Generate subnet CIDRs starting from configured values
             ip_version = ip_version or cls._ip_version
             if ip_version == const.IP_VERSION_4:
-                mask_bits = mask_bits or config.safe_get_config_value(
-                    'network', 'project_network_mask_bits')
-                cidr = netaddr.IPNetwork(config.safe_get_config_value(
-                    'network', 'project_network_cidr'))
+                mask_bits = mask_bits or CONF.network.project_network_mask_bits
+                cidr = netaddr.IPNetwork(CONF.network.project_network_cidr)
             elif ip_version == const.IP_VERSION_6:
-                mask_bits = config.safe_get_config_value(
-                    'network', 'project_network_v6_mask_bits')
-                cidr = netaddr.IPNetwork(config.safe_get_config_value(
-                    'network', 'project_network_v6_cidr'))
+                mask_bits = CONF.network.project_network_v6_mask_bits
+                cidr = netaddr.IPNetwork(CONF.network.project_network_v6_cidr)
             else:
                 raise ValueError('Invalid IP version: {!r}'.format(ip_version))
 
@@ -1466,6 +1462,10 @@
     def _extract_resources(cls, body):
         return body[cls.plural_name]
 
+    @classmethod
+    def _test_resources(cls, resources):
+        return [res for res in resources if res["name"] in cls.resource_names]
+
     def _test_list_sorts(self, direction):
         sort_args = {
             'sort_dir': direction,
@@ -1517,11 +1517,12 @@
             'sort_key': self.field
         }
         body = self.list_method(**sort_args)
-        expected_resources = self._extract_resources(body)
+        total_resources = self._extract_resources(body)
+        expected_resources = self._test_resources(total_resources)
         self.assertNotEmpty(expected_resources)
 
         resources = lister(
-            len(expected_resources), sort_args
+            len(total_resources), sort_args
         )
 
         # finally, compare that the list retrieved in one go is identical to
@@ -1539,9 +1540,11 @@
                 pagination_args['marker'] = resources[-1]['id']
             body = self.list_method(**pagination_args)
             resources_ = self._extract_resources(body)
-            self.assertEqual(1, len(resources_))
+            # Empty resource list can be returned when any concurrent
+            # tests delete them
+            self.assertGreaterEqual(1, len(resources_))
             resources.extend(resources_)
-        return resources
+        return self._test_resources(resources)
 
     @_require_pagination
     @_require_sorting
@@ -1564,8 +1567,10 @@
                 self.plural_name, uri
             )
             resources_ = self._extract_resources(body)
-            self.assertEqual(1, len(resources_))
-            resources.extend(resources_)
+            # Empty resource list can be returned when any concurrent
+            # tests delete them
+            self.assertGreaterEqual(1, len(resources_))
+            resources.extend(self._test_resources(resources_))
 
         # The last element is empty and does not contain 'next' link
         uri = self.get_bare_url(prev_links['next'])
@@ -1582,8 +1587,10 @@
                 self.plural_name, uri
             )
             resources_ = self._extract_resources(body)
-            self.assertEqual(1, len(resources_))
-            resources2.extend(resources_)
+            # Empty resource list can be returned when any concurrent
+            # tests delete them
+            self.assertGreaterEqual(1, len(resources_))
+            resources2.extend(self._test_resources(resources_))
 
         self.assertSameOrder(resources, reversed(resources2))
 
@@ -1603,14 +1610,15 @@
             'sort_key': self.field,
         }
         body = self.list_method(**pagination_args)
-        expected_resources = self._extract_resources(body)
+        total_resources = self._extract_resources(body)
+        expected_resources = self._test_resources(total_resources)
 
         page_size = 2
         pagination_args['limit'] = page_size
 
         prev_links = {}
         resources = []
-        num_resources = len(expected_resources)
+        num_resources = len(total_resources)
         niterations = int(math.ceil(float(num_resources) / page_size))
         for i in range(niterations):
             if prev_links:
@@ -1622,7 +1630,7 @@
             prev_links, body = self.list_client.get_uri_with_links(
                 self.plural_name, uri
             )
-            resources_ = self._extract_resources(body)
+            resources_ = self._test_resources(self._extract_resources(body))
             self.assertGreaterEqual(page_size, len(resources_))
             resources.extend(reversed(resources_))
 
diff --git a/neutron_tempest_plugin/api/base_routers.py b/neutron_tempest_plugin/api/base_routers.py
index 94db116..37a84b8 100644
--- a/neutron_tempest_plugin/api/base_routers.py
+++ b/neutron_tempest_plugin/api/base_routers.py
@@ -31,10 +31,14 @@
             pass
 
     def _create_router(self, name, admin_state_up=False,
-                       external_network_id=None, enable_snat=None, **kwargs):
+                       external_network_id=None, enable_snat=None,
+                       client=None, **kwargs):
         # associate a cleanup with created routers to avoid quota limits
-        router = self.create_router(name, admin_state_up,
-                                    external_network_id, enable_snat, **kwargs)
+        client = client or self.client
+        router = self._create_router_with_client(
+            client, router_name=name, admin_state_up=admin_state_up,
+            external_network_id=external_network_id, enable_snat=enable_snat,
+            **kwargs)
         self.addCleanup(self._cleanup_router, router)
         return router
 
diff --git a/neutron_tempest_plugin/api/test_routers.py b/neutron_tempest_plugin/api/test_routers.py
index 7758b1a..1470a7b 100644
--- a/neutron_tempest_plugin/api/test_routers.py
+++ b/neutron_tempest_plugin/api/test_routers.py
@@ -38,9 +38,9 @@
     def resource_setup(cls):
         super(RoutersTest, cls).resource_setup()
         cls.tenant_cidr = (
-            config.safe_get_config_value('network', 'project_network_cidr')
+            CONF.network.project_network_cidr
             if cls._ip_version == 4 else
-            config.safe_get_config_value('network', 'project_network_v6_cidr'))
+            CONF.network.project_network_v6_cidr)
 
     @decorators.idempotent_id('c72c1c0c-2193-4aca-eeee-b1442640eeee')
     @tutils.requires_ext(extension="standard-attr-description",
@@ -377,7 +377,7 @@
         router = self._create_router(data_utils.rand_name('router'))
         self.assertEqual(len(router['external_gateways']), 0)
 
-        res = self.client.router_add_external_gateways(
+        res = self.admin_client.router_add_external_gateways(
             router['id'],
             [{'network_id': CONF.network.public_network_id,
               'enable_snat': False}])
@@ -391,7 +391,7 @@
         router = self._create_router(data_utils.rand_name('router'))
         self.assertEqual(len(router['external_gateways']), 0)
 
-        res = self.client.router_add_external_gateways(
+        res = self.admin_client.router_add_external_gateways(
             router['id'],
             [
                 {'network_id': CONF.network.public_network_id,
@@ -424,9 +424,11 @@
         router = self._create_router(
             data_utils.rand_name('router'),
             external_network_id=CONF.network.public_network_id,
-            enable_snat=False)
+            enable_snat=False,
+            client=self.admin_client,
+        )
         self.assertEqual(len(router['external_gateways']), 1)
-        res = self.client.router_add_external_gateways(
+        res = self.admin_client.router_add_external_gateways(
             router['id'],
             [{'network_id': CONF.network.public_network_id,
               'enable_snat': False}])
@@ -437,9 +439,10 @@
         router = self._create_router(
             data_utils.rand_name('router'),
             external_network_id=CONF.network.public_network_id,
-            enable_snat=False)
+            enable_snat=False,
+            client=self.admin_client)
         self.assertEqual(len(router['external_gateways']), 1)
-        res = self.client.router_remove_external_gateways(
+        res = self.admin_client.router_remove_external_gateways(
             router['id'],
             [{'network_id': CONF.network.public_network_id}])
         self.assertEqual(len(res['router']['external_gateways']), 0)
@@ -449,7 +452,7 @@
         router = self._create_router(data_utils.rand_name('router'))
         self.assertEqual(len(router['external_gateways']), 0)
 
-        res = self.client.router_add_external_gateways(
+        res = self.admin_client.router_add_external_gateways(
             router['id'],
             [
                 {'network_id': CONF.network.public_network_id,
@@ -480,7 +483,7 @@
         router = self._create_router(data_utils.rand_name('router'))
         self.assertEqual(len(router['external_gateways']), 0)
 
-        res = self.client.router_add_external_gateways(
+        res = self.admin_client.router_add_external_gateways(
             router['id'],
             [
                 {'network_id': CONF.network.public_network_id,
@@ -503,7 +506,7 @@
                     remove_gateways[0])
 
         external_gateways[1] = remove_gateways[0]
-        res_update_gws = self.client.router_update_external_gateways(
+        res_update_gws = self.admin_client.router_update_external_gateways(
             router['id'],
             external_gateways)
 
diff --git a/neutron_tempest_plugin/api/test_security_groups.py b/neutron_tempest_plugin/api/test_security_groups.py
index 5e8b18e..37cd80b 100644
--- a/neutron_tempest_plugin/api/test_security_groups.py
+++ b/neutron_tempest_plugin/api/test_security_groups.py
@@ -281,9 +281,10 @@
     def _set_quota(self, val, resource):
         res_quota = self._get_quota(resource)
         project_id = self.client.project_id
-        self.admin_client.update_quotas(project_id, **{resource: val})
+        self.admin_client.update_quotas(project_id, **{resource: val,
+                                                       'force': True})
         self.addCleanup(self.admin_client.update_quotas,
-                        project_id, **{resource: res_quota})
+                        project_id, **{resource: res_quota, 'force': True})
 
     def _get_quota(self, resource):
         project_id = self.client.project_id
@@ -383,8 +384,9 @@
     def _set_sg_rules_quota(self, val):
         project_id = self.client.project_id
         self.admin_client.update_quotas(project_id,
-                                        **{'security_group_rule': val})
-        LOG.info('Trying to update security group rule quota {} '.format(val))
+                                        **{'security_group_rule': val,
+                                           'force': True})
+        LOG.info('Trying to update security group rule quota %r', val)
 
     def _get_sg_rules_quota(self):
         project_id = self.client.project_id
@@ -435,7 +437,8 @@
         sg_rules_quota = self._get_sg_rules_quota()
         project_id = self.client.project_id
         self.addCleanup(self.admin_client.update_quotas,
-                        project_id, **{'security_group_rule': sg_rules_quota})
+                        project_id, **{'security_group_rule': sg_rules_quota,
+                                       'force': True})
         values = [-1, 0, 10, 2147483647]
         for value in values:
             self._set_sg_rules_quota(value)
diff --git a/neutron_tempest_plugin/common/constants.py b/neutron_tempest_plugin/common/constants.py
index f695f6c..36fb865 100644
--- a/neutron_tempest_plugin/common/constants.py
+++ b/neutron_tempest_plugin/common/constants.py
@@ -87,7 +87,7 @@
 
 ATTRIBUTES_TO_UPDATE = 'attributes_to_update'
 
-# Maximum value integer can take in MySQL and PostgreSQL
+# Maximum value integer can take in MySQL.
 # In SQLite integer can be stored in 1, 2, 3, 4, 6, or 8 bytes,
 # but here it will be limited by this value for consistency.
 DB_INTEGER_MAX_VALUE = 2 ** 31 - 1
diff --git a/neutron_tempest_plugin/common/ip.py b/neutron_tempest_plugin/common/ip.py
index 07bbe69..5335219 100644
--- a/neutron_tempest_plugin/common/ip.py
+++ b/neutron_tempest_plugin/common/ip.py
@@ -96,7 +96,7 @@
         return self.configure_vlan(addresses, port, vlan_tag, subport_ips,
                                    subport['mac_address'])
 
-    def configure_vlan_transparent(self, port, vlan_tag, ip_addresses):
+    def configure_inner_vlan(self, port, vlan_tag, ip_addresses):
         addresses = self.list_addresses()
         try:
             subport_device = get_vlan_device_name(addresses, ip_addresses)
@@ -108,6 +108,11 @@
 
         return self.configure_vlan(addresses, port, vlan_tag, ip_addresses)
 
+    # NOTE(ralonsoh): some projects, like whitebox-neutron-tempest-plugin, are
+    # using ``configure_vlan_transparent`` method. The concept of "inner VLAN"
+    # does not exist in the VLAN transparency feature.
+    configure_vlan_transparent = configure_inner_vlan
+
     def list_namespaces(self):
         namespaces_output = self.execute("netns")
         ns_list = []
diff --git a/neutron_tempest_plugin/common/utils.py b/neutron_tempest_plugin/common/utils.py
index c62aa78..62191bf 100644
--- a/neutron_tempest_plugin/common/utils.py
+++ b/neutron_tempest_plugin/common/utils.py
@@ -132,17 +132,6 @@
         return False
 
 
-def spawn_http_server(ssh_client, port, message):
-    cmd = ("(echo -e 'HTTP/1.1 200 OK\r\n'; echo '%(msg)s') "
-           "| sudo nc -lp %(port)d &" % {'msg': message, 'port': port})
-    ssh_client.exec_command(cmd)
-
-
-def call_url_remote(ssh_client, url):
-    cmd = "curl %s --retry 3 --connect-timeout 2" % url
-    return ssh_client.exec_command(cmd)
-
-
 class StatefulConnection:
     """Class to test connection that should remain opened
 
@@ -205,29 +194,29 @@
                         sleep=self.test_sleep)
         try:
             LOG.info("Checking connectivity between server and client -"
-                    " attempt {}".format(self.test_attempt))
+                    " attempt %d", self.test_attempt)
             self.server_ssh.exec_command(
                     'grep {} output.txt'.format(self.test_str))
             self.client_ssh.exec_command(
                     'grep {} output.txt'.format(self.test_str))
             if not self.should_pass:
-                LOG.warning("attempt {} succeed while it should fail".format(
-                    self.test_attempt))
+                LOG.warning("attempt %d succeed while it should fail",
+                            self.test_attempt)
                 return False
             else:
                 if not self.connection_started:
                     self.connection_started = True
-                LOG.info("attempt {} succeed as it expected".format(
-                    self.test_attempt))
+                LOG.info("attempt %d succeed as it expected",
+                         self.test_attempt)
                 return True
         except exceptions.SSHExecCommandFailed:
             if self.should_pass:
-                LOG.warning("attempt {} failed while it should pass".format(
-                    self.test_attempt))
+                LOG.warning("attempt %d failed while it should pass",
+                            self.test_attempt)
                 return False
             else:
-                LOG.info("attempt {} failed as it expected".format(
-                    self.test_attempt))
+                LOG.info("attempt %d failed as it expected",
+                         self.test_attempt)
                 return True
         finally:
             self.test_attempt += 1
diff --git a/neutron_tempest_plugin/config.py b/neutron_tempest_plugin/config.py
index a6d5c09..38d6ac6 100644
--- a/neutron_tempest_plugin/config.py
+++ b/neutron_tempest_plugin/config.py
@@ -77,6 +77,12 @@
                default='openstackgate.local',
                help='dns_domain value configured at neutron.conf, which will '
                     'be used for the DNS configuration of the instances'),
+    cfg.BoolOpt('snat_rules_apply_to_nested_networks',
+                default=False,
+                help='Whether SNAT rules apply recursively to all connected '
+                'networks. This is the default behavior for ovs and '
+                'linuxbridge drivers. OVN requires '
+                'ovn_router_indirect_snat=True setting to implement it.'),
 
     # Multicast tests settings
     cfg.StrOpt('multicast_group_range',
@@ -158,16 +164,16 @@
 for opt in NeutronPluginOptions:
     CONF.register_opt(opt, 'neutron_plugin_options')
 
-# TODO(slaweq): This config option is added to avoid running bgpvpn tests twice
-# on stable branches till stable/stein. We need to remove this config option
-# once stable/stein is EOL. Bgpvpn tempest plugin has been merged into
-# neutron-tempest-plugin from Train. Train onwards bgpvpn tests will run from
-# neutron-tempest-plugins.
 BgpvpnGroup = [
+    # TODO(tkajinam): This has been required since the plugin tests was merged
+    # into neutron-tempest-plugin in Train. Remove this after 2025.1 release.
     cfg.BoolOpt('run_bgpvpn_tests',
                 default=True,
                 help=("If it is set to False bgpvpn api and scenario tests "
-                      "will be skipped")),
+                      "will be skipped"),
+                deprecated_for_removal=True,
+                deprecated_reason='Tests are skipped according to '
+                                  'the available extensions.'),
     cfg.IntOpt('min_asn',
                default=100,
                help=("Minimum number for the range of "
@@ -191,16 +197,20 @@
 CONF.register_group(bgpvpn_group)
 CONF.register_opts(BgpvpnGroup, group="bgpvpn")
 
-# TODO(slaweq): This config option is added to avoid running fwaas tests twice
-# on stable branches till stable/stein. We need to remove this config option
-# once stable/stein is EOL. Fwaas tempest plugin has been merged into
-# neutron-tempest-plugin from Train. Train onwards fwaas tests will run from
-# neutron-tempest-plugins.
 FwaasGroup = [
+    # TODO(tkajinam): This has been required since the plugin tests was merged
+    # into neutron-tempest-plugin in Train. Remove this after 2025.1 release.
     cfg.BoolOpt('run_fwaas_tests',
                 default=True,
                 help=("If it is set to False fwaas api and scenario tests "
-                      "will be skipped")),
+                      "will be skipped"),
+                deprecated_for_removal=True,
+                deprecated_reason='Tests are skipped according to '
+                                  'the available extensions.'),
+    cfg.StrOpt('driver',
+               default=None,
+               choices=['openvswitch', 'ovn'],
+               help='Driver used by the FWaaS plugin.'),
 ]
 
 fwaas_group = cfg.OptGroup(
@@ -208,16 +218,16 @@
 CONF.register_group(fwaas_group)
 CONF.register_opts(FwaasGroup, group="fwaas")
 
-# TODO(slaweq): This config option is added to avoid running SFC tests twice
-# on stable branches till stable/stein. We need to remove this config option
-# once stable/stein is EOL. SFC tempest plugin has been merged into
-# neutron-tempest-plugin from Train. Train onwards SFC tests will run from
-# neutron-tempest-plugins.
 SfcGroup = [
+    # TODO(tkajinam): This has been required since the plugin tests was merged
+    # into neutron-tempest-plugin in Train. Remove this after 2025.1 release.
     cfg.BoolOpt('run_sfc_tests',
                 default=True,
                 help=("If it is set to False SFC api and scenario tests "
-                      "will be skipped")),
+                      "will be skipped"),
+                deprecated_for_removal=True,
+                deprecated_reason='Tests are skipped according to '
+                                  'the available extensions.'),
 ]
 
 sfc_group = cfg.OptGroup(name="sfc", title=("Networking-sfc Service Options"))
@@ -242,6 +252,21 @@
 CONF.register_group(taas_group)
 CONF.register_opts(TaasGroup, group="taas")
 
+
+DynamicRoutingGroup = [
+    cfg.StrOpt('base_image',
+               default='quay.io/nf-core/ubuntu:20.04',
+               help=('Base image used to build the image for connectivity '
+                     'check')),
+]
+
+dynamic_routing_group = cfg.OptGroup(
+    name="dynamic_routing",
+    title=("Neutron-Dynamic-Routing Service Options"))
+CONF.register_group(dynamic_routing_group)
+CONF.register_opts(DynamicRoutingGroup, group="dynamic_routing")
+
+
 # DNS Integration with an External Service
 DnsFeatureGroup = [
     cfg.IntOpt(
@@ -253,19 +278,3 @@
     name='designate_feature_enabled', title='Enabled Designate Features')
 CONF.register_group(dns_feature_group)
 CONF.register_opts(DnsFeatureGroup, group="designate_feature_enabled")
-
-config_opts_translator = {
-    'project_network_cidr': 'tenant_network_cidr',
-    'project_network_v6_cidr': 'tenant_network_v6_cidr',
-    'project_network_mask_bits': 'tenant_network_mask_bits',
-    'project_network_v6_mask_bits': 'tenant_network_v6_mask_bits'}
-
-
-def safe_get_config_value(group, name):
-    """Safely get Oslo config opts from Tempest, using old and new names."""
-    conf_group = getattr(CONF, group)
-
-    try:
-        return getattr(conf_group, name)
-    except cfg.NoSuchOptError:
-        return getattr(conf_group, config_opts_translator[name])
diff --git a/neutron_tempest_plugin/fwaas/scenario/test_fwaas_v2.py b/neutron_tempest_plugin/fwaas/scenario/test_fwaas_v2.py
index 9896073..6af27fc 100644
--- a/neutron_tempest_plugin/fwaas/scenario/test_fwaas_v2.py
+++ b/neutron_tempest_plugin/fwaas/scenario/test_fwaas_v2.py
@@ -89,9 +89,9 @@
                                 (ssh_source, remote_ip, should_connect),
                                 msg)
             except Exception:
-                LOG.exception("Unable to access {dest} via ssh to "
-                              "floating-ip {src}".format(dest=remote_ip,
-                                                         src=floating_ip))
+                LOG.exception("Unable to access %s via ssh to "
+                              "floating-ip %s",
+                              remote_ip, floating_ip)
                 raise
 
     def _check_remote_connectivity(self, source, dest, should_succeed=True,
@@ -269,12 +269,11 @@
 
         # Scenario 3: Create a rule allowing ICMP only from server_fixed_ip_1
         # to server_fixed_ip_2 and check that traffic from opposite direction
-        # is blocked.
+        # is blocked (for ovs driver where rules are stateful).
         fw_allow_unidirectional_icmp_rule = self.create_firewall_rule(
             action="allow", protocol="icmp",
             source_ip_address=topology['server_fixed_ip_1'],
             destination_ip_address=topology['server_fixed_ip_2'])
-
         self.remove_firewall_rule_from_policy_and_wait(
             firewall_group_id=fw_group['id'],
             firewall_rule_id=fw_deny_icmp_rule['id'],
@@ -284,6 +283,20 @@
             firewall_rule_id=fw_allow_unidirectional_icmp_rule['id'],
             firewall_policy_id=fw_policy['id'])
 
+        if CONF.fwaas.driver == 'ovn':
+            # NOTE(slaweq): OVN driver in FWaaS implements only stateless rules
+            # so allowing only unidirectional traffic is not enough as ICMP
+            # replies are still blocked and to make it working additional rule
+            # for the opposite direction is required also:
+            fw_allow_icmp_reply_rule = self.create_firewall_rule(
+                action="allow", protocol="icmp",
+                source_ip_address=topology['server_fixed_ip_2'],
+                destination_ip_address=topology['server_fixed_ip_1'])
+            self.insert_firewall_rule_in_policy_and_wait(
+                firewall_group_id=fw_group['id'],
+                firewall_rule_id=fw_allow_icmp_reply_rule['id'],
+                firewall_policy_id=fw_policy['id'])
+
         self._check_server_connectivity(
             topology['server_floating_ip_1'],
             topology['private_key1'],
@@ -293,7 +306,7 @@
             topology['server_floating_ip_2'],
             topology['private_key2'],
             address_list=[topology['server_fixed_ip_1']],
-            should_connect=False)
+            should_connect=CONF.fwaas.driver == 'ovn')
 
         # Disassociate ports of this firewall group for cleanup resources
         self.update_firewall_group_and_wait(fw_group['id'], ports=[])
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py b/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
index 5cdd524..1d089f6 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
@@ -177,7 +177,7 @@
         bgp_speaker = self.get_bgp_speaker(bgp_speaker_id)
         bgp_peers_list = bgp_speaker['peers']
         self.assertEqual(1, len(bgp_peers_list))
-        self.assertTrue(bgp_peer_id in bgp_peers_list)
+        self.assertIn(bgp_peer_id, bgp_peers_list)
 
     @decorators.idempotent_id('f9737708-1d79-440b-8350-779f97d882ee')
     def test_remove_bgp_peer(self):
@@ -188,7 +188,7 @@
         self.add_bgp_peer(bgp_speaker_id, bgp_peer_id)
         bgp_speaker = self.get_bgp_speaker(bgp_speaker_id)
         bgp_peers_list = bgp_speaker['peers']
-        self.assertTrue(bgp_peer_id in bgp_peers_list)
+        self.assertIn(bgp_peer_id, bgp_peers_list)
 
         bgp_speaker = self.remove_bgp_peer(bgp_speaker_id, bgp_peer_id)
         bgp_speaker = self.get_bgp_speaker(bgp_speaker_id)
@@ -206,7 +206,7 @@
         bgp_speaker = self.get_bgp_speaker(bgp_speaker_id)
         network_list = bgp_speaker['networks']
         self.assertEqual(1, len(network_list))
-        self.assertTrue(self.ext_net_id in network_list)
+        self.assertIn(self.ext_net_id, network_list)
 
     @decorators.idempotent_id('6cfc7137-0d99-4a3d-826c-9d1a3a1767b0')
     def test_remove_gateway_network(self):
@@ -218,7 +218,7 @@
         bgp_speaker = self.get_bgp_speaker(bgp_speaker_id)
         networks = bgp_speaker['networks']
 
-        self.assertTrue(self.ext_net_id in networks)
+        self.assertIn(self.ext_net_id, networks)
         self.bgp_adm_client.remove_bgp_gateway_network(bgp_speaker_id,
                                                        self.ext_net_id)
         bgp_speaker = self.get_bgp_speaker(bgp_speaker_id)
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
index c7023af..3f799bb 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/base.py
@@ -65,6 +65,7 @@
 
 
 class BgpSpeakerScenarioTestJSONBase(base.BaseAdminNetworkTest):
+    baseimage = CONF.dynamic_routing.base_image
 
     def setUp(self):
         self.addCleanup(self.net_resource_cleanup)
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/base.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/base.py
index dd170e7..3719dd6 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/base.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/base.py
@@ -84,7 +84,7 @@
                                        router_id=cls.L_AS.router_id)
         cls.dr.set_addr_info(bridge='br-docker-basic', ipv4=cls.public_gw)
         # quagga container
-        cls.dockerimg = ctn_base.DockerImage()
+        cls.dockerimg = ctn_base.DockerImage(baseimage=cls.baseimage)
         cls.q_img = cls.dockerimg.create_quagga(check_exist=True)
         cls.images.append(cls.q_img)
         for i in range(cls.RAS_MAX):
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_4byte_asn.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_4byte_asn.py
index f492ede..1421734 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_4byte_asn.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/basic/test_4byte_asn.py
@@ -91,7 +91,7 @@
                                        router_id=cls.L_AS.router_id)
         cls.dr.set_addr_info(bridge='br-docker-4byte-asn', ipv4=cls.public_gw)
         # quagga container
-        cls.dockerimg = ctn_base.DockerImage()
+        cls.dockerimg = ctn_base.DockerImage(baseimage=cls.baseimage)
         cls.q_img = cls.dockerimg.create_quagga(check_exist=True)
         cls.images.append(cls.q_img)
         for i in range(cls.RAS_MAX):
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv4/test_ipv4.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv4/test_ipv4.py
index 158b7ad..57c9018 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv4/test_ipv4.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv4/test_ipv4.py
@@ -91,7 +91,7 @@
                                        router_id=cls.L_AS.router_id)
         cls.dr.set_addr_info(bridge='br-docker-ipv4', ipv4=cls.public_gw)
         # quagga container
-        cls.dockerimg = ctn_base.DockerImage()
+        cls.dockerimg = ctn_base.DockerImage(baseimage=cls.baseimage)
         cls.q_img = cls.dockerimg.create_quagga(check_exist=True)
         cls.images.append(cls.q_img)
         for i in range(cls.RAS_MAX):
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv6/test_ipv6.py b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv6/test_ipv6.py
index 937b38d..9bd4c8d 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv6/test_ipv6.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/scenario/ipv6/test_ipv6.py
@@ -91,7 +91,7 @@
                                        router_id=cls.L_AS.router_id)
         cls.dr.set_addr_info(bridge='br-docker-ipv6', ipv6=cls.public_gw)
         # quagga container
-        cls.dockerimg = ctn_base.DockerImage()
+        cls.dockerimg = ctn_base.DockerImage(baseimage=cls.baseimage)
         cls.q_img = cls.dockerimg.create_quagga(check_exist=True)
         cls.images.append(cls.q_img)
         for i in range(cls.RAS_MAX):
diff --git a/neutron_tempest_plugin/scenario/base.py b/neutron_tempest_plugin/scenario/base.py
index 6149b06..70cb2dc 100644
--- a/neutron_tempest_plugin/scenario/base.py
+++ b/neutron_tempest_plugin/scenario/base.py
@@ -337,7 +337,7 @@
         if create_fip:
             self.fip = self.create_floatingip(port=self.port)
 
-    def check_connectivity(self, host, ssh_user=None, ssh_key=None,
+    def check_connectivity(self, host=None, ssh_user=None, ssh_key=None,
                            servers=None, ssh_timeout=None, ssh_client=None):
         # Either ssh_client or ssh_user+ssh_key is mandatory.
         if ssh_client is None:
diff --git a/neutron_tempest_plugin/scenario/test_dns_integration.py b/neutron_tempest_plugin/scenario/test_dns_integration.py
index d520aa2..d6bafef 100644
--- a/neutron_tempest_plugin/scenario/test_dns_integration.py
+++ b/neutron_tempest_plugin/scenario/test_dns_integration.py
@@ -39,6 +39,8 @@
 # when designate_tempest_plugin is not available
 dns_base = testtools.try_import('designate_tempest_plugin.tests.base')
 dns_waiters = testtools.try_import('designate_tempest_plugin.common.waiters')
+dns_data_utils = testtools.try_import('designate_tempest_plugin.data_utils')
+
 if dns_base:
     DNSMixin = dns_base.BaseDnsV2Test
 else:
@@ -53,7 +55,7 @@
         super(BaseDNSIntegrationTests, cls).setup_clients()
         cls.zone_client = cls.os_tempest.dns_v2.ZonesClient()
         cls.recordset_client = cls.os_tempest.dns_v2.RecordsetClient()
-        cls.query_client.build_timeout = 30
+        cls.query_client.build_timeout = 60
 
     @classmethod
     def skip_checks(cls):
@@ -68,12 +70,13 @@
     @utils.requires_ext(extension="dns-integration", service="network")
     def resource_setup(cls):
         super(BaseDNSIntegrationTests, cls).resource_setup()
-        cls.zone = cls.zone_client.create_zone()[1]
-        cls.addClassResourceCleanup(cls.zone_client.delete_zone,
-            cls.zone['id'], ignore_errors=lib_exc.NotFound)
-        dns_waiters.wait_for_zone_status(
-            cls.zone_client, cls.zone['id'], 'ACTIVE')
-
+        cls.zone_name = dns_data_utils.rand_zone_name(
+            name="basednsintegrationtests")
+        cls.zone = cls.zone_client.create_zone(
+            name=cls.zone_name, wait_until='ACTIVE')[1]
+        cls.addClassResourceCleanup(
+            cls.zone_client.delete_zone, cls.zone['id'],
+            ignore_errors=lib_exc.NotFound)
         cls.network = cls.create_network(dns_domain=cls.zone['name'])
         cls.subnet = cls.create_subnet(cls.network)
         cls.subnet_v6 = cls.create_subnet(cls.network, ip_version=6)
@@ -250,8 +253,9 @@
     @classmethod
     def resource_setup(cls):
         super(DNSIntegrationExtraTests, cls).resource_setup()
-        cls.network2 = cls.create_network()
-        cls.subnet2 = cls.create_subnet(cls.network2)
+        cls.network2 = cls.create_network(
+            name=data_utils.rand_name('dns_integration_net'))
+        cls.subnet2 = cls.create_subnet(cls.network2, cidr='10.123.151.0/24')
         cls.subnet2_v6 = cls.create_subnet(cls.network2,
                                            ip_version=6,
                                            dns_publish_fixed_ip=True)
@@ -274,6 +278,16 @@
         self.client.delete_port(port['id'])
         self._verify_dns_records(addr_v6, name, record_type='AAAA',
                                  found=False)
+        self.client.update_subnet(
+            self.subnet2['id'], dns_publish_fixed_ip=True)
+        port = self.create_port(self.network2,
+                                dns_domain=self.zone['name'],
+                                dns_name=name)
+        addr_v4 = port['fixed_ips'][1 - v6_index]['ip_address']
+        self._verify_dns_records(addr_v4, name, record_type='A')
+        self.client.delete_port(port['id'])
+        self._verify_dns_records(addr_v4, name, record_type='A',
+                                 found=False)
 
 
 class DNSIntegrationDomainPerProjectTests(BaseDNSIntegrationTests):
@@ -286,19 +300,15 @@
     @classmethod
     def resource_setup(cls):
         super(BaseDNSIntegrationTests, cls).resource_setup()
-
-        name = data_utils.rand_name('test-domain')
-        zone_name = "%s.%s.%s.zone." % (cls.client.user_id,
+        cls.name = data_utils.rand_name('test-domain')
+        cls.zone_name = "%s.%s.%s.zone." % (cls.client.user_id,
                                         cls.client.project_id,
-                                        name)
-        dns_domain_template = "<user_id>.<project_id>.%s.zone." % name
-
-        cls.zone = cls.zone_client.create_zone(name=zone_name)[1]
+                                        cls.name)
+        dns_domain_template = "<user_id>.<project_id>.%s.zone." % cls.name
+        cls.zone = cls.zone_client.create_zone(
+            name=cls.zone_name, wait_until='ACTIVE')[1]
         cls.addClassResourceCleanup(cls.zone_client.delete_zone,
             cls.zone['id'], ignore_errors=lib_exc.NotFound)
-        dns_waiters.wait_for_zone_status(
-            cls.zone_client, cls.zone['id'], 'ACTIVE')
-
         cls.network = cls.create_network(dns_domain=dns_domain_template)
         cls.subnet = cls.create_subnet(cls.network,
                                        dns_publish_fixed_ip=True)
diff --git a/neutron_tempest_plugin/scenario/test_floatingip.py b/neutron_tempest_plugin/scenario/test_floatingip.py
index f222396..f3d03e6 100644
--- a/neutron_tempest_plugin/scenario/test_floatingip.py
+++ b/neutron_tempest_plugin/scenario/test_floatingip.py
@@ -18,7 +18,6 @@
 import ddt
 from neutron_lib import constants as lib_constants
 from neutron_lib.services.qos import constants as qos_consts
-from neutron_lib.utils import test
 from oslo_log import log
 from tempest.common import utils
 from tempest.common import waiters
@@ -147,7 +146,6 @@
 
     same_network = True
 
-    @test.unstable_test("bug 1717302")
     @decorators.idempotent_id('05c4e3b3-7319-4052-90ad-e8916436c23b')
     @ddt.unpack
     @ddt.data({'src_has_fip': True, 'dest_has_fip': True},
@@ -165,7 +163,6 @@
 
     same_network = False
 
-    @test.unstable_test("bug 1717302")
     @decorators.idempotent_id('f18f0090-3289-4783-b956-a0f8ac511e8b')
     @ddt.unpack
     @ddt.data({'src_has_fip': True, 'dest_has_fip': True},
@@ -204,6 +201,64 @@
                                        gateway_external_ip,
                                        servers=[proxy, src_server])
 
+    def _test_nested_snat_external_ip(self, feature_enabled_bool):
+        """Check connectivity to an external IP from a nested network."""
+        gateway_external_ip = self._get_external_gateway()
+
+        if not gateway_external_ip:
+            raise self.skipTest("IPv4 gateway is not configured for public "
+                                "network or public_network_id is not "
+                                "configured")
+        proxy = self._create_server()
+        proxy_client = ssh.Client(proxy['fip']['floating_ip_address'],
+                                  CONF.validation.image_ssh_user,
+                                  pkey=self.keypair['private_key'])
+
+        # Create a nested router
+        router = self.create_router(
+            router_name=data_utils.rand_name('router'),
+            admin_state_up=True)
+
+        # Attach outer subnet to it
+        outer_port = self.create_port(self.network)
+        self.client.add_router_interface_with_port_id(router['id'],
+                                                      outer_port['id'])
+
+        # Attach a nested subnet to it
+        network = self.create_network()
+        subnet = self.create_subnet(network)
+        self.create_router_interface(router['id'], subnet['id'])
+
+        # Set up static routes in both directions
+        self.client.update_extra_routes(
+            self.router['id'],
+            outer_port['fixed_ips'][0]['ip_address'], subnet['cidr'])
+        self.client.update_extra_routes(
+            router['id'], self.subnet['gateway_ip'], '0.0.0.0/0')
+
+        # Create a server inside the nested network
+        src_server = self._create_server(create_floating_ip=False,
+                                         network=network)
+
+        # Check connectivity if nested SNAT is enabled, else no connectivity
+        src_server_ip = src_server['port']['fixed_ips'][0]['ip_address']
+        ssh_client = ssh.Client(src_server_ip,
+                                CONF.validation.image_ssh_user,
+                                pkey=self.keypair['private_key'],
+                                proxy_client=proxy_client)
+        self.check_remote_connectivity(ssh_client,
+                                       gateway_external_ip,
+                                       should_succeed=feature_enabled_bool,
+                                       servers=[proxy, src_server])
+
+    @decorators.idempotent_id('b911b124-b6cb-449d-83d9-b34f3665741d')
+    @utils.requires_ext(extension='extraroute', service='network')
+    def test_nested_snat_external_ip(self):
+        feature_enabled_bool = (
+            CONF.neutron_plugin_options.snat_rules_apply_to_nested_networks
+        )
+        self._test_nested_snat_external_ip(feature_enabled_bool)
+
 
 class FloatingIPPortDetailsTest(FloatingIpTestCasesMixin,
                                 base.BaseTempestTestCase):
diff --git a/neutron_tempest_plugin/scenario/test_metadata.py b/neutron_tempest_plugin/scenario/test_metadata.py
index af6bd09..34b9b88 100644
--- a/neutron_tempest_plugin/scenario/test_metadata.py
+++ b/neutron_tempest_plugin/scenario/test_metadata.py
@@ -12,7 +12,10 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import base64
 import collections
+import textwrap
+import time
 
 from neutron_lib import constants as nlib_const
 from oslo_log import log as logging
@@ -32,6 +35,8 @@
 Server = collections.namedtuple(
     'Server', ['floating_ip', 'server', 'ssh_client'])
 
+QUERY_MSG = 'Queried the metadata service over IPv6'
+
 
 class MetadataTest(base.BaseTempestTestCase):
 
@@ -86,19 +91,49 @@
                                 security_groups=[self.security_group['id']],
                                 **params)
 
-    def _create_server(self, port, use_advanced_image=False, **params):
+    def _create_server(self, port=None, network_id=None,
+                       use_advanced_image=False, **params):
         if use_advanced_image:
             flavor_ref = CONF.neutron_plugin_options.advanced_image_flavor_ref
             image_ref = CONF.neutron_plugin_options.advanced_image_ref
         else:
             flavor_ref = CONF.compute.flavor_ref
             image_ref = CONF.compute.image_ref
+        if port:
+            networks = [{'port': port['id']}]
+        else:
+            networks = [{'uuid': network_id}]
         return self.create_server(flavor_ref=flavor_ref,
                                   image_ref=image_ref,
                                   key_name=self.keypair['name'],
-                                  networks=[{'port': port['id']}],
+                                  networks=networks,
                                   **params)['server']
 
+    def _get_metadata_query_script(self):
+        sheebang_line = '\n#!/bin/bash -x'
+        curl_cmd = '\ncurl http://[%(address)s' % {'address':
+                                                   nlib_const.METADATA_V6_IP}
+        ip_cmd = ("%25$(ip -6 -br address show scope link up | head -1 | "
+                  "cut -d ' ' -f1)]/openstack/")
+        echo_cmd = '\necho %s' % QUERY_MSG
+        script = '%s%s%s%s' % (sheebang_line, curl_cmd, ip_cmd, echo_cmd)
+        script_clean = textwrap.dedent(script).lstrip().encode('utf8')
+        script_b64 = base64.b64encode(script_clean)
+        return {'user_data': script_b64}
+
+    def _wait_for_metadata_query_msg(self, vm):
+        timeout = 300
+        start_time = int(time.time())
+        while int(time.time()) - start_time < timeout:
+            console_output = self.os_primary.servers_client.get_console_output(
+                vm['id'])['output']
+            pos = console_output.find(QUERY_MSG)
+            if pos > -1:
+                return console_output, pos
+            time.sleep(30)
+        self.fail('Failed to find metadata query message in console log %s' %
+                  console_output)
+
     def _create_ssh_client(self, floating_ip, use_advanced_image=False):
         if use_advanced_image:
             username = CONF.neutron_plugin_options.advanced_image_ssh_user
@@ -134,8 +169,7 @@
             self.network, use_advanced_image=use_advanced_image)
         self.wait_for_server_active(server=vm.server)
         self.wait_for_guest_os_ready(vm.server)
-        self.check_connectivity(host=vm.floating_ip['floating_ip_address'],
-                                ssh_client=vm.ssh_client)
+        self.check_connectivity(ssh_client=vm.ssh_client)
         interface = self._get_primary_interface(vm.ssh_client)
 
         try:
@@ -153,3 +187,26 @@
         except exceptions.SSHExecCommandFailed:
             self._log_console_output()
             self._log_local_network_status()
+
+    @testtools.skipUnless(
+        CONF.neutron_plugin_options.advanced_image_ref or
+        CONF.neutron_plugin_options.default_image_is_advanced,
+        'Advanced image is required to run this test.')
+    @decorators.idempotent_id('7542892a-d132-471c-addb-172dcf888ff6')
+    def test_metadata_ipv6_only_network(self):
+        ipv6_network = self.create_network()
+        ipv6_subnet = self.create_subnet(network=ipv6_network, ip_version=6,
+                                         ipv6_ra_mode="slaac",
+                                         ipv6_address_mode="slaac")
+        self.create_router_interface(self.router['id'], ipv6_subnet['id'])
+        use_advanced_image = (
+            not CONF.neutron_plugin_options.default_image_is_advanced)
+        params = self._get_metadata_query_script()
+        params['config_drive'] = True
+        vm = self._create_server(
+            network_id=ipv6_network['id'],
+            use_advanced_image=use_advanced_image, **params)
+        self.wait_for_server_active(server=vm)
+        self.wait_for_guest_os_ready(vm)
+        console_output, pos = self._wait_for_metadata_query_msg(vm)
+        self.assertIn('latest', console_output[pos - 100:])
diff --git a/neutron_tempest_plugin/scenario/test_mtu.py b/neutron_tempest_plugin/scenario/test_mtu.py
index ea62fcf..29ccb01 100644
--- a/neutron_tempest_plugin/scenario/test_mtu.py
+++ b/neutron_tempest_plugin/scenario/test_mtu.py
@@ -170,18 +170,12 @@
     networks = []
 
     @classmethod
-    def skip_checks(cls):
-        super(NetworkWritableMtuTest, cls).skip_checks()
-        supported_type_drivers = ['vxlan', 'geneve']
-        if not any(type_driver in supported_type_drivers for type_driver in
-                   config.CONF.neutron_plugin_options.available_type_drivers):
-            raise cls.skipException(
-                "Neither VXLAN nor GENEVE type_driver is enabled")
-
-    @classmethod
     @utils.requires_ext(extension="net-mtu-writable", service="network")
     def resource_setup(cls):
         super(NetworkWritableMtuTest, cls).resource_setup()
+        if cls.is_driver_ovn:
+            raise cls.skipException("East/west icmp fragmentation is not "
+                                    "supported with ML2/OVN")
 
     def _create_setup(self):
         self.admin_client = self.os_admin.network_client
@@ -233,37 +227,37 @@
     @decorators.idempotent_id('bc470200-d8f4-4f07-b294-1b4cbaaa35b9')
     def test_connectivity_min_max_mtu(self):
         server_ssh_client, _, _, fip2 = self._create_setup()
-        log_msg = ("Ping with {mtu_size} MTU of 2 networks. Fragmentation is "
-                   "{fragmentation_state}. Expected result: ping "
-                   "{ping_status}")
+        log_msg = ("Ping with %(mtu_size)s MTU of 2 networks. "
+                   "Fragmentation is %(fragmentation_state)s. "
+                   "Expected result: ping %(ping_status)s")
 
         # ping with min mtu of 2 networks succeeds even when
         # fragmentation is disabled
-        LOG.debug(log_msg.format(mtu_size='minimal',
-                  fragmentation_state='disabled', ping_status='succeeded'))
+        LOG.debug(log_msg, mtu_size='minimal',
+                  fragmentation_state='disabled', ping_status='succeeded')
         self.check_remote_connectivity(
             server_ssh_client, fip2['fixed_ip_address'],
             mtu=self.networks[0]['mtu'], fragmentation=False)
 
         # ping with the size above min mtu of 2 networks
         # fails when fragmentation is disabled
-        LOG.debug(log_msg.format(mtu_size='size above minimal',
-                  fragmentation_state='disabled', ping_status='failed'))
+        LOG.debug(log_msg, mtu_size='size above minimal',
+                  fragmentation_state='disabled', ping_status='failed')
         self.check_remote_connectivity(
             server_ssh_client, fip2['fixed_ip_address'], should_succeed=False,
             mtu=self.networks[0]['mtu'] + 2, fragmentation=False)
 
         # ping with max mtu of 2 networks succeeds when
         # fragmentation is enabled
-        LOG.debug(log_msg.format(mtu_size='maximal',
-                  fragmentation_state='enabled', ping_status='succeeded'))
+        LOG.debug(log_msg, mtu_size='maximal',
+                  fragmentation_state='enabled', ping_status='succeeded')
         self.check_remote_connectivity(
             server_ssh_client, fip2['fixed_ip_address'],
             mtu=self.networks[1]['mtu'])
 
         # ping with max mtu of 2 networks fails when fragmentation is disabled
-        LOG.debug(log_msg.format(mtu_size='maximal',
-                  fragmentation_state='disabled', ping_status='failed'))
+        LOG.debug(log_msg, mtu_size='maximal',
+                  fragmentation_state='disabled', ping_status='failed')
         self.check_remote_connectivity(
             server_ssh_client, fip2['fixed_ip_address'], should_succeed=False,
             mtu=self.networks[1]['mtu'], fragmentation=False)
diff --git a/neutron_tempest_plugin/scenario/test_multiple_gws.py b/neutron_tempest_plugin/scenario/test_multiple_gws.py
index 686457d..e4f1d3d 100644
--- a/neutron_tempest_plugin/scenario/test_multiple_gws.py
+++ b/neutron_tempest_plugin/scenario/test_multiple_gws.py
@@ -38,6 +38,7 @@
 
 CONF = config.CONF
 LOG = log.getLogger(__name__)
+FRR_BASE_IMAGE = 'quay.io/nf-core/ubuntu:22.04'
 
 
 class FRROCIImage(ctn_base.DockerImage):
@@ -47,7 +48,7 @@
         baseimage: typing.Optional[str] = None,
         use_existing: bool = False,
     ):
-        super().__init__(baseimage=baseimage or 'ubuntu:22.04')
+        super().__init__(baseimage=baseimage or FRR_BASE_IMAGE)
         self.daemons = daemons
         self.tagname = 'frr-' + '-'.join(daemons)
         if use_existing and self.exist(self.tagname):
@@ -629,7 +630,8 @@
     def test_update_router_single_gw_bfd(self):
         ext_network_id = self.ext_networks[0][0]['id']
         bfd_container = self.containers[0]
-        router = self.create_router(
+        router = self._create_router_with_client(
+            self.admin_client,
             router_name=data_utils.rand_name('router'),
             admin_state_up=True,
             enable_snat=False,
diff --git a/neutron_tempest_plugin/scenario/test_ports.py b/neutron_tempest_plugin/scenario/test_ports.py
index c661d39..56cedde 100644
--- a/neutron_tempest_plugin/scenario/test_ports.py
+++ b/neutron_tempest_plugin/scenario/test_ports.py
@@ -107,8 +107,8 @@
                 if port is not None:
                     break
             except Exception as e:
-                LOG.warning('Failed to create Port, using Fixed_IP:{}, '
-                            'the Error was:{}'.format(ip, e))
+                LOG.warning('Failed to create Port, using Fixed_IP:%s, '
+                            'the Error was:%s', ip, e)
         fip, server = self._create_instance_with_port(port)
         self.check_connectivity(fip[0]['floating_ip_address'],
                                 CONF.validation.image_ssh_user,
diff --git a/neutron_tempest_plugin/scenario/test_security_groups.py b/neutron_tempest_plugin/scenario/test_security_groups.py
index 03156c7..dc0f5ef 100644
--- a/neutron_tempest_plugin/scenario/test_security_groups.py
+++ b/neutron_tempest_plugin/scenario/test_security_groups.py
@@ -51,37 +51,13 @@
     credentials = ['primary', 'admin']
     required_extensions = ['router', 'security-group']
 
-    def _verify_http_connection(self, ssh_client, ssh_server,
-                                test_ip, test_port, servers, should_pass=True):
-        """Verify if HTTP connection works using remote hosts.
-
-        :param ssh.Client ssh_client: The client host active SSH client.
-        :param ssh.Client ssh_server: The HTTP server host active SSH client.
-        :param string test_ip: IP address of HTTP server
-        :param string test_port: Port of HTTP server
-        :param list servers: List of servers for which console output will be
-                             logged in case when test case
-        :param bool should_pass: Wheter test should pass or not.
-
-        :return: if passed or not
-        :rtype: bool
-        """
-        utils.kill_nc_process(ssh_server)
-        url = 'http://%s:%d' % (test_ip, test_port)
-        utils.spawn_http_server(ssh_server, port=test_port, message='foo_ok')
-        utils.process_is_running(ssh_server, 'nc')
+    def _test_connection_and_log(self, con, *args, **kwargs):
         try:
-            ret = utils.call_url_remote(ssh_client, url)
-            if should_pass:
-                self.assertIn('foo_ok', ret)
-                return
-            self.assertNotIn('foo_ok', ret)
-        except Exception as e:
-            if not should_pass:
-                return
-            self._log_console_output(servers)
+            con.test_connection(*args, **kwargs)
+        except utils.WaitTimeout:
+            self._log_console_output()
             self._log_local_network_status()
-            raise e
+            raise
 
     @classmethod
     def setup_credentials(cls):
@@ -601,7 +577,7 @@
         for port in range(80, 84):
             with utils.StatefulConnection(
                     ssh_clients[0], ssh_clients[2], test_ip, port) as con:
-                con.test_connection(should_pass=False)
+                self._test_connection_and_log(con, should_pass=False)
 
         # add two remote-group rules with port-ranges
         rule_list = [{'protocol': constants.PROTO_NUM_TCP,
@@ -636,7 +612,7 @@
         for port in range(80, 84):
             with utils.StatefulConnection(
                     ssh_clients[0], ssh_clients[2], test_ip, port) as con:
-                con.test_connection()
+                self._test_connection_and_log(con)
 
         # list the tcp rule id by SG id and port-range
         sg_rule_id = self.os_primary.network_client.list_security_group_rules(
@@ -650,7 +626,7 @@
         for port in range(80, 82):
             with utils.StatefulConnection(
                     ssh_clients[0], ssh_clients[2], test_ip, port) as con:
-                con.test_connection(should_pass=False)
+                self._test_connection_and_log(con, should_pass=False)
 
     def _test_overlapping_sec_grp_rules(self):
         """Test security group rules with overlapping port ranges"""
@@ -714,11 +690,11 @@
         for _ in range(2):
             with utils.StatefulConnection(
                     client_ssh[0], srv_ssh, srv_ip, tcp_port) as con:
-                con.test_connection()
+                self._test_connection_and_log(con)
             for port in range(tcp_port, tcp_port + 3):
                 with utils.StatefulConnection(
                         client_ssh[1], srv_ssh, srv_ip, port) as con:
-                    con.test_connection()
+                    self._test_connection_and_log(con)
 
     def _test_remove_sec_grp_from_active_vm(self):
         """Tests the following:
@@ -906,23 +882,23 @@
                 vm_ssh[0], vm_ssh[1], srv_ip, 6666) as con:
             self.client.update_port(srv_port['id'],
                     security_groups=[ssh_sg['id'], sg['id']])
-            con.test_connection()
+            self._test_connection_and_log(con)
         with utils.StatefulConnection(
                 vm_ssh[0], vm_ssh[1], srv_ip, 6666) as con:
             self.client.update_port(
                     srv_port['id'], security_groups=[ssh_sg['id']])
-            con.test_connection(should_pass=False)
+            self._test_connection_and_log(con, should_pass=False)
         with utils.StatefulConnection(
                 vm_ssh[0], vm_ssh[1], srv_ip, 6666) as con:
             self.client.update_port(srv_port['id'],
                     security_groups=[ssh_sg['id'], sg['id']])
-            con.test_connection()
+            self._test_connection_and_log(con)
             self.client.update_port(srv_port['id'],
                     security_groups=[ssh_sg['id']])
-            con.test_connection(should_pass=False)
+            self._test_connection_and_log(con, should_pass=False)
             self.client.update_port(srv_port['id'],
                     security_groups=[ssh_sg['id'], sg['id']])
-            con.test_connection()
+            self._test_connection_and_log(con)
 
     @decorators.idempotent_id('4a724164-bbc0-4029-a844-644ece66c026')
     def test_connectivity_between_vms_using_different_sec_groups(self):
diff --git a/neutron_tempest_plugin/scenario/test_trunk.py b/neutron_tempest_plugin/scenario/test_trunk.py
index 2ba8f13..66e6254 100644
--- a/neutron_tempest_plugin/scenario/test_trunk.py
+++ b/neutron_tempest_plugin/scenario/test_trunk.py
@@ -164,14 +164,14 @@
         utils.wait_until_true(
             lambda: self._is_port_status(port, status),
             exception=RuntimeError(
-                "Timed out waiting for port {!r} to transition to get "
+                "Timed out waiting for port {!r} to transition to "
                 "status {!r}.".format(port['id'], status)))
 
     def _wait_for_trunk(self, trunk, status=constants.ACTIVE):
         utils.wait_until_true(
             lambda: self._is_trunk_status(trunk, status),
             exception=RuntimeError(
-                "Timed out waiting for trunk {!r} to transition to get "
+                "Timed out waiting for trunk {!r} to transition to "
                 "status {!r}.".format(trunk['id'], status)))
 
     def _create_ssh_client(self, floating_ip, use_advanced_image=False):
@@ -193,7 +193,6 @@
         self._wait_for_port(port=vm.port)
         self._wait_for_port(port=vm.subport)
         self.check_connectivity(
-            host=vm.floating_ip['floating_ip_address'],
             ssh_client=vm.ssh_client,
             servers=[vm.server])
 
@@ -317,7 +316,6 @@
                                          vlan_subnet=vlan_subnet)
             self._check_servers_remote_connectivity(vms=vms)
 
-    @test.unstable_test("bug 1897796")
     @testtools.skipUnless(
         (CONF.neutron_plugin_options.advanced_image_ref or
          CONF.neutron_plugin_options.default_image_is_advanced),
diff --git a/neutron_tempest_plugin/scenario/test_vlan_transparency.py b/neutron_tempest_plugin/scenario/test_vlan_transparency.py
index d9a529c..85648bc 100644
--- a/neutron_tempest_plugin/scenario/test_vlan_transparency.py
+++ b/neutron_tempest_plugin/scenario/test_vlan_transparency.py
@@ -30,20 +30,27 @@
 MAX_VLAN_ID = 4094
 
 
-class VlanTransparencyTest(base.BaseTempestTestCase):
-    credentials = ['primary', 'admin']
-    force_tenant_isolation = False
+class BaseVlanTest(base.BaseAdminTempestTestCase):
 
-    required_extensions = ['vlan-transparent', 'allowed-address-pairs']
+    """Base class common for the tests for the "vlan_transparent" and "qinq".
+
+    This base class covers common things for the tests for networks with
+    enabled either `qinq` or `vlan_transparent` attributes. Those 2 attributes
+    are functionally the same even from the end user's point of view. The only
+    difference between them is ethtype used for the outer VLAN tag but this
+    can't really be tested in the neutron-tempest-plugin tests.
+    """
+
+    network_kwargs = {}
 
     @classmethod
     def resource_setup(cls):
-        super(VlanTransparencyTest, cls).resource_setup()
+        super(BaseVlanTest, cls).resource_setup()
         # setup basic topology for servers we can log into
         cls.rand_name = data_utils.rand_name(
             cls.__name__.rsplit('.', 1)[-1])
         cls.network = cls.create_network(name=cls.rand_name,
-                                         vlan_transparent=True)
+                                         **cls.network_kwargs)
         cls.subnet = cls.create_subnet(network=cls.network,
                                        name=cls.rand_name)
         cls.router = cls.create_router_by_client()
@@ -63,7 +70,7 @@
 
     @classmethod
     def skip_checks(cls):
-        super(VlanTransparencyTest, cls).skip_checks()
+        super().skip_checks()
         if not (CONF.neutron_plugin_options.advanced_image_ref or
                 CONF.neutron_plugin_options.default_image_is_advanced):
             raise cls.skipException(
@@ -89,12 +96,11 @@
                                   networks=[{'port': self.vm_ports[-1]['id']}],
                                   name=server_name)['server']
 
-    def _configure_vlan_transparent(self, port, ssh_client,
-                                    vlan_tag, vlan_ip):
+    def _configure_inner_vlan(self, port, ssh_client, vlan_tag, vlan_ip):
         ip_command = ip.IPCommand(ssh_client=ssh_client)
         addresses = ip_command.list_addresses(port=port)
         port_iface = ip.get_port_device_name(addresses, port)
-        subport_iface = ip_command.configure_vlan_transparent(
+        subport_iface = ip_command.configure_inner_vlan(
             port=port, vlan_tag=vlan_tag, ip_addresses=[vlan_ip])
 
         for address in ip_command.list_addresses(ip_addresses=vlan_ip):
@@ -113,8 +119,9 @@
                           username=username,
                           pkey=self.keypair['private_key'])
 
-    def _test_basic_vlan_transparency_connectivity(
+    def _test_basic_inner_vlan_connectivity(
             self, port_security=True, use_allowed_address_pairs=False):
+        self._ensure_ethtype()
         vlan_tag = data_utils.rand_int_id(start=MIN_VLAN_ID, end=MAX_VLAN_ID)
         vlan_ipmask_template = '192.168.%d.{ip_last_byte}/24' % (vlan_tag %
                                                                  256)
@@ -138,13 +145,11 @@
             ssh_clients.append(
                 self._create_ssh_client(floating_ip=floating_ips[i]))
 
-            self.check_connectivity(
-                host=floating_ips[i]['floating_ip_address'],
-                ssh_client=ssh_clients[i])
-            self._configure_vlan_transparent(port=self.vm_ports[-1],
-                                             ssh_client=ssh_clients[i],
-                                             vlan_tag=vlan_tag,
-                                             vlan_ip=vlan_ipmasks[i])
+            self.check_connectivity(ssh_client=ssh_clients[i])
+            self._configure_inner_vlan(port=self.vm_ports[-1],
+                                       ssh_client=ssh_clients[i],
+                                       vlan_tag=vlan_tag,
+                                       vlan_ip=vlan_ipmasks[i])
 
         if port_security:
             # Ping from vm0 to vm1 via VLAN interface should fail because
@@ -175,12 +180,63 @@
             self.vm_ports[-2]['fixed_ips'][0]['ip_address'],
             servers=vms)
 
+
+class VlanTransparencyTest(BaseVlanTest):
+    credentials = ['primary', 'admin']
+    force_tenant_isolation = False
+
+    required_extensions = ['vlan-transparent', 'allowed-address-pairs']
+
+    network_kwargs = {'vlan_transparent': True}
+
+    def _ensure_ethtype(self):
+        self.assertTrue(self.network.get('vlan_transparent'))
+        self.assertFalse(self.network.get('qinq'))
+
     @decorators.idempotent_id('a2694e3a-6d4d-4a23-9fcc-c3ed3ef37b16')
     def test_vlan_transparent_port_sec_disabled(self):
-        self._test_basic_vlan_transparency_connectivity(
+        self._test_basic_inner_vlan_connectivity(
             port_security=False, use_allowed_address_pairs=False)
 
     @decorators.idempotent_id('2dd03b4f-9c20-4cda-8c6a-40fa453ec69a')
     def test_vlan_transparent_allowed_address_pairs(self):
-        self._test_basic_vlan_transparency_connectivity(
+        self._test_basic_inner_vlan_connectivity(
+            port_security=True, use_allowed_address_pairs=True)
+
+
+class VlanQinqTest(BaseVlanTest):
+    credentials = ['primary', 'admin']
+    force_tenant_isolation = False
+
+    required_extensions = ['qinq', 'allowed-address-pairs']
+
+    network_kwargs = {
+        'qinq': True,
+        'provider_network_type': 'vlan'}
+
+    @classmethod
+    def resource_setup(cls):
+        cls.network_kwargs['provider_physical_network'] = (
+            CONF.neutron_plugin_options.provider_vlans[0])
+        super().resource_setup()
+
+    @classmethod
+    def skip_checks(cls):
+        super().skip_checks()
+        if not CONF.neutron_plugin_options.provider_vlans:
+            raise cls.skipException(
+                'Physical network is required to run these tests.')
+
+    def _ensure_ethtype(self):
+        self.assertFalse(self.network.get('vlan_transparent'))
+        self.assertTrue(self.network.get('qinq'))
+
+    @decorators.idempotent_id('ae78398e-9242-46b4-a5fc-227581821fca')
+    def test_vlan_transparent_port_sec_disabled(self):
+        self._test_basic_inner_vlan_connectivity(
+            port_security=False, use_allowed_address_pairs=False)
+
+    @decorators.idempotent_id('6ca983cd-b1c5-4e2c-949e-4be8ffa22a9c')
+    def test_vlan_transparent_allowed_address_pairs(self):
+        self._test_basic_inner_vlan_connectivity(
             port_security=True, use_allowed_address_pairs=True)
diff --git a/neutron_tempest_plugin/tap_as_a_service/scenario/test_traffic_impact.py b/neutron_tempest_plugin/tap_as_a_service/scenario/test_traffic_impact.py
index e70eb03..904335d 100644
--- a/neutron_tempest_plugin/tap_as_a_service/scenario/test_traffic_impact.py
+++ b/neutron_tempest_plugin/tap_as_a_service/scenario/test_traffic_impact.py
@@ -14,16 +14,15 @@
 #    under the License.
 
 from contextlib import contextmanager
-from oslo_log import log
-import testtools
 
+from oslo_log import log
 from tempest.common import utils
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils.linux import remote_client
 from tempest.lib.common.utils import test_utils
-
 from tempest.lib import decorators
+import testtools
 
 from neutron_tempest_plugin.tap_as_a_service.scenario import manager
 
@@ -151,7 +150,7 @@
 
         # Ensure tcpdump is up and running
         psax = self.monitor_client.exec_command("ps -ax")
-        self.assertTrue("tcpdump" in psax)
+        self.assertIn("tcpdump", psax)
 
         # Run traffic from left_vm to right_vm
         LOG.debug('Check ICMP traffic: ping %s ', right_ip)
diff --git a/releasenotes/notes/deprecate-run-tests-opts-cdf54c17e72d80ac.yaml b/releasenotes/notes/deprecate-run-tests-opts-cdf54c17e72d80ac.yaml
new file mode 100644
index 0000000..a36b333
--- /dev/null
+++ b/releasenotes/notes/deprecate-run-tests-opts-cdf54c17e72d80ac.yaml
@@ -0,0 +1,9 @@
+---
+deprecations:
+  - |
+    The following options have been deprecated, in favor of the mechanism to
+    enable/disable tests according to the available extensions.
+
+    - ``[bgpvpn] run_bgpvpn_tests``
+    - ``[fwaas] run_fwaas_tests``
+    - ``[sfc] run_sfc_tests``
diff --git a/releasenotes/notes/dynamic-routing-base-image-12e76a6d85411a6d.yaml b/releasenotes/notes/dynamic-routing-base-image-12e76a6d85411a6d.yaml
new file mode 100644
index 0000000..303e095
--- /dev/null
+++ b/releasenotes/notes/dynamic-routing-base-image-12e76a6d85411a6d.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    The new ``[dynamic_routing] base_image`` option has been added. This option
+    allows customizing the reference of the base container image used for
+    connectivity check in dynamic routing plugin tests.
diff --git a/roles/docker-setup/tasks/main.yml b/roles/docker-setup/tasks/main.yml
index 19d8bfb..1b0e2d7 100644
--- a/roles/docker-setup/tasks/main.yml
+++ b/roles/docker-setup/tasks/main.yml
@@ -4,6 +4,14 @@
     name: docker.io
     state: present
 
+- name: Install docker-buildx (only for Ubuntu and Debian)
+  become: yes
+  package:
+    name: docker-buildx
+    state: present
+  when:
+    - (ansible_facts['distribution'] | lower) in ['ubuntu', 'debian']
+
 - name: Copy 52_docker_for_tempest to /etc/sudoers.d
   copy:
     src: 52_docker_for_tempest
diff --git a/setup.cfg b/setup.cfg
index 3e352a0..0962924 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,7 +6,7 @@
 author = OpenStack
 author_email = openstack-discuss@lists.openstack.org
 home_page = https://opendev.org/openstack/neutron-tempest-plugin
-python_requires = >=3.6
+python_requires = >=3.9
 classifier =
     Environment :: OpenStack
     Intended Audience :: Information Technology
@@ -15,10 +15,10 @@
     Operating System :: POSIX :: Linux
     Programming Language :: Python
     Programming Language :: Python :: 3
-    Programming Language :: Python :: 3.6
-    Programming Language :: Python :: 3.7
-    Programming Language :: Python :: 3.8
     Programming Language :: Python :: 3.9
+    Programming Language :: Python :: 3.10
+    Programming Language :: Python :: 3.11
+    Programming Language :: Python :: 3.12
 
 [files]
 packages =
diff --git a/test-requirements.txt b/test-requirements.txt
index 0151f21..ebde755 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,7 +1,7 @@
-hacking>=3.2.0,<3.3.0 # Apache-2.0
+hacking>=6.1.0,<6.2.0 # Apache-2.0
 
 coverage>=4.4.1 # Apache-2.0
-flake8-import-order==0.12 # LGPLv3
+flake8-import-order>=0.18.0,<0.19.0 # LGPLv3
 python-subunit>=1.0.0 # Apache-2.0/BSD
 oslotest>=3.2.0 # Apache-2.0
 stestr>=1.0.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index 2f7da5c..c8add2c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -62,9 +62,10 @@
 # E126 continuation line over-indented for hanging indent
 # E128 continuation line under-indented for visual indent
 # E129 visually indented line with same indent as next logical line
+# I202 Additional newline in a group of imports.
 # N530 direct neutron imports not allowed
 # W504 line break after binary operator
-ignore = E126,E128,E129,N530,W504
+ignore = E126,E128,E129,I202,N530,W504
 # H106: Don't put vim configuration in source files
 # H203: Use assertIs(Not)None to check for None
 # H204: Use assert(Not)Equal to check for equality
diff --git a/zuul.d/2023_1_jobs.yaml b/zuul.d/2023_1_jobs.yaml
index 4325b83..cedbc67 100644
--- a/zuul.d/2023_1_jobs.yaml
+++ b/zuul.d/2023_1_jobs.yaml
@@ -1,6 +1,7 @@
 - job:
     name: neutron-tempest-plugin-openvswitch-2023-1
     parent: neutron-tempest-plugin-openvswitch
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2023.1
     vars:
       network_api_extensions_openvswitch:
@@ -105,6 +106,7 @@
 - job:
     name: neutron-tempest-plugin-openvswitch-iptables_hybrid-2023-1
     parent: neutron-tempest-plugin-openvswitch-iptables_hybrid
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2023.1
     vars:
       network_api_extensions_common: *api_extensions
@@ -143,6 +145,7 @@
 - job:
     name: neutron-tempest-plugin-openvswitch-enforce-scope-new-defaults-2023-1
     parent: neutron-tempest-plugin-openvswitch-2023-1
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2023.1
     vars:
       devstack_localrc:
@@ -160,6 +163,7 @@
 - job:
     name: neutron-tempest-plugin-linuxbridge-2023-1
     parent: neutron-tempest-plugin-linuxbridge
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2023.1
     vars:
       network_api_extensions_common: *api_extensions
@@ -188,6 +192,7 @@
           (^neutron_tempest_plugin.scenario.test_floatingip.FloatingIPPortDetailsTest.test_floatingip_port_details)"
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_linuxbridge) | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -201,6 +206,7 @@
 - job:
     name: neutron-tempest-plugin-ovn-2023-1
     parent: neutron-tempest-plugin-ovn
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2023.1
     vars:
       network_api_extensions_ovn:
@@ -210,12 +216,9 @@
           (^neutron_tempest_plugin.scenario)|\
           (^tempest.api.compute.servers.test_attach_interfaces)|\
           (^tempest.api.compute.servers.test_multiple_create)"
-      # TODO(jlibosva): Remove the NetworkWritableMtuTest test from the list
-      # once east/west fragmentation is supported in core OVN
-      tempest_exclude_regex: "\
-          (^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest)"
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_ovn) | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_services:
         q-ovn-metadata-agent: true
         q-ovn-agent: false
@@ -232,6 +235,7 @@
 - job:
     name: neutron-tempest-plugin-dvr-multinode-scenario-2023-1
     parent: neutron-tempest-plugin-dvr-multinode-scenario
+    nodeset: openstack-two-node-jammy
     override-checkout: stable/2023.1
     vars:
       network_api_extensions_common: *api_extensions
@@ -245,13 +249,17 @@
 - job:
     name: neutron-tempest-plugin-designate-scenario-2023-1
     parent: neutron-tempest-plugin-designate-scenario
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2023.1
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-sfc-2023-1
     parent: neutron-tempest-plugin-sfc
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2023.1
     vars:
       devstack_localrc:
@@ -260,6 +268,7 @@
 - job:
     name: neutron-tempest-plugin-bgpvpn-bagpipe-2023-1
     parent: neutron-tempest-plugin-bgpvpn-bagpipe
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2023.1
     vars:
       devstack_localrc:
@@ -268,11 +277,22 @@
 - job:
     name: neutron-tempest-plugin-dynamic-routing-2023-1
     parent: neutron-tempest-plugin-dynamic-routing
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2023.1
+    vars:
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
+      # NOTE(haleyb): Scenario tests are disabled since they are failing trying
+      # to create the unmaintained/2023.1 branch due to an os-ken issue. See
+      # https://review.opendev.org/c/openstack/neutron-dynamic-routing/+/935090
+      # for more details.
+      tempest_exclude_regex: "\
+          (^neutron_tempest_plugin.neutron_dynamic_routing.scenario)"
 
 - job:
     name: neutron-tempest-plugin-fwaas-2023-1
-    parent: neutron-tempest-plugin-fwaas
+    parent: neutron-tempest-plugin-fwaas-openvswitch
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2023.1
     vars:
       devstack_localrc:
@@ -281,6 +301,7 @@
 - job:
     name: neutron-tempest-plugin-vpnaas-2023-1
     parent: neutron-tempest-plugin-vpnaas
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2023.1
     vars:
       devstack_localrc:
@@ -289,6 +310,7 @@
 - job:
     name: neutron-tempest-plugin-tap-as-a-service-2023-1
     parent: neutron-tempest-plugin-tap-as-a-service
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2023.1
     vars:
       devstack_localrc:
diff --git a/zuul.d/2024_1_jobs.yaml b/zuul.d/2024_1_jobs.yaml
index f0a182b..674d1ab 100644
--- a/zuul.d/2024_1_jobs.yaml
+++ b/zuul.d/2024_1_jobs.yaml
@@ -1,6 +1,7 @@
 - job:
     name: neutron-tempest-plugin-openvswitch-2024-1
     parent: neutron-tempest-plugin-openvswitch
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2024.1
     vars:
       network_api_extensions_openvswitch: &api_extensions_openvswitch
@@ -107,6 +108,7 @@
 - job:
     name: neutron-tempest-plugin-openvswitch-iptables_hybrid-2024-1
     parent: neutron-tempest-plugin-openvswitch-iptables_hybrid
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2024.1
     vars:
       network_api_extensions_common: *api_extensions
@@ -140,6 +142,7 @@
 - job:
     name: neutron-tempest-plugin-openvswitch-enforce-scope-new-defaults-2024-1
     parent: neutron-tempest-plugin-openvswitch-2024-1
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2024.1
     vars:
       devstack_localrc:
@@ -157,6 +160,7 @@
 - job:
     name: neutron-tempest-plugin-linuxbridge-2024-1
     parent: neutron-tempest-plugin-linuxbridge
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2024.1
     vars:
       network_api_extensions_common: *api_extensions
@@ -185,6 +189,7 @@
           (^neutron_tempest_plugin.scenario.test_floatingip.FloatingIPPortDetailsTest.test_floatingip_port_details)"
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_linuxbridge) | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -198,6 +203,7 @@
 - job:
     name: neutron-tempest-plugin-ovn-2024-1
     parent: neutron-tempest-plugin-ovn
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2024.1
     vars:
       network_api_extensions_ovn:
@@ -207,12 +213,9 @@
           (^neutron_tempest_plugin.scenario)|\
           (^tempest.api.compute.servers.test_attach_interfaces)|\
           (^tempest.api.compute.servers.test_multiple_create)"
-      # TODO(jlibosva): Remove the NetworkWritableMtuTest test from the list
-      # once east/west fragmentation is supported in core OVN
-      tempest_exclude_regex: "\
-          (^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest)"
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_ovn) | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -226,6 +229,7 @@
 - job:
     name: neutron-tempest-plugin-dvr-multinode-scenario-2024-1
     parent: neutron-tempest-plugin-dvr-multinode-scenario
+    nodeset: openstack-two-node-jammy
     override-checkout: stable/2024.1
     vars:
       network_api_extensions_common: *api_extensions
@@ -239,13 +243,17 @@
 - job:
     name: neutron-tempest-plugin-designate-scenario-2024-1
     parent: neutron-tempest-plugin-designate-scenario
+    nodeset: neutron-nested-virt-ubuntu-jammy
     override-checkout: stable/2024.1
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-sfc-2024-1
     parent: neutron-tempest-plugin-sfc
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2024.1
     vars:
       devstack_localrc:
@@ -254,6 +262,7 @@
 - job:
     name: neutron-tempest-plugin-bgpvpn-bagpipe-2024-1
     parent: neutron-tempest-plugin-bgpvpn-bagpipe
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2024.1
     vars:
       devstack_localrc:
@@ -262,11 +271,16 @@
 - job:
     name: neutron-tempest-plugin-dynamic-routing-2024-1
     parent: neutron-tempest-plugin-dynamic-routing
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2024.1
+    vars:
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-fwaas-2024-1
-    parent: neutron-tempest-plugin-fwaas
+    parent: neutron-tempest-plugin-fwaas-openvswitch
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2024.1
     vars:
       devstack_localrc:
@@ -275,6 +289,7 @@
 - job:
     name: neutron-tempest-plugin-vpnaas-2024-1
     parent: neutron-tempest-plugin-vpnaas
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2024.1
     vars:
       devstack_localrc:
@@ -283,6 +298,7 @@
 - job:
     name: neutron-tempest-plugin-tap-as-a-service-2024-1
     parent: neutron-tempest-plugin-tap-as-a-service
+    nodeset: openstack-single-node-jammy
     override-checkout: stable/2024.1
     vars:
       devstack_localrc:
diff --git a/zuul.d/2023_2_jobs.yaml b/zuul.d/2024_2_jobs.yaml
similarity index 83%
rename from zuul.d/2023_2_jobs.yaml
rename to zuul.d/2024_2_jobs.yaml
index 7406440..f42bdbf 100644
--- a/zuul.d/2023_2_jobs.yaml
+++ b/zuul.d/2024_2_jobs.yaml
@@ -1,7 +1,8 @@
 - job:
-    name: neutron-tempest-plugin-openvswitch-2023-2
+    name: neutron-tempest-plugin-openvswitch-2024-2
     parent: neutron-tempest-plugin-openvswitch
-    override-checkout: stable/2023.2
+    nodeset: neutron-nested-virt-ubuntu-jammy
+    override-checkout: stable/2024.2
     vars:
       network_api_extensions_openvswitch: &api_extensions_openvswitch
         - dhcp_agent_scheduler
@@ -57,6 +58,7 @@
         - pagination
         - port-device-profile
         - port-mac-address-regenerate
+        - port-trusted-vif
         - port-resource-request
         - port-resource-request-groups
         - port-security
@@ -75,6 +77,8 @@
         - router
         - router_availability_zone
         - security-group
+        - security-groups-default-rules
+        - security-groups-normalized-cidr
         - security-groups-remote-address-group
         - segment
         - service-type
@@ -95,7 +99,6 @@
         - uplink-status-propagation
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_openvswitch) | join(',') }}"
-        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -103,9 +106,10 @@
               available_features: "{{ network_available_features | join(',') }}"
 
 - job:
-    name: neutron-tempest-plugin-openvswitch-iptables_hybrid-2023-2
+    name: neutron-tempest-plugin-openvswitch-iptables_hybrid-2024-2
     parent: neutron-tempest-plugin-openvswitch-iptables_hybrid
-    override-checkout: stable/2023.2
+    nodeset: neutron-nested-virt-ubuntu-jammy
+    override-checkout: stable/2024.2
     vars:
       network_api_extensions_common: *api_extensions
       network_api_extensions_openvswitch: *api_extensions_openvswitch
@@ -125,7 +129,6 @@
           (^neutron_tempest_plugin.scenario.test_security_groups.StatelessNetworkSecGroupTest.test_established_tcp_session_after_re_attachinging_sg)"
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_openvswitch) | join(',') }}"
-        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -136,9 +139,10 @@
               firewall_driver: iptables_hybrid
 
 - job:
-    name: neutron-tempest-plugin-openvswitch-enforce-scope-new-defaults-2023-2
-    parent: neutron-tempest-plugin-openvswitch-2023-2
-    override-checkout: stable/2023.2
+    name: neutron-tempest-plugin-openvswitch-enforce-scope-new-defaults-2024-2
+    parent: neutron-tempest-plugin-openvswitch-2024-2
+    nodeset: neutron-nested-virt-ubuntu-jammy
+    override-checkout: stable/2024.2
     vars:
       devstack_localrc:
         # Enabeling the scope and new defaults for services.
@@ -153,9 +157,10 @@
         NEUTRON_ENFORCE_SCOPE: true
 
 - job:
-    name: neutron-tempest-plugin-linuxbridge-2023-2
+    name: neutron-tempest-plugin-linuxbridge-2024-2
     parent: neutron-tempest-plugin-linuxbridge
-    override-checkout: stable/2023.2
+    nodeset: neutron-nested-virt-ubuntu-jammy
+    override-checkout: stable/2024.2
     vars:
       network_api_extensions_common: *api_extensions
       network_api_extensions_linuxbridge:
@@ -194,9 +199,10 @@
               firewall_driver: iptables
 
 - job:
-    name: neutron-tempest-plugin-ovn-2023-2
+    name: neutron-tempest-plugin-ovn-2024-2
     parent: neutron-tempest-plugin-ovn
-    override-checkout: stable/2023.2
+    nodeset: neutron-nested-virt-ubuntu-jammy
+    override-checkout: stable/2024.2
     vars:
       network_api_extensions_ovn:
         - vlan-transparent
@@ -211,9 +217,7 @@
           (^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest)"
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_ovn) | join(',') }}"
-      devstack_services:
-        q-ovn-metadata-agent: true
-        q-ovn-agent: false
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -225,9 +229,10 @@
               firewall_driver: ovn
 
 - job:
-    name: neutron-tempest-plugin-dvr-multinode-scenario-2023-2
+    name: neutron-tempest-plugin-dvr-multinode-scenario-2024-2
     parent: neutron-tempest-plugin-dvr-multinode-scenario
-    override-checkout: stable/2023.2
+    nodeset: openstack-two-node-jammy
+    override-checkout: stable/2024.2
     vars:
       network_api_extensions_common: *api_extensions
       network_api_extensions_dvr:
@@ -235,56 +240,49 @@
         - dvr
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_dvr) | join(',') }}"
-        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
-    name: neutron-tempest-plugin-designate-scenario-2023-2
+    name: neutron-tempest-plugin-designate-scenario-2024-2
     parent: neutron-tempest-plugin-designate-scenario
-    override-checkout: stable/2023.2
+    nodeset: neutron-nested-virt-ubuntu-jammy
+    override-checkout: stable/2024.2
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
-    name: neutron-tempest-plugin-sfc-2023-2
+    name: neutron-tempest-plugin-sfc-2024-2
     parent: neutron-tempest-plugin-sfc
-    override-checkout: stable/2023.2
-    vars:
-      devstack_localrc:
-        NEUTRON_DEPLOY_MOD_WSGI: false
+    nodeset: openstack-single-node-jammy
+    override-checkout: stable/2024.2
 
 - job:
-    name: neutron-tempest-plugin-bgpvpn-bagpipe-2023-2
+    name: neutron-tempest-plugin-bgpvpn-bagpipe-2024-2
     parent: neutron-tempest-plugin-bgpvpn-bagpipe
-    override-checkout: stable/2023.2
-    vars:
-      devstack_localrc:
-        NEUTRON_DEPLOY_MOD_WSGI: false
+    nodeset: openstack-single-node-jammy
+    override-checkout: stable/2024.2
 
 - job:
-    name: neutron-tempest-plugin-dynamic-routing-2023-2
+    name: neutron-tempest-plugin-dynamic-routing-2024-2
     parent: neutron-tempest-plugin-dynamic-routing
-    override-checkout: stable/2023.2
+    nodeset: openstack-single-node-jammy
+    override-checkout: stable/2024.2
 
 - job:
-    name: neutron-tempest-plugin-fwaas-2023-2
-    parent: neutron-tempest-plugin-fwaas
-    override-checkout: stable/2023.2
-    vars:
-      devstack_localrc:
-        NEUTRON_DEPLOY_MOD_WSGI: false
+    name: neutron-tempest-plugin-fwaas-2024-2
+    parent: neutron-tempest-plugin-fwaas-openvswitch
+    nodeset: openstack-single-node-jammy
+    override-checkout: stable/2024.2
 
 - job:
-    name: neutron-tempest-plugin-vpnaas-2023-2
+    name: neutron-tempest-plugin-vpnaas-2024-2
     parent: neutron-tempest-plugin-vpnaas
-    override-checkout: stable/2023.2
-    vars:
-      devstack_localrc:
-        NEUTRON_DEPLOY_MOD_WSGI: false
+    nodeset: openstack-single-node-jammy
+    override-checkout: stable/2024.2
 
 - job:
-    name: neutron-tempest-plugin-tap-as-a-service-2023-2
+    name: neutron-tempest-plugin-tap-as-a-service-2024-2
     parent: neutron-tempest-plugin-tap-as-a-service
-    override-checkout: stable/2023.2
-    vars:
-      devstack_localrc:
-        NEUTRON_DEPLOY_MOD_WSGI: false
+    nodeset: openstack-single-node-jammy
+    override-checkout: stable/2024.2
diff --git a/zuul.d/2025_1_jobs.yaml b/zuul.d/2025_1_jobs.yaml
new file mode 100644
index 0000000..b34db9f
--- /dev/null
+++ b/zuul.d/2025_1_jobs.yaml
@@ -0,0 +1,242 @@
+- job:
+    name: neutron-tempest-plugin-openvswitch-2025-1
+    parent: neutron-tempest-plugin-openvswitch
+    nodeset: neutron-nested-virt-ubuntu-noble
+    override-checkout: stable/2025.1
+    vars:
+      network_api_extensions_openvswitch: &api_extensions_openvswitch
+        - dhcp_agent_scheduler
+        - local_ip
+        - qos-bw-minimum-ingress
+      tempest_test_regex: "\
+          (^neutron_tempest_plugin.api)|\
+          (^neutron_tempest_plugin.scenario)|\
+          (^tempest.api.compute.servers.test_attach_interfaces)|\
+          (^tempest.api.compute.servers.test_multiple_create)"
+      network_available_features: &available_features
+        - ipv6_metadata
+      network_api_extensions_common: &api_extensions
+        - address-group
+        - address-scope
+        - agent
+        - allowed-address-pairs
+        - auto-allocated-topology
+        - availability_zone
+        - binding
+        - default-subnetpools
+        - dns-domain-ports
+        - dns-integration
+        - dns-integration-domain-keywords
+        - empty-string-filtering
+        - expose-port-forwarding-in-fip
+        - expose-l3-conntrack-helper
+        - ext-gw-mode
+        - external-net
+        - extra_dhcp_opt
+        - extraroute
+        - extraroute-atomic
+        - filter-validation
+        - fip-port-details
+        - flavors
+        - floating-ip-port-forwarding
+        - floating-ip-port-forwarding-detail
+        - floatingip-pools
+        - ip-substring-filtering
+        - l3-conntrack-helper
+        - l3-ext-ndp-proxy
+        - l3-flavors
+        - l3-ha
+        - l3-ndp-proxy
+        - l3_agent_scheduler
+        - metering
+        - multi-provider
+        - net-mtu
+        - net-mtu-writable
+        - network-ip-availability
+        - network_availability_zone
+        - network-segment-range
+        - pagination
+        - port-device-profile
+        - port-mac-address-regenerate
+        - port-trusted-vif
+        - port-resource-request
+        - port-resource-request-groups
+        - port-security
+        - port-security-groups-filtering
+        - project-id
+        - provider
+        - qos
+        - qos-fip
+        - quotas
+        - quota_details
+        - rbac-address-group
+        - rbac-address-scope
+        - rbac-policies
+        - rbac-security-groups
+        - rbac-subnetpool
+        - router
+        - router_availability_zone
+        - security-group
+        - security-groups-default-rules
+        - security-groups-normalized-cidr
+        - security-groups-remote-address-group
+        - segment
+        - service-type
+        - sorting
+        - standard-attr-description
+        - standard-attr-revisions
+        - standard-attr-segment
+        - standard-attr-tag
+        - standard-attr-timestamp
+        - stateful-security-group
+        - subnet_allocation
+        - subnet-dns-publish-fixed-ip
+        - subnet-service-types
+        - subnetpool-prefix-ops
+        - tag-ports-during-bulk-creation
+        - trunk
+        - trunk-details
+        - uplink-status-propagation
+      devstack_localrc:
+        NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_openvswitch) | join(',') }}"
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            network-feature-enabled:
+              available_features: "{{ network_available_features | join(',') }}"
+
+- job:
+    name: neutron-tempest-plugin-openvswitch-ubuntu-jammy-2025-1
+    parent: neutron-tempest-plugin-openvswitch-2025-1
+    nodeset: neutron-nested-virt-ubuntu-jammy
+
+- job:
+    name: neutron-tempest-plugin-openvswitch-iptables_hybrid-2025-1
+    parent: neutron-tempest-plugin-openvswitch-iptables_hybrid
+    nodeset: neutron-nested-virt-ubuntu-noble
+    override-checkout: stable/2025.1
+    vars:
+      network_api_extensions_common: *api_extensions
+      network_api_extensions_openvswitch: *api_extensions_openvswitch
+      network_available_features: *available_features
+      tempest_test_regex: "\
+          (^neutron_tempest_plugin.api)|\
+          (^neutron_tempest_plugin.scenario)|\
+          (^tempest.api.compute.servers.test_attach_interfaces)|\
+          (^tempest.api.compute.servers.test_multiple_create)"
+      # TODO(slaweq): remove trunks subport_connectivity test from blacklist
+      # when bug https://bugs.launchpad.net/neutron/+bug/1838760 will be fixed
+      # TODO(akatz): remove established tcp session verification test when the
+      # bug https://bugzilla.redhat.com/show_bug.cgi?id=1965036 will be fixed
+      tempest_exclude_regex: "\
+          (^neutron_tempest_plugin.scenario.test_trunk.TrunkTest.test_subport_connectivity)|\
+          (^neutron_tempest_plugin.scenario.test_security_groups.StatefulNetworkSecGroupTest.test_established_tcp_session_after_re_attachinging_sg)|\
+          (^neutron_tempest_plugin.scenario.test_security_groups.StatelessNetworkSecGroupTest.test_established_tcp_session_after_re_attachinging_sg)"
+      devstack_localrc:
+        NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_openvswitch) | join(',') }}"
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            network-feature-enabled:
+              available_features: "{{ network_available_features | join(',') }}"
+            neutron_plugin_options:
+              available_type_drivers: flat,vlan,local,vxlan
+              firewall_driver: iptables_hybrid
+
+- job:
+    name: neutron-tempest-plugin-ovn-enforce-scope-old-defaults-2025-1
+    parent: neutron-tempest-plugin-ovn-2025-1
+    nodeset: neutron-nested-virt-ubuntu-noble
+    override-checkout: stable/2025.1
+    vars:
+      devstack_localrc:
+        NEUTRON_ENFORCE_SCOPE: false
+
+- job:
+    name: neutron-tempest-plugin-ovn-2025-1
+    parent: neutron-tempest-plugin-ovn
+    nodeset: neutron-nested-virt-ubuntu-noble
+    override-checkout: stable/2025.1
+    vars:
+      network_api_extensions_ovn:
+        - vlan-transparent
+        - qinq
+        - external-gateway-multihoming
+      tempest_test_regex: "\
+          (^neutron_tempest_plugin.api)|\
+          (^neutron_tempest_plugin.scenario)|\
+          (^tempest.api.compute.servers.test_attach_interfaces)|\
+          (^tempest.api.compute.servers.test_multiple_create)"
+      devstack_localrc:
+        NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_ovn) | join(',') }}"
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            network-feature-enabled:
+              available_features: ""
+            neutron_plugin_options:
+              available_type_drivers: local,flat,vlan,geneve
+              is_igmp_snooping_enabled: True
+              firewall_driver: ovn
+
+- job:
+    name: neutron-tempest-plugin-ovn-ubuntu-jammy-2025-1
+    parent: neutron-tempest-plugin-ovn-2025-1
+    nodeset: neutron-nested-virt-ubuntu-jammy
+
+- job:
+    name: neutron-tempest-plugin-dvr-multinode-scenario-2025-1
+    parent: neutron-tempest-plugin-dvr-multinode-scenario
+    nodeset: openstack-two-node-noble
+    override-checkout: stable/2025.1
+    vars:
+      network_api_extensions_common: *api_extensions
+      network_api_extensions_dvr:
+        - dhcp_agent_scheduler
+        - dvr
+      devstack_localrc:
+        NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_dvr) | join(',') }}"
+
+- job:
+    name: neutron-tempest-plugin-designate-scenario-2025-1
+    parent: neutron-tempest-plugin-designate-scenario
+    nodeset: neutron-nested-virt-ubuntu-noble
+    override-checkout: stable/2025.1
+    vars:
+      network_api_extensions_common: *api_extensions
+
+- job:
+    name: neutron-tempest-plugin-sfc-2025-1
+    parent: neutron-tempest-plugin-sfc
+    nodeset: openstack-single-node-noble
+    override-checkout: stable/2025.1
+
+- job:
+    name: neutron-tempest-plugin-bgpvpn-bagpipe-2025-1
+    parent: neutron-tempest-plugin-bgpvpn-bagpipe
+    nodeset: openstack-single-node-noble
+    override-checkout: stable/2025.1
+
+- job:
+    name: neutron-tempest-plugin-dynamic-routing-2025-1
+    parent: neutron-tempest-plugin-dynamic-routing
+    nodeset: openstack-single-node-noble
+    override-checkout: stable/2025.1
+
+- job:
+    name: neutron-tempest-plugin-fwaas-2025-1
+    parent: neutron-tempest-plugin-fwaas-openvswitch
+    nodeset: openstack-single-node-noble
+    override-checkout: stable/2025.1
+
+- job:
+    name: neutron-tempest-plugin-vpnaas-2025-1
+    parent: neutron-tempest-plugin-vpnaas
+    nodeset: openstack-single-node-noble
+    override-checkout: stable/2025.1
+
+- job:
+    name: neutron-tempest-plugin-tap-as-a-service-2025-1
+    parent: neutron-tempest-plugin-tap-as-a-service
+    nodeset: openstack-single-node-noble
+    override-checkout: stable/2025.1
diff --git a/zuul.d/base-nested-switch.yaml b/zuul.d/base-nested-switch.yaml
index f8fa799..fa5217c 100644
--- a/zuul.d/base-nested-switch.yaml
+++ b/zuul.d/base-nested-switch.yaml
@@ -18,16 +18,26 @@
         nodes:
           - controller
 
-# Base nested switch job for 2023.1 and later
+- nodeset:
+    name: neutron-nested-virt-ubuntu-noble
+    nodes:
+      - name: controller
+        label: nested-virt-ubuntu-noble
+    groups:
+      - name: tempest
+        nodes:
+          - controller
+
+# Base nested switch job for 2025.1 and later
 - job:
     name: neutron-tempest-plugin-base-nested-switch
     parent: neutron-tempest-plugin-base
     abstract: true
     branches:
-      regex: ^(unmaintained|stable/(victoria|wallaby|xena|yoga|zed)).*$
+      regex: ^(unmaintained|stable/(victoria|wallaby|xena|yoga|zed|2023|2024)).*$
       negate: true
     # Comment nodeset and vars to switch back to non nested nodes
-    nodeset: neutron-nested-virt-ubuntu-jammy
+    nodeset: neutron-nested-virt-ubuntu-noble
     vars: &nested_virt_vars
       devstack_localrc:
         LIBVIRT_TYPE: kvm
@@ -39,6 +49,16 @@
         DEFAULT_IMAGE_NAME: cirros-0.5.3-x86_64-disk
         DEFAULT_IMAGE_FILE_NAME: cirros-0.5.3-x86_64-disk.img
 
+# Base nested switch job for 2023.1 till 2024.2
+- job:
+    name: neutron-tempest-plugin-base-nested-switch
+    parent: neutron-tempest-plugin-base
+    abstract: true
+    branches: ^(unmaintained|stable)/(2023|2024).*$
+    # Comment nodeset and vars to switch back to non nested nodes
+    nodeset: neutron-nested-virt-ubuntu-jammy
+    vars: *nested_virt_vars
+
 # Base nested switch job for yoga and zed
 - job:
     name: neutron-tempest-plugin-base-nested-switch
diff --git a/zuul.d/master_jobs.yaml b/zuul.d/master_jobs.yaml
index 90379a1..3d4f0e9 100644
--- a/zuul.d/master_jobs.yaml
+++ b/zuul.d/master_jobs.yaml
@@ -27,9 +27,9 @@
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
         PHYSICAL_NETWORK: public
         IMAGE_URLS: https://cloud-images.ubuntu.com/minimal/releases/focal/release/ubuntu-20.04-minimal-cloudimg-amd64.img
-        CIRROS_VERSION: 0.6.2
-        DEFAULT_IMAGE_NAME: cirros-0.6.2-x86_64-uec
-        DEFAULT_IMAGE_FILE_NAME: cirros-0.6.2-x86_64-uec.tar.gz
+        CIRROS_VERSION: 0.6.3
+        DEFAULT_IMAGE_NAME: cirros-0.6.3-x86_64-uec
+        DEFAULT_IMAGE_FILE_NAME: cirros-0.6.3-x86_64-uec.tar.gz
         ADVANCED_IMAGE_NAME: ubuntu-20.04-minimal-cloudimg-amd64
         ADVANCED_INSTANCE_TYPE: ntp_image_256M
         ADVANCED_INSTANCE_USER: ubuntu
@@ -37,14 +37,7 @@
         BUILD_TIMEOUT: 784
         # TODO(lucasagomes): Re-enable MOD_WSGI after
         # https://bugs.launchpad.net/neutron/+bug/1912359 is implemented
-        NEUTRON_DEPLOY_MOD_WSGI: false
-        # TODO(ihrachys): remove OVN_BUILD_FROM_SOURCE once the OS packages
-        # include at least OVN v22.03.3.
-        OVN_BUILD_FROM_SOURCE: True
-        # TODO(ihrachys): switch back to a tagged version when it's released
-        # OVN_BRANCH: "v22.03.3"
-        OVN_BRANCH: "36e3ab9b47e93af0599a818e9d6b2930e49473f0"
-        OVS_BRANCH: "2410b95597fcec5f733caf77febdb46f4ffacd27"
+        NEUTRON_DEPLOY_MOD_WSGI: true
       devstack_plugins:
         neutron: https://opendev.org/openstack/neutron.git
         neutron-tempest-plugin: https://opendev.org/openstack/neutron-tempest-plugin.git
@@ -98,6 +91,7 @@
         - port-resource-request
         - port-resource-request-groups
         - port-mac-address-regenerate
+        - port-trusted-vif
         - port-security
         - port-security-groups-filtering
         - project-id
@@ -148,6 +142,7 @@
         neutron-tag-ports-during-bulk-creation: true
         neutron-ndp-proxy: true
         neutron-subnet-external-network: true
+        neutron-port-trusted-vif: true
         br-ex-tcpdump: true
         br-int-flows: true
         # Cinder services
@@ -194,19 +189,20 @@
               image_is_advanced: true
               available_type_drivers: flat,geneve,vlan,gre,local,vxlan
               provider_net_base_segm_id: 1
+              snat_rules_apply_to_nested_networks: true
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
       - ^setup.cfg$
       - ^.*\.rst$
-      - ^.*\.conf\.sample$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^tools/.*$
       - ^tox.ini$
       - ^plugin.spec$
@@ -219,16 +215,8 @@
       - ^playbooks/.*functional.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-openvswitch
@@ -264,7 +252,6 @@
         Q_ML2_TENANT_NETWORK_TYPE: vxlan
         Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_openvswitch) | join(',') }}"
-        NEUTRON_DEPLOY_MOD_WSGI: true
       devstack_local_conf:
         post-config:
           $NEUTRON_CONF:
@@ -285,19 +272,20 @@
             neutron_plugin_options:
               available_type_drivers: flat,vlan,local,vxlan
               firewall_driver: openvswitch
+              snat_rules_apply_to_nested_networks: true
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
       - ^setup.cfg$
       - ^.*\.rst$
-      - ^.*\.conf\.sample$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^tools/.*$
       - ^tox.ini$
       - ^plugin.spec$
@@ -326,16 +314,8 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-openvswitch-iptables_hybrid
@@ -378,7 +358,6 @@
         Q_ML2_TENANT_NETWORK_TYPE: vxlan
         Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_openvswitch) | join(',') }}"
-        NEUTRON_DEPLOY_MOD_WSGI: true
       devstack_local_conf:
         post-config:
           $NEUTRON_CONF:
@@ -400,19 +379,20 @@
             neutron_plugin_options:
               available_type_drivers: flat,vlan,local,vxlan
               firewall_driver: iptables_hybrid
+              snat_rules_apply_to_nested_networks: true
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
       - ^setup.cfg$
       - ^.*\.rst$
-      - ^.*\.conf\.sample$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^tools/.*$
       - ^tox.ini$
       - ^plugin.spec$
@@ -442,33 +422,16 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
-    name: neutron-tempest-plugin-openvswitch-enforce-scope-old-defaults
-    parent: neutron-tempest-plugin-openvswitch
+    name: neutron-tempest-plugin-ovn-enforce-scope-old-defaults
+    parent: neutron-tempest-plugin-ovn
     vars:
       devstack_localrc:
         NEUTRON_ENFORCE_SCOPE: false
 
-
-# TODO(slaweq): remove that job's definition as soon as new job
-# "neutron-tempest-plugin-openvswitch-iptables_hybrid" will be used in the
-# neutron repo as a parent for a
-# "neutron-ovs-tempest-plugin-scenario-iptables_hybrid-nftables" job
-- job:
-    name: neutron-tempest-plugin-scenario-openvswitch-iptables_hybrid
-    parent: neutron-tempest-plugin-openvswitch-iptables_hybrid
-
 - job:
     name: neutron-tempest-plugin-openvswitch-distributed-dhcp
     parent: neutron-tempest-plugin-openvswitch
@@ -551,7 +514,7 @@
         Q_AGENT: linuxbridge
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_linuxbridge) | join(',') }}"
         Q_ML2_TENANT_NETWORK_TYPE: vxlan
-        Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch,linuxbridge
+        Q_ML2_PLUGIN_MECHANISM_DRIVERS: linuxbridge
       devstack_local_conf:
         post-config:
           $NEUTRON_CONF:
@@ -575,19 +538,20 @@
               available_type_drivers: flat,vlan,local,vxlan
               q_agent: linuxbridge
               firewall_driver: iptables
+              snat_rules_apply_to_nested_networks: true
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
       - ^setup.cfg$
       - ^.*\.rst$
-      - ^.*\.conf\.sample$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^tools/.*$
       - ^tox.ini$
       - ^plugin.spec$
@@ -617,23 +581,8 @@
       - ^playbooks/.*functional.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
-
-# TODO(slaweq): remove that job's definition as soon as new job
-# "neutron-tempest-plugin-linuxbridge" will be used in the neutron repo as
-# a parent for a "neutron-linuxbridge-tempest-plugin-scenario-nftables" job
-- job:
-    name: neutron-tempest-plugin-scenario-linuxbridge
-    parent: neutron-tempest-plugin-linuxbridge
 
 - job:
     name: neutron-tempest-plugin-ovn
@@ -643,16 +592,16 @@
     vars:
       network_api_extensions_ovn:
         - vlan-transparent
+        - qinq
         - external-gateway-multihoming
-      # TODO(jlibosva): Remove the NetworkWritableMtuTest test from the list
-      # once east/west fragmentation is supported in core OVN
-      tempest_exclude_regex: "\
-          (^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest)"
       devstack_localrc:
         Q_AGENT: ovn
         OVN_AGENT_EXTENSIONS: 'metadata'
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_ovn) | join(',') }}"
-        Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
+        # NOTE(ralonsoh): during the eventlet removal, the "logger" mech
+        # driver has been removed from this list. Re-add it once the removal
+        # is finished or the mech driver does not call monkey_patch().
+        Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn
         Q_ML2_PLUGIN_TYPE_DRIVERS: local,flat,vlan,geneve
         Q_ML2_TENANT_NETWORK_TYPE: geneve
         Q_USE_PROVIDERNET_FOR_PUBLIC: true
@@ -661,14 +610,6 @@
         OVN_DBS_LOG_LEVEL: dbg
         ENABLE_TLS: True
         OVN_IGMP_SNOOPING_ENABLE: True
-        # TODO(ihrachys): remove OVN_BUILD_FROM_SOURCE once the OS packages
-        # include at least OVN v22.03.3.
-        OVN_BUILD_FROM_SOURCE: True
-        # TODO(ihrachys): switch back to a tagged version when it's released
-        # OVN_BRANCH: "v22.03.3"
-        OVN_BRANCH: "36e3ab9b47e93af0599a818e9d6b2930e49473f0"
-        OVS_BRANCH: "2410b95597fcec5f733caf77febdb46f4ffacd27"
-        OVS_SYSCONFDIR: "/usr/local/etc/openvswitch"
       devstack_services:
         br-ex-tcpdump: true
         br-int-flows: true
@@ -702,19 +643,26 @@
             DEFAULT:
               enable_dvr: false
               vlan_transparent: true
+              vlan_qinq: true
           /$NEUTRON_CORE_PLUGIN_CONF:
             ml2:
               type_drivers: local,flat,vlan,geneve
             ml2_type_vlan:
               network_vlan_ranges: foo:1:10,public
+            ovn:
+              # This feature is available in OVN v24.03.4
+              # Latest Ubuntu 24.04 provides OVN v24.03.2
+              ovn_router_indirect_snat: false
         test-config:
           $TEMPEST_CONFIG:
             network-feature-enabled:
               available_features: "{{ network_available_features | join(',') }}"
             neutron_plugin_options:
+              provider_vlans: public,
               available_type_drivers: local,flat,vlan,geneve
               is_igmp_snooping_enabled: True
               firewall_driver: ovn
+              snat_rules_apply_to_nested_networks: false
       zuul_copy_output:
         '{{ devstack_base_dir }}/data/ovs': 'logs'
         '{{ devstack_base_dir }}/data/ovn': 'logs'
@@ -728,16 +676,16 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
       - ^setup.cfg$
       - ^.*\.rst$
-      - ^.*\.conf\.sample$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^tools/.*$
       - ^tox.ini$
       - ^plugin.spec$
@@ -771,16 +719,8 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 # TODO(slaweq): remove that job's definition as soon as new job
 # "neutron-tempest-plugin-ovn" will be used in the neutron-lib repo as
@@ -789,7 +729,7 @@
     name: neutron-tempest-plugin-api
     parent: neutron-tempest-plugin-ovn
 
-- job:
+- job:  # Needed only in Neutron stable/2024.2
     name: neutron-tempest-plugin-api-ovs-wsgi
     parent: neutron-tempest-plugin-openvswitch
     voting: false
@@ -797,7 +737,7 @@
       devstack_localrc:
         NEUTRON_DEPLOY_MOD_WSGI: true
 
-- job:
+- job:  # Needed only in Neutron stable/2024.2
     name: neutron-tempest-plugin-api-ovn-wsgi
     parent: neutron-tempest-plugin-ovn
     voting: false
@@ -807,7 +747,8 @@
 
 - job:
     name: neutron-tempest-plugin-dvr-multinode-scenario
-    parent: tempest-multinode-full
+    parent: tempest-multinode-full-py3
+    timeout: 10800
     description: |
         Perform setup for Neutron tempest tests in multinode with DVR scenario
     roles:
@@ -834,9 +775,9 @@
         USE_PYTHON3: true
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_dvr) | join(',') }}"
         PHYSICAL_NETWORK: default
-        CIRROS_VERSION: 0.6.2
-        DEFAULT_IMAGE_NAME: cirros-0.6.2-x86_64-uec
-        DEFAULT_IMAGE_FILE_NAME: cirros-0.6.2-x86_64-uec.tar.gz
+        CIRROS_VERSION: 0.6.3
+        DEFAULT_IMAGE_NAME: cirros-0.6.3-x86_64-uec
+        DEFAULT_IMAGE_FILE_NAME: cirros-0.6.3-x86_64-uec.tar.gz
         IMAGE_URLS: https://cloud-images.ubuntu.com/minimal/releases/focal/release/ubuntu-20.04-minimal-cloudimg-amd64.img
         ADVANCED_IMAGE_NAME: ubuntu-20.04-minimal-cloudimg-amd64
         ADVANCED_INSTANCE_TYPE: ntp_image_256M
@@ -855,15 +796,16 @@
       devstack_services:
         tls-proxy: true
         tempest: true
+        br-ex-tcpdump: true
+        br-int-flows: true
         # Disable OVN services
-        br-ex-tcpdump: false
-        br-int-flows: false
         ovn-controller: false
         ovn-northd: false
         ovs-vswitchd: false
         ovsdb-server: false
         q-ovn-metadata-agent: false
         # Neutron services
+        q-svc: true
         q-agt: true
         q-dhcp: true
         q-l3: true
@@ -937,12 +879,13 @@
               available_type_drivers: flat,geneve,vlan,gre,local,vxlan
               l3_agent_mode: dvr_snat
               firewall_driver: openvswitch
+              snat_rules_apply_to_nested_networks: false
     group-vars:
       subnode:
         devstack_services:
           tls-proxy: true
-          br-ex-tcpdump: false
-          br-int-flows: false
+          br-ex-tcpdump: true
+          br-int-flows: true
           # Disable OVN services
           ovn-controller: false
           ovn-northd: false
@@ -958,8 +901,11 @@
           neutron-log: true
           neutron-port-forwarding: true
           # Cinder services
+          c-api: false
           c-bak: false
+          c-sch: false
           c-vol: false
+          cinder: false
           # We don't need Swift to be run in the Neutron jobs
           s-account: false
           s-container: false
@@ -991,16 +937,16 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
       - ^setup.cfg$
       - ^.*\.rst$
-      - ^.*\.conf\.sample$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^tools/.*$
       - ^tox.ini$
       - ^plugin.spec$
@@ -1028,16 +974,8 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-designate-scenario
@@ -1068,16 +1006,16 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
       - ^setup.cfg$
       - ^.*\.rst$
-      - ^.*\.conf\.sample$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^tools/.*$
       - ^tox.ini$
       - ^plugin.spec$
@@ -1088,6 +1026,7 @@
       - ^neutron/scheduler/.*$
       - ^neutron/services/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/(bgpvpn|fwaas|neutron_dynamic_routing|sfc|tap_as_a_service|vpnaas).*$
       - ^neutron_tempest_plugin/services/bgp/.*$
       - ^rally-jobs/.*$
@@ -1121,16 +1060,8 @@
       - ^neutron/services/timestamp/.*$
       - ^neutron/services/trunk/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-sfc
@@ -1174,7 +1105,6 @@
         Q_ML2_TENANT_NETWORK_TYPE: vxlan
         Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_sfc) | join(',') }}"
-        NEUTRON_DEPLOY_MOD_WSGI: true
       # TODO(bcafarel): tests still fail from time to time in parallel
       # https://bugs.launchpad.net/neutron/+bug/1851500
       # https://bugs.launchpad.net/networking-sfc/+bug/1660366
@@ -1182,17 +1112,18 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
-      - ^.*\.conf\.sample$
       - ^setup.cfg$
       - ^.*\.rst$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/scenario/admin/.*$
       - ^neutron_tempest_plugin/scenario/test_.*$
       - ^neutron_tempest_plugin/(bgpvpn|fwaas|neutron_dynamic_routing|tap_as_a_service|vpnaas).*$
@@ -1208,16 +1139,8 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-bgpvpn-bagpipe
@@ -1254,24 +1177,24 @@
         BAGPIPE_DATAPLANE_DRIVER_IPVPN: "ovs"
         BAGPIPE_BGP_PEERS: "-"
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_bgpvpn) | join(',') }}"
-        NEUTRON_DEPLOY_MOD_WSGI: true
       devstack_plugins:
         networking-bgpvpn: https://git.openstack.org/openstack/networking-bgpvpn
         networking-bagpipe: https://git.openstack.org/openstack/networking-bagpipe
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
-      - ^.*\.conf\.sample$
       - ^setup.cfg$
       - ^.*\.rst$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/scenario/admin/.*$
       - ^neutron_tempest_plugin/scenario/test_.*$
       - ^neutron_tempest_plugin/(fwaas|neutron_dynamic_routing|sfc|tap_as_a_service|vpnaas).*$
@@ -1287,16 +1210,8 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-dynamic-routing
@@ -1327,17 +1242,18 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
-      - ^.*\.conf\.sample$
       - ^setup.cfg$
       - ^.*\.rst$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/scenario/admin/.*$
       - ^neutron_tempest_plugin/scenario/test_.*$
       - ^neutron_tempest_plugin/(bgpvpn|fwaas|sfc|tap_as_a_service|vpnaas).*$
@@ -1351,20 +1267,12 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
-    name: neutron-tempest-plugin-fwaas
-    parent: neutron-tempest-plugin-base
+    name: neutron-tempest-plugin-fwaas-ovn
+    parent: neutron-tempest-plugin-ovn
     timeout: 10800
     required-projects:
       - openstack/neutron-fwaas
@@ -1376,42 +1284,30 @@
       tempest_test_regex: ^neutron_tempest_plugin\.fwaas
       devstack_plugins:
         neutron-fwaas: https://opendev.org/openstack/neutron-fwaas.git
-        neutron-tempest-plugin: https://opendev.org/openstack/neutron-tempest-plugin.git
       network_api_extensions_fwaas:
         - fwaas_v2
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_fwaas) | join(',') }}"
-        Q_AGENT: openvswitch
-        Q_ML2_TENANT_NETWORK_TYPE: vxlan
-        Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
-        NEUTRON_DEPLOY_MOD_WSGI: true
-      devstack_services:
-        # Disable OVN services
-        br-ex-tcpdump: false
-        br-int-flows: false
-        ovn-controller: false
-        ovn-northd: false
-        q-ovn-metadata-agent: false
-        # Neutron services
-        q-agt: true
-        q-dhcp: true
-        q-meta: true
-        q-metering: true
-        q-l3: true
-        neutron-log: false
-    irrelevant-files:
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            fwaas:
+              driver: ovn
+    irrelevant-files: &fwaas_irrelevant_files
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
-      - ^.*\.conf\.sample$
       - ^setup.cfg$
       - ^.*\.rst$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/scenario/admin/.*$
       - ^neutron_tempest_plugin/scenario/test_.*$
       - ^neutron_tempest_plugin/(bgpvpn|neutron_dynamic_routing|sfc|tap_as_a_service|vpnaas).*$
@@ -1427,21 +1323,51 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
+
+- job:
+    name: neutron-tempest-plugin-fwaas-openvswitch
+    parent: neutron-tempest-plugin-openvswitch
+    required-projects:
+      - openstack/neutron-fwaas
+      - openstack/neutron
+      - openstack/neutron-tempest-plugin
+      - openstack/tempest
+    vars:
+      tempest_concurrency: 4
+      tempest_test_regex: ^neutron_tempest_plugin\.fwaas
+      devstack_plugins:
+        neutron-fwaas: https://opendev.org/openstack/neutron-fwaas.git
+      network_api_extensions_fwaas:
+        - fwaas_v2
+      devstack_localrc:
+        NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_fwaas) | join(',') }}"
+      devstack_services:
+        # Neutron services
+        q-agt: true
+        q-dhcp: true
+        q-meta: true
+        q-metering: true
+        q-l3: true
+        neutron-log: false
+      devstack_local_conf:
+        test-config:
+          $TEMPEST_CONFIG:
+            fwaas:
+              driver: openvswitch
+    irrelevant-files: *fwaas_irrelevant_files
+
+# TODO(slaweq):
+# Remove this alias once jobs in fwaas project will be moved to the new names
+- job:
+    name: neutron-tempest-plugin-fwaas
+    parent: neutron-tempest-plugin-fwaas-openvswitch
 
 - job:
     name: neutron-tempest-plugin-vpnaas
     parent: neutron-tempest-plugin-base
-    timeout: 3900
+    timeout: 5400
     required-projects:
       - openstack/neutron
       - openstack/neutron-vpnaas
@@ -1462,7 +1388,6 @@
         Q_AGENT: openvswitch
         Q_ML2_TENANT_NETWORK_TYPE: vxlan
         Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
-        NEUTRON_DEPLOY_MOD_WSGI: true
       devstack_services:
         # Disable OVN services
         br-ex-tcpdump: false
@@ -1481,17 +1406,18 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
-      - ^.*\.conf\.sample$
       - ^setup.cfg$
       - ^.*\.rst$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/scenario/admin/.*$
       - ^neutron_tempest_plugin/scenario/test_.*$
       - ^neutron_tempest_plugin/(bgpvpn|fwaas|neutron_dynamic_routing|sfc|tap_as_a_service).*$
@@ -1507,21 +1433,13 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-vpnaas-ovn
     parent: neutron-tempest-plugin-base
-    timeout: 3900
+    timeout: 5400
     required-projects:
       - openstack/neutron
       - openstack/neutron-vpnaas
@@ -1539,6 +1457,7 @@
       devstack_localrc:
         IPSEC_PACKAGE: strongswan
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_vpnaas) | join(',') }}"
+        Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn
       devstack_services:
         q-ovn-vpn-agent: true
       devstack_local_conf:
@@ -1551,17 +1470,18 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
-      - ^.*\.conf\.sample$
       - ^setup.cfg$
       - ^.*\.rst$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/scenario/admin/.*$
       - ^neutron_tempest_plugin/scenario/test_.*$
       - ^neutron_tempest_plugin/(bgpvpn|fwaas|neutron_dynamic_routing|sfc|tap_as_a_service).*$
@@ -1577,16 +1497,8 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
 
 - job:
     name: neutron-tempest-plugin-tap-as-a-service
@@ -1613,7 +1525,6 @@
         Q_AGENT: openvswitch
         Q_ML2_TENANT_NETWORK_TYPE: vxlan,vlan
         Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
-        NEUTRON_DEPLOY_MOD_WSGI: true
       devstack_local_conf:
         post-config:
           /$NEUTRON_CORE_PLUGIN_CONF:
@@ -1671,17 +1582,18 @@
     irrelevant-files:
       - ^\.pylintrc$
       - ^(test-|)requirements.txt$
-      - lower-constraints.txt
+      - ^lower-constraints.txt$
       - ^releasenotes/.*$
       - ^doc/.*$
-      - ^.*\.conf\.sample$
       - ^setup.cfg$
       - ^.*\.rst$
+      - ^.*\.sample$
       - ^neutron/locale/.*$
       - ^neutron/tests/unit/.*$
-      - ^neutron/tests/fullstack/.*
-      - ^neutron/tests/functional/.*
+      - ^neutron/tests/fullstack/.*$
+      - ^neutron/tests/functional/.*$
       - ^neutron_tempest_plugin/api/test_.*$
+      - ^neutron_tempest_plugin/api/admin/test_.*$
       - ^neutron_tempest_plugin/scenario/admin/.*$
       - ^neutron_tempest_plugin/scenario/test_.*$
       - ^neutron_tempest_plugin/(bgpvpn|fwaas|neutron_dynamic_routing|sfc|vpnaas).*$
@@ -1697,13 +1609,5 @@
       - ^playbooks/.*linuxbridge.*$
       - ^vagrant/.*$
       # Ignore everything except for zuul.d/project.yaml
-      - ^zuul.d/2023_1_jobs.yaml
-      - ^zuul.d/2023_2_jobs.yaml
-      - ^zuul.d/2024_1_jobs.yaml
+      - ^zuul.d/.*_jobs\.yaml$
       - ^zuul.d/base-nested-switch.yaml
-      - ^zuul.d/master_jobs.yaml
-      - ^zuul.d/victoria_jobs.yaml
-      - ^zuul.d/wallaby_jobs.yaml
-      - ^zuul.d/xena_jobs.yaml
-      - ^zuul.d/yoga_jobs.yaml
-      - ^zuul.d/zed_jobs.yaml
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 9a20f80..f9f70dd 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -3,29 +3,25 @@
     check:
       jobs:
         - neutron-tempest-plugin-openvswitch
-        - neutron-tempest-plugin-openvswitch-iptables_hybrid
-        - neutron-tempest-plugin-openvswitch-enforce-scope-old-defaults
         - neutron-tempest-plugin-ovn
-        - neutron-tempest-plugin-designate-scenario:
-            # TODO(slaweq) make job voting again once bug
-            # https://bugs.launchpad.net/designate/+bug/2072627 will be fixed
-            voting: false
+        - neutron-tempest-plugin-designate-scenario
     gate:
       jobs:
         - neutron-tempest-plugin-openvswitch
         - neutron-tempest-plugin-ovn
-        - neutron-tempest-plugin-openvswitch-iptables_hybrid
-        - neutron-tempest-plugin-openvswitch-enforce-scope-old-defaults
     #TODO(slaweq): Move neutron-tempest-plugin-dvr-multinode-scenario out of
     #              the experimental queue when it will be more stable
     experimental:
       jobs:
-        - neutron-tempest-plugin-linuxbridge
         - neutron-tempest-plugin-dvr-multinode-scenario
         - neutron-tempest-plugin-openvswitch-distributed-dhcp
         - neutron-tempest-plugin-openvswitch-iptables_hybrid-distributed-dhcp
-        - neutron-tempest-plugin-api-ovs-wsgi
-        - neutron-tempest-plugin-api-ovn-wsgi
+        - neutron-tempest-plugin-ovn-enforce-scope-old-defaults
+        - neutron-tempest-plugin-openvswitch-iptables_hybrid
+    periodic:
+      jobs:
+        - neutron-tempest-plugin-ovn-enforce-scope-old-defaults
+        - neutron-tempest-plugin-openvswitch-iptables_hybrid
 
 
 - project-template:
@@ -143,24 +139,6 @@
         - neutron-tempest-plugin-dvr-multinode-scenario-2023-1
 
 - project-template:
-    name: neutron-tempest-plugin-jobs-2023-2
-    check:
-      jobs:
-        - neutron-tempest-plugin-openvswitch-2023-2
-        - neutron-tempest-plugin-openvswitch-iptables_hybrid-2023-2
-        - neutron-tempest-plugin-ovn-2023-2
-        - neutron-tempest-plugin-designate-scenario-2023-2
-    gate:
-      jobs:
-        - neutron-tempest-plugin-ovn-2023-2
-    #TODO(slaweq): Move neutron-tempest-plugin-dvr-multinode-scenario out of
-    #              the experimental queue when it will be more stable
-    experimental:
-      jobs:
-        - neutron-tempest-plugin-linuxbridge-2023-2
-        - neutron-tempest-plugin-dvr-multinode-scenario-2023-2
-
-- project-template:
     name: neutron-tempest-plugin-jobs-2024-1
     check:
       jobs:
@@ -178,50 +156,92 @@
         - neutron-tempest-plugin-linuxbridge-2024-1
         - neutron-tempest-plugin-dvr-multinode-scenario-2024-1
 
+- project-template:
+    name: neutron-tempest-plugin-jobs-2024-2
+    check:
+      jobs:
+        - neutron-tempest-plugin-openvswitch-2024-2
+        - neutron-tempest-plugin-openvswitch-iptables_hybrid-2024-2
+        - neutron-tempest-plugin-ovn-2024-2
+        - neutron-tempest-plugin-designate-scenario-2024-2
+    gate:
+      jobs:
+        - neutron-tempest-plugin-ovn-2024-2
+    #TODO(slaweq): Move neutron-tempest-plugin-dvr-multinode-scenario out of
+    #              the experimental queue when it will be more stable
+    experimental:
+      jobs:
+        - neutron-tempest-plugin-linuxbridge-2024-2
+        - neutron-tempest-plugin-dvr-multinode-scenario-2024-2
+
+- project-template:
+    name: neutron-tempest-plugin-jobs-2025-1
+    check:
+      jobs:
+        - neutron-tempest-plugin-openvswitch-2025-1
+        - neutron-tempest-plugin-openvswitch-iptables_hybrid-2025-1
+        - neutron-tempest-plugin-ovn-2025-1
+        - neutron-tempest-plugin-designate-scenario-2025-1
+        - neutron-tempest-plugin-openvswitch-ubuntu-jammy-2025-1
+        - neutron-tempest-plugin-ovn-ubuntu-jammy-2025-1
+    gate:
+      jobs:
+        - neutron-tempest-plugin-ovn-2025-1
+    #TODO(slaweq): Move neutron-tempest-plugin-dvr-multinode-scenario out of
+    #              the experimental queue when it will be more stable
+    experimental:
+      jobs:
+        - neutron-tempest-plugin-dvr-multinode-scenario-2025-1
+
 - project:
     templates:
       - build-openstack-docs-pti
       - neutron-tempest-plugin-jobs
-      - neutron-tempest-plugin-jobs-2023-1
-      - neutron-tempest-plugin-jobs-2023-2
       - neutron-tempest-plugin-jobs-2024-1
+      - neutron-tempest-plugin-jobs-2024-2
+      - neutron-tempest-plugin-jobs-2025-1
       - check-requirements
       - tempest-plugin-jobs
       - release-notes-jobs-python3
     check:
       jobs:
-        - neutron-tempest-plugin-sfc:
-            # Note(lajoskatona): make it voting when #2068727
-            # is fixed.
-            voting: false
-        - neutron-tempest-plugin-sfc-2023-1
-        - neutron-tempest-plugin-sfc-2023-2
+        - neutron-tempest-plugin-sfc
         - neutron-tempest-plugin-sfc-2024-1
+        - neutron-tempest-plugin-sfc-2024-2
+        - neutron-tempest-plugin-sfc-2025-1
         - neutron-tempest-plugin-bgpvpn-bagpipe
-        - neutron-tempest-plugin-bgpvpn-bagpipe-2023-1
-        - neutron-tempest-plugin-bgpvpn-bagpipe-2023-2
         - neutron-tempest-plugin-bgpvpn-bagpipe-2024-1
-        - neutron-tempest-plugin-dynamic-routing
-        - neutron-tempest-plugin-dynamic-routing-2023-1
-        - neutron-tempest-plugin-dynamic-routing-2023-2
+        - neutron-tempest-plugin-bgpvpn-bagpipe-2024-2
+        - neutron-tempest-plugin-bgpvpn-bagpipe-2025-1
+        - neutron-tempest-plugin-dynamic-routing:
+            # TODO(ralonsoh): this job is temporarily disabled; it will be
+            # restored once [1] is merged. This patch has been successfully
+            # tested in [2]. This job is removed from the gate queue,
+            # thus **remember to restore it in this queue too**.
+            # [1]https://review.opendev.org/c/openstack/neutron/+/941202
+            # [2]https://review.opendev.org/c/openstack/neutron-tempest-plugin/+/940906
+            voting: false
         - neutron-tempest-plugin-dynamic-routing-2024-1
-        - neutron-tempest-plugin-fwaas
-        - neutron-tempest-plugin-fwaas-2023-1
-        - neutron-tempest-plugin-fwaas-2023-2
+        - neutron-tempest-plugin-dynamic-routing-2024-2
+        - neutron-tempest-plugin-dynamic-routing-2025-1
+        - neutron-tempest-plugin-fwaas-ovn
+        - neutron-tempest-plugin-fwaas-openvswitch
         - neutron-tempest-plugin-fwaas-2024-1
+        - neutron-tempest-plugin-fwaas-2024-2
+        - neutron-tempest-plugin-fwaas-2025-1
         - neutron-tempest-plugin-vpnaas
         - neutron-tempest-plugin-vpnaas-ovn
-        - neutron-tempest-plugin-vpnaas-2023-1
-        - neutron-tempest-plugin-vpnaas-2023-2
         - neutron-tempest-plugin-vpnaas-2024-1
+        - neutron-tempest-plugin-vpnaas-2024-2
+        - neutron-tempest-plugin-vpnaas-2025-1
         - neutron-tempest-plugin-tap-as-a-service
-        - neutron-tempest-plugin-tap-as-a-service-2023-1
-        - neutron-tempest-plugin-tap-as-a-service-2023-2
         - neutron-tempest-plugin-tap-as-a-service-2024-1
+        - neutron-tempest-plugin-tap-as-a-service-2024-2
+        - neutron-tempest-plugin-tap-as-a-service-2025-1
 
     gate:
       jobs:
+        - neutron-tempest-plugin-sfc
         - neutron-tempest-plugin-bgpvpn-bagpipe
-        - neutron-tempest-plugin-dynamic-routing
-        - neutron-tempest-plugin-fwaas
+        - neutron-tempest-plugin-fwaas-ovn
         - neutron-tempest-plugin-vpnaas-ovn
diff --git a/zuul.d/victoria_jobs.yaml b/zuul.d/victoria_jobs.yaml
index 291e01d..c7bc886 100644
--- a/zuul.d/victoria_jobs.yaml
+++ b/zuul.d/victoria_jobs.yaml
@@ -207,6 +207,7 @@
       network_available_features: *available_features
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
         # NOTE(bcafarel) guestmount binary not available on host OS
         IMAGE_URLS: https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-amd64.img
         ADVANCED_IMAGE_NAME: ubuntu-18.04-server-cloudimg-amd64
@@ -231,6 +232,8 @@
           (^neutron_tempest_plugin.scenario)|\
           (^tempest.api.compute.servers.test_attach_interfaces)|\
           (^tempest.api.compute.servers.test_multiple_create)"
+      # NOTE(ralonsoh): ``NetworkWritableMtuTest`` excluded because of https://bugs.launchpad.net/neutron/+bug/2082344
+      tempest_exclude_regex: "^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest.*"
       network_api_extensions: *api_extensions
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
@@ -242,6 +245,7 @@
         CUSTOMIZE_IMAGE: false
         OVN_BRANCH: "v21.06.0"
         OVS_BRANCH: "a4b04276ab5934d087669ff2d191a23931335c87"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_services:
         q-ovn-metadata-agent: true
         q-ovn-agent: false
@@ -314,6 +318,8 @@
     required-projects: *required-projects-victoria
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-vpnaas-victoria
diff --git a/zuul.d/wallaby_jobs.yaml b/zuul.d/wallaby_jobs.yaml
index 7df6876..5b35bbc 100644
--- a/zuul.d/wallaby_jobs.yaml
+++ b/zuul.d/wallaby_jobs.yaml
@@ -9,6 +9,8 @@
         override-checkout: 1.8.0
       - openstack/tempest
     vars:
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
       tempest_concurrency: 4
       tempest_test_regex: ^neutron_tempest_plugin\.api
       # TODO(slaweq): find a way to put this list of extensions in
@@ -158,6 +160,7 @@
       network_available_features: *available_features
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -174,11 +177,14 @@
           (^neutron_tempest_plugin.scenario)|\
           (^tempest.api.compute.servers.test_attach_interfaces)|\
           (^tempest.api.compute.servers.test_multiple_create)"
+      # NOTE(ralonsoh): ``NetworkWritableMtuTest`` excluded because of https://bugs.launchpad.net/neutron/+bug/2082344
+      tempest_exclude_regex: "^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest.*"
       network_api_extensions: *api_extensions
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
         OVN_BRANCH: "v21.06.0"
         OVS_BRANCH: "a4b04276ab5934d087669ff2d191a23931335c87"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_services:
         q-ovn-metadata-agent: true
         q-ovn-agent: false
@@ -212,6 +218,8 @@
         override-checkout: 0.16.0
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-sfc-wallaby
@@ -243,6 +251,8 @@
     required-projects: *required-projects-wallaby
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-vpnaas-wallaby
diff --git a/zuul.d/xena_jobs.yaml b/zuul.d/xena_jobs.yaml
index e1e13c4..b03b6c5 100644
--- a/zuul.d/xena_jobs.yaml
+++ b/zuul.d/xena_jobs.yaml
@@ -9,11 +9,14 @@
         override-checkout: 2.3.0
       - openstack/tempest
     vars:
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
       tempest_concurrency: 4
       tempest_test_regex: ^neutron_tempest_plugin\.api
       # TODO(slaweq): find a way to put this list of extensions in
       # neutron repository and keep it different per branch,
       # then it could be removed from here
+      tempest_exclude_regex: "^neutron_tempest_plugin.api.admin.test_logging.LoggingTestJSON.*"
       network_api_extensions_common: &api_extensions
         - address-group
         - address-scope
@@ -153,6 +156,7 @@
       network_available_features: *available_features
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -169,9 +173,12 @@
           (^neutron_tempest_plugin.scenario)|\
           (^tempest.api.compute.servers.test_attach_interfaces)|\
           (^tempest.api.compute.servers.test_multiple_create)"
+      # NOTE(ralonsoh): ``NetworkWritableMtuTest`` excluded because of https://bugs.launchpad.net/neutron/+bug/2082344
+      tempest_exclude_regex: "^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest.*"
       network_api_extensions: *api_extensions
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_services:
         q-ovn-metadata-agent: true
         q-ovn-agent: false
@@ -199,6 +206,8 @@
     required-projects: *required-projects-xena
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-sfc-xena
diff --git a/zuul.d/yoga_jobs.yaml b/zuul.d/yoga_jobs.yaml
index 6e0ddcd..be6c65e 100644
--- a/zuul.d/yoga_jobs.yaml
+++ b/zuul.d/yoga_jobs.yaml
@@ -9,11 +9,14 @@
         override-checkout: 2.6.0
       - openstack/tempest
     vars:
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
       tempest_concurrency: 4
       tempest_test_regex: ^neutron_tempest_plugin\.api
       # TODO(slaweq): find a way to put this list of extensions in
       # neutron repository and keep it different per branch,
       # then it could be removed from here
+      tempest_exclude_regex: "^neutron_tempest_plugin.api.admin.test_logging.LoggingTestJSON.*"
       network_api_extensions_common: &api_extensions
         - address-group
         - address-scope
@@ -158,6 +161,7 @@
       network_available_features: *available_features
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ network_api_extensions | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -175,11 +179,20 @@
           (^neutron_tempest_plugin.scenario)|\
           (^tempest.api.compute.servers.test_attach_interfaces)|\
           (^tempest.api.compute.servers.test_multiple_create)"
+      # NOTE(ralonsoh): tests disabled because of https://bugs.launchpad.net/neutron/+bug/2082070
+      # NOTE(ralonsoh): ``NetworkWritableMtuTest`` excluded because of https://bugs.launchpad.net/neutron/+bug/2082344
+      tempest_exclude_regex: "\
+          (neutron_tempest_plugin.scenario.test_security_groups.StatelessNetworkSecGroupIPv4Test.test_connectivity_between_vms_using_different_sec_groups)|\
+          (neutron_tempest_plugin.scenario.test_security_groups.StatelessNetworkSecGroupIPv4Test.test_packets_of_any_connection_state_can_reach_dest)|\
+          (neutron_tempest_plugin.scenario.test_vlan_transparency.VlanTransparencyTest.test_vlan_transparent_allowed_address_pairs)|\
+          (neutron_tempest_plugin.scenario.test_vlan_transparency.VlanTransparencyTest.test_vlan_transparent_port_sec_disabled)|\
+          (neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest.*)"
       network_api_extensions: *api_extensions
       network_api_extensions_ovn:
         - vlan-transparent
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions + network_api_extensions_ovn) | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_services:
         q-ovn-metadata-agent: true
         q-ovn-agent: false
@@ -208,6 +221,8 @@
     nodeset: neutron-nested-virt-ubuntu-focal
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-sfc-yoga
diff --git a/zuul.d/zed_jobs.yaml b/zuul.d/zed_jobs.yaml
index 176527d..9ae2d87 100644
--- a/zuul.d/zed_jobs.yaml
+++ b/zuul.d/zed_jobs.yaml
@@ -168,6 +168,7 @@
       network_available_features: *available_features
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_linuxbridge) | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_local_conf:
         test-config:
           $TEMPEST_CONFIG:
@@ -186,13 +187,20 @@
           (^neutron_tempest_plugin.scenario)|\
           (^tempest.api.compute.servers.test_attach_interfaces)|\
           (^tempest.api.compute.servers.test_multiple_create)"
+      # NOTE(ralonsoh): tests disabled because of https://bugs.launchpad.net/neutron/+bug/2082070
+      # NOTE(ralonsoh): ``NetworkWritableMtuTest`` excluded because of https://bugs.launchpad.net/neutron/+bug/2082344
       tempest_exclude_regex: "\
-          (^neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest)"
+          (neutron_tempest_plugin.scenario.test_security_groups.StatelessNetworkSecGroupIPv4Test.test_connectivity_between_vms_using_different_sec_groups)|\
+          (neutron_tempest_plugin.scenario.test_security_groups.StatelessNetworkSecGroupIPv4Test.test_packets_of_any_connection_state_can_reach_dest)|\
+          (neutron_tempest_plugin.scenario.test_vlan_transparency.VlanTransparencyTest.test_vlan_transparent_allowed_address_pairs)|\
+          (neutron_tempest_plugin.scenario.test_vlan_transparency.VlanTransparencyTest.test_vlan_transparent_port_sec_disabled)|\
+          (neutron_tempest_plugin.scenario.test_mtu.NetworkWritableMtuTest.*)"
       network_api_extensions: *api_extensions
       network_api_extensions_ovn:
         - vlan-transparent
       devstack_localrc:
         NETWORK_API_EXTENSIONS: "{{ (network_api_extensions + network_api_extensions_ovn) | join(',') }}"
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_services:
         q-ovn-metadata-agent: true
         q-ovn-agent: false
@@ -217,10 +225,18 @@
     name: neutron-tempest-plugin-designate-scenario-zed
     parent: neutron-tempest-plugin-designate-scenario
     override-checkout: unmaintained/zed
-    required-projects: *required-projects-zed
+    required-projects:
+      - openstack/neutron
+      - name: openstack/neutron-tempest-plugin
+        override-checkout: zed-last
+      - openstack/tempest
+      - name: openstack/designate-tempest-plugin
+        override-checkout: zed-last
     nodeset: neutron-nested-virt-ubuntu-focal
     vars:
       network_api_extensions_common: *api_extensions
+      devstack_localrc:
+        NEUTRON_DEPLOY_MOD_WSGI: false
 
 - job:
     name: neutron-tempest-plugin-sfc-zed
@@ -257,6 +273,7 @@
         Q_AGENT: openvswitch
         Q_ML2_TENANT_NETWORK_TYPE: vxlan
         Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
+        NEUTRON_DEPLOY_MOD_WSGI: false
       devstack_services:
         # Disable OVN services
         br-ex-tcpdump: false
@@ -277,7 +294,7 @@
 
 - job:
     name: neutron-tempest-plugin-fwaas-zed
-    parent: neutron-tempest-plugin-fwaas
+    parent: neutron-tempest-plugin-fwaas-openvswitch
     nodeset: openstack-single-node-focal
     override-checkout: unmaintained/zed
     required-projects: *required-projects-zed