get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.0/patches/2197636/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2197636,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2197636/?format=api",
    "project": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/1.0/projects/68/?format=api",
        "name": "Open Virtual Network development",
        "link_name": "ovn",
        "list_id": "ovs-dev.openvswitch.org",
        "list_email": "ovs-dev@openvswitch.org",
        "web_url": "http://openvswitch.org/",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20260218094857.1378115-2-dceara@redhat.com>",
    "date": "2026-02-18T09:48:55",
    "name": "[ovs-dev,1/3] northd: controller: Remove EVPN iface name defaults.",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "8f2d2053fc11f3901326e78f15807422db33879f",
    "submitter": {
        "id": 76591,
        "url": "http://patchwork.ozlabs.org/api/1.0/people/76591/?format=api",
        "name": "Dumitru Ceara",
        "email": "dceara@redhat.com"
    },
    "delegate": {
        "id": 132642,
        "url": "http://patchwork.ozlabs.org/api/1.0/users/132642/?format=api",
        "username": "amusil",
        "first_name": "Ales",
        "last_name": "Musil",
        "email": "amusil@redhat.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260218094857.1378115-2-dceara@redhat.com/mbox/",
    "series": [
        {
            "id": 492526,
            "url": "http://patchwork.ozlabs.org/api/1.0/series/492526/?format=api",
            "date": "2026-02-18T09:48:54",
            "name": "Make EVPN support stable.",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/492526/mbox/"
        }
    ],
    "check": "success",
    "checks": "http://patchwork.ozlabs.org/api/patches/2197636/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "ovs-dev@openvswitch.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "ovs-dev@lists.linuxfoundation.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=B0s1rxkT;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)",
            "smtp2.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=B0s1rxkT",
            "smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com",
            "smtp1.osuosl.org;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.a=rsa-sha256 header.s=mimecast20190719 header.b=B0s1rxkT"
        ],
        "Received": [
            "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fGBYS5DbNz1xpl\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 20:49:16 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp2.osuosl.org (Postfix) with ESMTP id 1539440262;\n\tWed, 18 Feb 2026 09:49:15 +0000 (UTC)",
            "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id nFB27Lzn2H87; Wed, 18 Feb 2026 09:49:12 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp2.osuosl.org (Postfix) with ESMTPS id 555CE40251;\n\tWed, 18 Feb 2026 09:49:12 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 3E0A0C0035;\n\tWed, 18 Feb 2026 09:49:12 +0000 (UTC)",
            "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 8DD8CC0033\n for <ovs-dev@openvswitch.org>; Wed, 18 Feb 2026 09:49:11 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 7430C80DAF\n for <ovs-dev@openvswitch.org>; Wed, 18 Feb 2026 09:49:11 +0000 (UTC)",
            "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id YvMTCPqEIVRB for <ovs-dev@openvswitch.org>;\n Wed, 18 Feb 2026 09:49:09 +0000 (UTC)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 88A9580DCA\n for <ovs-dev@openvswitch.org>; Wed, 18 Feb 2026 09:49:08 +0000 (UTC)",
            "from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-668-qpRHEGmzOsWbG1v6GLiugw-1; Wed,\n 18 Feb 2026 04:49:05 -0500",
            "from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 85A1F195411D\n for <ovs-dev@openvswitch.org>; Wed, 18 Feb 2026 09:49:04 +0000 (UTC)",
            "from cecil-rh.redhat.com (unknown [10.45.224.198])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 6418919560AD\n for <ovs-dev@openvswitch.org>; Wed, 18 Feb 2026 09:49:02 +0000 (UTC)"
        ],
        "X-Virus-Scanned": [
            "amavis at osuosl.org",
            "amavis at osuosl.org"
        ],
        "X-Comment": "SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ",
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 smtp2.osuosl.org 555CE40251",
            "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 88A9580DCA"
        ],
        "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=dceara@redhat.com;\n receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org 88A9580DCA",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1771408147;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=L/ATNYZB+mpuGz5jBsA5+3QvKJMRYyvoOqpR+njM4hE=;\n b=B0s1rxkTb77P203wPRGim0A2e4Bv7Ef1OqTr6M6MIvOddhep+Y4bVmCXNaP4ccJIBMVHv9\n yJRku447ktp09GgYc5ChTa5Ldigo1su7qvNuOQSzykSHDm5wLnmte3Tkb6CYhY5/ChIaQ4\n 32/w92j85wXPMLr+fl79KSqz8U3G3IE=",
        "X-MC-Unique": "qpRHEGmzOsWbG1v6GLiugw-1",
        "X-Mimecast-MFC-AGG-ID": "qpRHEGmzOsWbG1v6GLiugw_1771408144",
        "To": "ovs-dev@openvswitch.org",
        "Date": "Wed, 18 Feb 2026 10:48:55 +0100",
        "Message-ID": "<20260218094857.1378115-2-dceara@redhat.com>",
        "In-Reply-To": "<20260218094857.1378115-1-dceara@redhat.com>",
        "References": "<20260218094857.1378115-1-dceara@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.12",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "8_D6_L6T_FkFVo-2pQSMjBU7NMmQ_rmA4UxTrvMc1Qo_1771408144",
        "X-Mimecast-Originator": "redhat.com",
        "Subject": "[ovs-dev] [PATCH ovn 1/3] northd: controller: Remove EVPN iface\n name defaults.",
        "X-BeenThere": "ovs-dev@openvswitch.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "<ovs-dev.openvswitch.org>",
        "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>",
        "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>",
        "List-Post": "<mailto:ovs-dev@openvswitch.org>",
        "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>",
        "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>",
        "From": "Dumitru Ceara via dev <ovs-dev@openvswitch.org>",
        "Reply-To": "Dumitru Ceara <dceara@redhat.com>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "ovs-dev-bounces@openvswitch.org",
        "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>"
    },
    "content": "The default values didn't allow dual-stack deployments.  Moreover, they\nmade very specific assumptions and would likely be overridden by the CMS\nin all deployments.\n\nInstead make them mandatory if dynamic-routing-vni is configured for an\nEVPN enabled logical switch.\n\nAlso:\n- made sure dynamic-routing-*-ifname are ignored if VNI not set (this is\n  what our docs said)\n- moved the man page description of the options in the right place, in a\n  group listing all EVPN options\n\nReported-at: https://issues.redhat.com/browse/FDP-3136\nSigned-off-by: Dumitru Ceara <dceara@redhat.com>\n---\nNOTE: As discussed on-list [0] this patch targets 26.03 (main branch\nbefore hard freeze).\n\n[0] https://mail.openvswitch.org/pipermail/ovs-dev/2026-February/430230.html\n---\n controller/neighbor.c               | 67 ++++++++++++-----------\n northd/en-datapath-logical-switch.c | 85 +++++++++++++++++------------\n ovn-nb.xml                          | 62 +++++++++++++--------\n tests/multinode.at                  | 14 +++--\n tests/ovn.at                        | 82 ++++++++++++++++++++++++++++\n tests/system-common-macros.at       |  9 +--\n 6 files changed, 217 insertions(+), 102 deletions(-)",
    "diff": "diff --git a/controller/neighbor.c b/controller/neighbor.c\nindex eae5eadb24..57df1e90c9 100644\n--- a/controller/neighbor.c\n+++ b/controller/neighbor.c\n@@ -28,12 +28,6 @@\n \n VLOG_DEFINE_THIS_MODULE(neighbor);\n \n-static const char *neighbor_interface_prefixes[] = {\n-    [NEIGH_IFACE_BRIDGE] = \"br-\",\n-    [NEIGH_IFACE_VXLAN] = \"vxlan-\",\n-    [NEIGH_IFACE_LOOPBACK] = \"lo-\",\n-};\n-\n static const char *neighbor_opt_name[] = {\n     [NEIGH_IFACE_BRIDGE] = \"dynamic-routing-bridge-ifname\",\n     [NEIGH_IFACE_VXLAN] = \"dynamic-routing-vxlan-ifname\",\n@@ -87,17 +81,16 @@ advertise_neigh_find(const struct hmap *neighbors, struct eth_addr mac,\n \n static void\n neigh_parse_device_name(struct sset *device_names, struct local_datapath *ld,\n-                        enum neighbor_interface_type type, uint32_t vni)\n+                        enum neighbor_interface_type type)\n {\n     const char *names = smap_get_def(&ld->datapath->external_ids,\n                                      neighbor_opt_name[type], \"\");\n     sset_from_delimited_string(device_names, names, \",\");\n     if (sset_is_empty(device_names)) {\n-        /* Default device name if not specified. */\n-        char if_name[IFNAMSIZ + 1];\n-        snprintf(if_name, sizeof if_name, \"%s%\"PRIu32,\n-                 neighbor_interface_prefixes[type], vni);\n-        sset_add(device_names, if_name);\n+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);\n+        VLOG_WARN_RL(&rl, \"Datapath \"UUID_FMT\" misses %s\",\n+                     UUID_ARGS(&ld->datapath->header_.uuid),\n+                     neighbor_opt_name[type]);\n     }\n }\n \n@@ -123,7 +116,7 @@ neighbor_run(struct neighbor_ctx_in *n_ctx_in,\n         }\n \n         struct sset device_names;\n-        neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_VXLAN, vni);\n+        neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_VXLAN);\n         const char *name;\n         SSET_FOR_EACH (name, &device_names) {\n             struct neighbor_interface_monitor *vxlan =\n@@ -133,49 +126,57 @@ neighbor_run(struct neighbor_ctx_in *n_ctx_in,\n         }\n         sset_destroy(&device_names);\n \n-        neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_LOOPBACK, vni);\n+        struct neighbor_interface_monitor *lo = NULL;\n+        neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_LOOPBACK);\n         if (sset_count(&device_names) > 1) {\n             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);\n             VLOG_WARN_RL(&rl, \"Datapath \"UUID_FMT\" too many names provided \"\n                               \"for loopback device\",\n                          UUID_ARGS(&ld->datapath->header_.uuid));\n         }\n-        struct neighbor_interface_monitor *lo =\n-            neighbor_interface_monitor_alloc(NEIGH_AF_BRIDGE,\n-                                             NEIGH_IFACE_LOOPBACK, vni,\n-                                             SSET_FIRST(&device_names));\n-        vector_push(n_ctx_out->monitored_interfaces, &lo);\n+\n+        if (!sset_is_empty(&device_names)) {\n+            lo = neighbor_interface_monitor_alloc(NEIGH_AF_BRIDGE,\n+                                                  NEIGH_IFACE_LOOPBACK, vni,\n+                                                  SSET_FIRST(&device_names));\n+            vector_push(n_ctx_out->monitored_interfaces, &lo);\n+        }\n         sset_destroy(&device_names);\n \n-        neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_BRIDGE, vni);\n+        struct neighbor_interface_monitor *br_v4 = NULL;\n+        struct neighbor_interface_monitor *br_v6 = NULL;\n+        neigh_parse_device_name(&device_names, ld, NEIGH_IFACE_BRIDGE);\n         if (sset_count(&device_names) > 1) {\n             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);\n             VLOG_WARN_RL(&rl, \"Datapath \"UUID_FMT\" too many names provided \"\n                               \"for bridge device\",\n                          UUID_ARGS(&ld->datapath->header_.uuid));\n         }\n-        struct neighbor_interface_monitor *br_v4 =\n-            neighbor_interface_monitor_alloc(NEIGH_AF_INET,\n-                                             NEIGH_IFACE_BRIDGE, vni,\n-                                             SSET_FIRST(&device_names));\n-        vector_push(n_ctx_out->monitored_interfaces, &br_v4);\n-\n-        struct neighbor_interface_monitor *br_v6 =\n-            neighbor_interface_monitor_alloc(NEIGH_AF_INET6,\n-                                             NEIGH_IFACE_BRIDGE, vni,\n-                                             SSET_FIRST(&device_names));\n-        vector_push(n_ctx_out->monitored_interfaces, &br_v6);\n+\n+        if (!sset_is_empty(&device_names)) {\n+            br_v4 =\n+                neighbor_interface_monitor_alloc(NEIGH_AF_INET,\n+                                                 NEIGH_IFACE_BRIDGE, vni,\n+                                                 SSET_FIRST(&device_names));\n+            vector_push(n_ctx_out->monitored_interfaces, &br_v4);\n+\n+            br_v6 =\n+                neighbor_interface_monitor_alloc(NEIGH_AF_INET6,\n+                                                 NEIGH_IFACE_BRIDGE, vni,\n+                                                 SSET_FIRST(&device_names));\n+            vector_push(n_ctx_out->monitored_interfaces, &br_v6);\n+        }\n         sset_destroy(&device_names);\n \n         enum neigh_redistribute_mode mode =\n             parse_neigh_dynamic_redistribute(&ld->datapath->external_ids);\n-        if (nrm_mode_FDB_is_set(mode)) {\n+        if (nrm_mode_FDB_is_set(mode) && lo) {\n             neighbor_collect_mac_to_advertise(n_ctx_in,\n                                               &lo->announced_neighbors,\n                                               n_ctx_out->advertised_pbs,\n                                               ld->datapath);\n         }\n-        if (nrm_mode_IP_is_set(mode)) {\n+        if (nrm_mode_IP_is_set(mode) && br_v4 && br_v6) {\n             neighbor_collect_ip_mac_to_advertise(n_ctx_in,\n                                                  &br_v4->announced_neighbors,\n                                                  &br_v6->announced_neighbors,\ndiff --git a/northd/en-datapath-logical-switch.c b/northd/en-datapath-logical-switch.c\nindex d37dfa2bd1..ef4c95d28c 100644\n--- a/northd/en-datapath-logical-switch.c\n+++ b/northd/en-datapath-logical-switch.c\n@@ -59,6 +59,20 @@ get_requested_tunnel_key(const struct nbrec_logical_switch *nbs,\n     return requested_tunnel_key;\n }\n \n+static const char *\n+get_dynamic_device_name(const struct nbrec_logical_switch *nbs,\n+                        const char *dynamic_routing_option)\n+{\n+    const char *ifname = smap_get(&nbs->other_config, dynamic_routing_option);\n+\n+    if (!ifname) {\n+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);\n+        VLOG_WARN_RL(&rl, \"Missing %s for datapath %s\",\n+                     dynamic_routing_option, nbs->name);\n+    }\n+    return ifname;\n+}\n+\n static bool\n check_dynamic_device_name(const char *dynamic_routing_option,\n                           const char *if_name)\n@@ -125,46 +139,47 @@ gather_external_ids(const struct nbrec_logical_switch *nbs,\n     const char *vni = smap_get(&nbs->other_config, \"dynamic-routing-vni\");\n     if (vni) {\n         smap_add(external_ids, \"dynamic-routing-vni\", vni);\n-    }\n \n-    const char *bridge_ifname = smap_get(&nbs->other_config,\n-                                         \"dynamic-routing-bridge-ifname\");\n-    if (bridge_ifname &&\n-        check_dynamic_device_name(\"dynamic-routing-bridge-ifname\",\n-                                  bridge_ifname)) {\n-        smap_add(external_ids, \"dynamic-routing-bridge-ifname\",\n-                 bridge_ifname);\n-    }\n+        const char *bridge_ifname =\n+            get_dynamic_device_name(nbs, \"dynamic-routing-bridge-ifname\");\n+        if (bridge_ifname &&\n+            check_dynamic_device_name(\"dynamic-routing-bridge-ifname\",\n+                                      bridge_ifname)) {\n+            smap_add(external_ids, \"dynamic-routing-bridge-ifname\",\n+                     bridge_ifname);\n+        }\n \n-    const char *vxlan_ifnames = smap_get(&nbs->other_config,\n-                                         \"dynamic-routing-vxlan-ifname\");\n-    if (vxlan_ifnames &&\n-        check_dynamic_device_names(\"dynamic-routing-vxlan-ifname\",\n-                                   vxlan_ifnames)) {\n-        smap_add(external_ids, \"dynamic-routing-vxlan-ifname\",\n-                 vxlan_ifnames);\n-    }\n+        const char *vxlan_ifnames =\n+            get_dynamic_device_name(nbs, \"dynamic-routing-vxlan-ifname\");\n+        if (vxlan_ifnames &&\n+            check_dynamic_device_names(\"dynamic-routing-vxlan-ifname\",\n+                                       vxlan_ifnames)) {\n+            smap_add(external_ids, \"dynamic-routing-vxlan-ifname\",\n+                     vxlan_ifnames);\n+        }\n \n-    const char *adv_ifname = smap_get(&nbs->other_config,\n-                                      \"dynamic-routing-advertise-ifname\");\n-    if (adv_ifname &&\n-        check_dynamic_device_name(\"dynamic-routing-advertise-ifname\",\n-                                  adv_ifname)) {\n-        smap_add(external_ids, \"dynamic-routing-advertise-ifname\",\n-                 adv_ifname);\n-    }\n+        const char *adv_ifname =\n+            get_dynamic_device_name(nbs, \"dynamic-routing-advertise-ifname\");\n+        if (adv_ifname &&\n+            check_dynamic_device_name(\"dynamic-routing-advertise-ifname\",\n+                                      adv_ifname)) {\n+            smap_add(external_ids, \"dynamic-routing-advertise-ifname\",\n+                     adv_ifname);\n+        }\n \n-    const char *redistribute =\n-        smap_get(&nbs->other_config, \"dynamic-routing-redistribute\");\n-    if (redistribute) {\n-        smap_add(external_ids, \"dynamic-routing-redistribute\", redistribute);\n-    }\n+        const char *redistribute =\n+            smap_get(&nbs->other_config, \"dynamic-routing-redistribute\");\n+        if (redistribute) {\n+            smap_add(external_ids, \"dynamic-routing-redistribute\",\n+                     redistribute);\n+        }\n \n-    const char *prefer_evpn_arp_local =\n-        smap_get(&nbs->other_config, \"dynamic-routing-arp-prefer-local\");\n-    if (prefer_evpn_arp_local) {\n-        smap_add(external_ids, \"dynamic-routing-arp-prefer-local\",\n-                 prefer_evpn_arp_local);\n+        const char *prefer_evpn_arp_local =\n+            smap_get(&nbs->other_config, \"dynamic-routing-arp-prefer-local\");\n+        if (prefer_evpn_arp_local) {\n+            smap_add(external_ids, \"dynamic-routing-arp-prefer-local\",\n+                     prefer_evpn_arp_local);\n+        }\n     }\n \n     /* For backwards-compatibility, also store the NB UUID in\ndiff --git a/ovn-nb.xml b/ovn-nb.xml\nindex ae37d03d15..d4cef12e04 100644\n--- a/ovn-nb.xml\n+++ b/ovn-nb.xml\n@@ -795,27 +795,6 @@\n       <column name=\"external_ids\" key=\"neutron:network_name\">\n         Another name for the logical switch.\n       </column>\n-\n-      <column name=\"other_config\" key=\"dynamic-routing-bridge-ifname\">\n-       Set the interface name for the bridge used for EVPN integration.\n-       The default name is <code>br-$vni</code>.\n-       Only relevant if <ref column=\"other_config\" key=\"dynamic-routing-vni\"\n-                             table=\"Logical_switch\"/> is set to valid VNI.\n-      </column>\n-\n-      <column name=\"other_config\" key=\"dynamic-routing-vxlan-ifname\">\n-       List of interface names used for the vxlan devices used for EVPN\n-       integration. The default name is <code>vxlan-$vni</code>.\n-       Only relevant if <ref column=\"other_config\" key=\"dynamic-routing-vni\"\n-                             table=\"Logical_switch\"/> is set to valid VNI.\n-      </column>\n-\n-      <column name=\"other_config\" key=\"dynamic-routing-advertise-ifname\">\n-       Set the interface name for the advertise device used for EVPN\n-       integration. The default name is <code>lo-$vni</code>.\n-       Only relevant if <ref column=\"other_config\" key=\"dynamic-routing-vni\"\n-                             table=\"Logical_switch\"/> is set to valid VNI.\n-      </column>\n     </group>\n \n     <group title=\"IP Address Assignment\">\n@@ -919,6 +898,16 @@\n         dropped, even if use_ct_inv_match is set to true.\n         Default: <code>false</code>.\n       </column>\n+    </group>\n+\n+    <group title=\"EVPN Options\">\n+      <p>\n+        These options control the EVPN configuration of the logical switch.\n+        To enable EVPN integration set\n+        <ref column=\"other_config\" key=\"dynamic-routing-vni\"/> to a valid\n+        VNI number to represent the EVPN L2 domain extended by the\n+        logical switch.\n+      </p>\n \n       <column name=\"other_config\" key=\"dynamic-routing-vni\"\n               type='{\"type\": \"integer\", \"minInteger\": 0,\n@@ -929,9 +918,14 @@\n         </p>\n \n         <p>\n-          The ovn-controller expects three interfaces to exist within the\n-          BGP vrf: <code>br-$vni</code>, <code>lo-$vni</code> and\n-          <code>vxlan-$vni</code>.\n+          All of the following configuration options must also be provided\n+          in order for the configuration to be valid:\n+          <ref column=\"other_config\" key=\"dynamic-routing-bridge-ifname\"\n+               table=\"Logical_switch\"/>,\n+          <ref column=\"other_config\" key=\"dynamic-routing-vxlan-ifname\"\n+               table=\"Logical_switch\"/>,\n+          <ref column=\"other_config\" key=\"dynamic-routing-advertise-ifname\"\n+               table=\"Logical_switch\"/>,\n         </p>\n \n         <p>\n@@ -940,6 +934,26 @@\n         </p>\n       </column>\n \n+      <column name=\"other_config\" key=\"dynamic-routing-bridge-ifname\">\n+       Set the interface name for the bridge used for EVPN integration.\n+       Only relevant if <ref column=\"other_config\" key=\"dynamic-routing-vni\"\n+                             table=\"Logical_switch\"/> is set to valid VNI.\n+      </column>\n+\n+      <column name=\"other_config\" key=\"dynamic-routing-vxlan-ifname\">\n+       List of interface names used for the vxlan devices used for EVPN\n+       integration.\n+       Only relevant if <ref column=\"other_config\" key=\"dynamic-routing-vni\"\n+                             table=\"Logical_switch\"/> is set to valid VNI.\n+      </column>\n+\n+      <column name=\"other_config\" key=\"dynamic-routing-advertise-ifname\">\n+       Set the interface name for the advertise device used for EVPN\n+       integration.\n+       Only relevant if <ref column=\"other_config\" key=\"dynamic-routing-vni\"\n+                             table=\"Logical_switch\"/> is set to valid VNI.\n+      </column>\n+\n       <column name=\"other_config\" key=\"dynamic-routing-fdb-prefer-local\"\n               type='{\"type\": \"boolean\"}'>\n         <p>\ndiff --git a/tests/multinode.at b/tests/multinode.at\nindex b5331af247..e02bd6f074 100644\n--- a/tests/multinode.at\n+++ b/tests/multinode.at\n@@ -3515,8 +3515,11 @@ m_wait_for_ports_up\n \n # Enable EVPN support for the distributed logical switch and redistribute\n # local FDBs.\n-check multinode_nbctl set logical_switch ls          \\\n-    other_config:dynamic-routing-vni=$vni            \\\n+check multinode_nbctl set logical_switch ls               \\\n+    other_config:dynamic-routing-vni=$vni                 \\\n+    other_config:dynamic-routing-bridge-ifname=br-$vni    \\\n+    other_config:dynamic-routing-vxlan-ifname=vxlan-$vni  \\\n+    other_config:dynamic-routing-advertise-ifname=lo-$vni \\\n     other_config:dynamic-routing-redistribute=fdb,ip\n check multinode_nbctl --wait=hv sync\n dp_key=$(m_fetch_column Datapath_Binding tunnel_key external_ids:name=ls)\n@@ -4336,8 +4339,11 @@ check m_as ovn-gw-2 /data/create_fake_vm.sh w2 w2 \\\n m_wait_for_ports_up\n \n # Enable EVPN support for the distributed logical switch.\n-check multinode_nbctl set logical_switch ls \\\n-    other_config:dynamic-routing-vni=$vni   \\\n+check multinode_nbctl set logical_switch ls               \\\n+    other_config:dynamic-routing-vni=$vni                 \\\n+    other_config:dynamic-routing-bridge-ifname=br-$vni    \\\n+    other_config:dynamic-routing-vxlan-ifname=vxlan-$vni  \\\n+    other_config:dynamic-routing-advertise-ifname=lo-$vni \\\n     other_config:dynamic-routing-redistribute=fdb,ip\n \n check multinode_nbctl --wait=hv sync\ndiff --git a/tests/ovn.at b/tests/ovn.at\nindex 3a3b05ab7f..17a59eaebc 100644\n--- a/tests/ovn.at\n+++ b/tests/ovn.at\n@@ -45700,3 +45700,85 @@ AT_CHECK([grep -q 'name=\"eth-unknown\"' hv1/ovn-controller.log], [1])\n OVN_CLEANUP([hv1])\n AT_CLEANUP\n ])\n+\n+OVN_FOR_EACH_NORTHD([\n+AT_SETUP([EVPN ifname configurations])\n+ovn_start\n+\n+net_add n1\n+sim_add hv\n+ovs-vsctl add-br br-phys\n+ovn_attach n1 br-phys 192.168.0.1\n+\n+as northd\n+check ovn-appctl -t ovn-northd vlog/set jsonrpc:info\n+check ovn-appctl -t ovn-northd vlog/disable-rate-limit\n+as hv\n+check ovn-appctl -t ovn-controller vlog/disable-rate-limit\n+\n+clear_logs() {\n+    as northd\n+    check ovn-appctl -t ovn-northd vlog/close\n+    check rm northd/ovn-northd.log\n+    check ovn-appctl -t ovn-northd vlog/reopen\n+\n+    as hv\n+    check ovn-appctl -t ovn-controller vlog/close\n+    check rm hv/ovn-controller.log\n+    check ovn-appctl -t ovn-controller vlog/reopen\n+}\n+\n+check ovn-nbctl ls-add ls -- lsp-add ls lsp\n+check ovs-vsctl add-port br-int lsp -- \\\n+    set Interface lsp external_ids:iface-id=lsp\n+\n+wait_for_ports_up\n+check ovn-nbctl --wait=hv sync\n+\n+AS_BOX([Missing bridge ifname])\n+clear_logs\n+check ovn-nbctl --wait=hv                                                      \\\n+    -- set logical_switch ls other_config:dynamic-routing-vni=42               \\\n+    -- set logical_switch ls other_config:dynamic-routing-vxlan-ifname=foo     \\\n+    -- set logical_switch ls other_config:dynamic-routing-advertise-ifname=bar\n+\n+OVS_WAIT_UNTIL([grep -q \"WARN.*dynamic-routing-bridge-ifname\" northd/ovn-northd.log])\n+OVS_WAIT_UNTIL([grep -q \"WARN.*dynamic-routing-bridge-ifname\" hv/ovn-controller.log])\n+check ovn-nbctl --wait=hv clear logical_switch ls other_config\n+\n+AS_BOX([Missing vxlan ifname])\n+clear_logs\n+check ovn-nbctl --wait=hv                                                      \\\n+    -- set logical_switch ls other_config:dynamic-routing-vni=42               \\\n+    -- set logical_switch ls other_config:dynamic-routing-bridge-ifname=foo    \\\n+    -- set logical_switch ls other_config:dynamic-routing-advertise-ifname=bar\n+\n+OVS_WAIT_UNTIL([grep -q \"WARN.*dynamic-routing-vxlan-ifname\" northd/ovn-northd.log])\n+OVS_WAIT_UNTIL([grep -q \"WARN.*dynamic-routing-vxlan-ifname\" hv/ovn-controller.log])\n+check ovn-nbctl --wait=hv clear logical_switch ls other_config\n+\n+AS_BOX([Missing advertise ifname])\n+clear_logs\n+check ovn-nbctl --wait=hv                                                   \\\n+    -- set logical_switch ls other_config:dynamic-routing-vni=42            \\\n+    -- set logical_switch ls other_config:dynamic-routing-bridge-ifname=foo \\\n+    -- set logical_switch ls other_config:dynamic-routing-vxlan-ifname=bar\n+\n+OVS_WAIT_UNTIL([grep -q \"WARN.*dynamic-routing-advertise-ifname\" northd/ovn-northd.log])\n+OVS_WAIT_UNTIL([grep -q \"WARN.*dynamic-routing-advertise-ifname\" hv/ovn-controller.log])\n+check ovn-nbctl --wait=hv clear logical_switch ls other_config\n+\n+AS_BOX([Valid config])\n+clear_logs\n+check ovn-nbctl --wait=hv                                                      \\\n+    -- set logical_switch ls other_config:dynamic-routing-vni=42               \\\n+    -- set logical_switch ls other_config:dynamic-routing-bridge-ifname=foo    \\\n+    -- set logical_switch ls other_config:dynamic-routing-vxlan-ifname=bar     \\\n+    -- set logical_switch ls other_config:dynamic-routing-advertise-ifname=xyz\n+\n+AT_CHECK([grep -q \"WARN.*dynamic-routing\" northd/ovn-northd.log], [1])\n+AT_CHECK([grep -q \"WARN.*dynamic-routing\" hv/ovn-controller.log], [1])\n+\n+OVN_CLEANUP([hv])\n+AT_CLEANUP\n+])\ndiff --git a/tests/system-common-macros.at b/tests/system-common-macros.at\nindex 0f4f8952c6..5062f02b0e 100644\n--- a/tests/system-common-macros.at\n+++ b/tests/system-common-macros.at\n@@ -213,12 +213,9 @@ m4_define([SET_EVPN_IFACE_NAMES],\n         [[ $ifname = \"default\" ]] && VXLAN_V6_NAME=vxlan-v6-$vni || VXLAN_V6_NAME=vxlan-v6-$ifname\n         [[ $ifname = \"default\" ]] && LO_NAME=lo-$vni || LO_NAME=lo-$ifname\n \n-        if [[ $ifname != \"default\" ]]; then\n-            check ovn-nbctl set logical_switch $switch                 \\\n-                other_config:dynamic-routing-bridge-ifname=$BR_NAME    \\\n-                other_config:dynamic-routing-advertise-ifname=$LO_NAME\n-        fi\n-        check ovn-nbctl set logical_switch $switch  \\\n+        check ovn-nbctl set logical_switch $switch                 \\\n+            other_config:dynamic-routing-bridge-ifname=$BR_NAME    \\\n+            other_config:dynamic-routing-advertise-ifname=$LO_NAME \\\n             other_config:dynamic-routing-vxlan-ifname=$VXLAN_NAME\",\"$VXLAN_V6_NAME\n \n         export BR_NAME VXLAN_NAME VXLAN_V6_NAME LO_NAME\n",
    "prefixes": [
        "ovs-dev",
        "1/3"
    ]
}