Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2195096/?format=api
{ "id": 2195096, "url": "http://patchwork.ozlabs.org/api/patches/2195096/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20260209213445.89053-1-leih@nvidia.com/", "project": { "id": 68, "url": "http://patchwork.ozlabs.org/api/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": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260209213445.89053-1-leih@nvidia.com>", "list_archive_url": null, "date": "2026-02-09T21:34:45", "name": "[ovs-dev,1/1] northd: add requested-encap-ip for remote ports", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "921d7113be1ae789707cfd35cb1ccba9e7492425", "submitter": { "id": 92618, "url": "http://patchwork.ozlabs.org/api/people/92618/?format=api", "name": "Lei Huang", "email": "leihuang.dev8@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260209213445.89053-1-leih@nvidia.com/mbox/", "series": [ { "id": 491666, "url": "http://patchwork.ozlabs.org/api/series/491666/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/list/?series=491666", "date": "2026-02-09T21:34:45", "name": "[ovs-dev,1/1] northd: add requested-encap-ip for remote ports", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/491666/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2195096/comments/", "check": "warning", "checks": "http://patchwork.ozlabs.org/api/patches/2195096/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "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\" (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=AuTYbQin;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp4.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=AuTYbQin", "smtp2.osuosl.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "smtp2.osuosl.org; dkim=pass (2048-bit key,\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=AuTYbQin" ], "Received": [ "from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\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 4f9LYm3X9lz1xvb\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 10 Feb 2026 23:32:44 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id C521140CC5;\n\tTue, 10 Feb 2026 12:32:42 +0000 (UTC)", "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id RWOp70REULLI; Tue, 10 Feb 2026 12:32:41 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp4.osuosl.org (Postfix) with ESMTPS id 3C5AC40CC2;\n\tTue, 10 Feb 2026 12:32:41 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 071E8C077F;\n\tTue, 10 Feb 2026 12:32:41 +0000 (UTC)", "from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 5CD2BC077E\n for <dev@openvswitch.org>; Mon, 9 Feb 2026 21:34:52 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 34FCB405D6\n for <dev@openvswitch.org>; Mon, 9 Feb 2026 21:34:52 +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 OgaECKEyLPiz for <dev@openvswitch.org>;\n Mon, 9 Feb 2026 21:34:51 +0000 (UTC)", "from mail-dl1-x1233.google.com (mail-dl1-x1233.google.com\n [IPv6:2607:f8b0:4864:20::1233])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 2000C40165\n for <dev@openvswitch.org>; Mon, 9 Feb 2026 21:34:50 +0000 (UTC)", "by mail-dl1-x1233.google.com with SMTP id\n a92af1059eb24-1271257ae53so164894c88.1\n for <dev@openvswitch.org>; Mon, 09 Feb 2026 13:34:50 -0800 (PST)", "from gmail.com (searspoint.nvidia.com. [216.228.112.21])\n by smtp.gmail.com with ESMTPSA id\n a92af1059eb24-127043463bcsm9833302c88.13.2026.02.09.13.34.48\n (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256);\n Mon, 09 Feb 2026 13:34:48 -0800 (PST)" ], "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 smtp4.osuosl.org 3C5AC40CC2", "OpenDKIM Filter v2.11.0 smtp2.osuosl.org 2000C40165" ], "Received-SPF": "Pass (mailfrom) identity=mailfrom;\n client-ip=2607:f8b0:4864:20::1233; helo=mail-dl1-x1233.google.com;\n envelope-from=leihuang.dev8@gmail.com; receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp2.osuosl.org 2000C40165", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1770672890; x=1771277690; darn=openvswitch.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:from:to:cc:subject:date:message-id:reply-to;\n bh=wusgiXs/WOio/xJ5JRD7vjhdVNedLAFL8gmjhu2aoK8=;\n b=AuTYbQinlCuZOruxo7R7W9yg872drHgRImH6g/9JAmU5NEY/dQqp+Ub9h6R7Bm60ZU\n L1uGOvxAsWNj4SwggubJvr2f94qZgyGnoErYoGNghMY11XgsnjYsiOBYOlNZDjr/pF+c\n 8g4FVgnXRFEui7Cy85lz+PjqpNCmE0BuvStY3yTfAQBn/outd+N/2Q1V1NLnUQJZWc2V\n TrMOkLlEL9OxD5Op3eZ4kPPnCWhX3lb1O3ZKHRKkqvtoQAo6EF73+zljESghPL03JZlC\n 7mm8iSkuu7EakwA/wIyntvAyVf/6AAkwKC6v7ALRlfo7hTdOUlFftTQ6hJgYG8CKumiK\n bX0g==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770672890; x=1771277690;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=wusgiXs/WOio/xJ5JRD7vjhdVNedLAFL8gmjhu2aoK8=;\n b=dtoMTn8LDnpvlVtyMSJme2zMCYcCs5dMT5T2pDiqL41FSsxVxJDehGEoOFMPDWWLZK\n vRh3+AbAG4mQng8V18KIRpIn7Fnv6eVLbBzYUTNPBLkD4YRcbHW+kWRCxGH6cY7NFaiE\n 02kleCDQnyghwIrl9y/TflG2wVUOUGG4MzfT+ph5JeYolIkjZ8p7BNh1MRkxoFiOh4Pt\n c84k5P2WOPXZfxK/+ZnrI3nEyMWRJzrc9BSDBgfffLqiq2kjVrSLQ0toXOm5ZbFvfXlR\n T4uPtc6xaVeyotqaC5ChP2oZZMsqFK8KeXycqHUWVBRwIhfhGNpCKFM7y8lpFBlzF1Jo\n yDlw==", "X-Gm-Message-State": "AOJu0Yz+QwKzkU4Y/zBARAjJ7nkUnM/mNCJcrPsbHAGEXskEAx02Crbl\n n9tSbQNb98Zh+Ucq5CPAFOW8XxKna/R/Dx2k+lSuWGV5/0TRY3v9gpNZ3T37L9iL", "X-Gm-Gg": "AZuq6aIOHGRbTnbCEsb3plhsQwj5+pbG2Zn1EpP+xyQ3dVtdwKt9NRWykwqus4MnBVQ\n KCFjHBkDtbm6Cy4iLFTnul+042s8x6yGYj/G+7SY65X4okJmJ5xKQEskIZ7YmHlCjmBMx2IURoQ\n Szwu3lFuFrzaItgGoYZacMUVQnzwC8whzfDm8daUgSMbeoPaNEgUWG41I50efQM8xmOqf3m9nRB\n I4PplXJhW5KxUm8qt9EivPSPxi0+TWsZr6Ws8CdO663NckmMSH0R/8xc+2lqdnV0jWkiSihC64G\n o5NVt67OOI33O1/2DgkfAfh/QCXKVRHNw502xxXvYOubbQNAqmB259WTeLJRCet1KxNTQdmPWsW\n ie1vr8ehJWDnoSPqL3AwoLI7HEp4wbwpHVjNtlkYvWSX1oSBJ0TJw5yE5sR/kAPJI39Cj6XlRY2\n hpq6uWy63PCbSYxQzpRONYINc=", "X-Received": "by 2002:a05:7022:627:b0:11b:9e5e:1a66 with SMTP id\n a92af1059eb24-12704014bf0mr5343094c88.14.1770672889732;\n Mon, 09 Feb 2026 13:34:49 -0800 (PST)", "From": "Lei Huang <leihuang.dev8@gmail.com>", "X-Google-Original-From": "Lei Huang <leih@nvidia.com>", "To": "dev@openvswitch.org", "Date": "Mon, 9 Feb 2026 13:34:45 -0800", "Message-Id": "<20260209213445.89053-1-leih@nvidia.com>", "X-Mailer": "git-send-email 2.39.5 (Apple Git-154)", "MIME-Version": "1.0", "X-Mailman-Approved-At": "Tue, 10 Feb 2026 12:32:39 +0000", "Subject": "[ovs-dev] [PATCH ovn 1/1] northd: add requested-encap-ip for remote\n ports", "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>", "Cc": "Lei Huang <leih@nvidia.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": "Use requested-encap-ip (with requested-chassis) to set Port_Binding.encap,\nclear on removal, and prefer geneve when both types exist. Add a northd\ntest and document the ovn-k8s interconnect use case.\n\nCC: Han Zhou <hzhou@ovn.org>\nSigned-off-by: Lei Huang <leih@nvidia.com>\n---\n NEWS | 3 ++\n northd/northd.c | 116 +++++++++++++++++++++++++++++++++++++++++---\n ovn-nb.xml | 18 +++++++\n tests/ovn-northd.at | 63 ++++++++++++++++++++++++\n 4 files changed, 193 insertions(+), 7 deletions(-)", "diff": "diff --git a/NEWS b/NEWS\nindex 2a2b5e12d..040577519 100644\n--- a/NEWS\n+++ b/NEWS\n@@ -1,5 +1,8 @@\n Post v25.09.0\n -------------\n+ - Added LSP/LRP option \"requested-encap-ip\" to let CMS request a specific\n+ SB Port_Binding encap IP (e.g., for remote transit ports in ovn-k8s\n+ interconnect mode).\n - Added DNS query statistics tracking in ovn-controller using OVS coverage\n counters. Statistics can be queried using \"ovn-appctl -t ovn-controller\n coverage/read-counter <counter_name>\" or \"coverage/show\". Tracked metrics\ndiff --git a/northd/northd.c b/northd/northd.c\nindex b4bb4ba6d..3e8e9a994 100644\n--- a/northd/northd.c\n+++ b/northd/northd.c\n@@ -2531,6 +2531,82 @@ ovn_port_update_sbrec_chassis(\n free(requested_chassis_sb);\n }\n \n+static void\n+encap_ip_map_init(struct shash *encap_by_ip,\n+ const struct sbrec_chassis_table *sbrec_chassis_table)\n+{\n+ shash_init(encap_by_ip);\n+ if (!sbrec_chassis_table) {\n+ return;\n+ }\n+\n+ const struct sbrec_chassis *chassis;\n+ SBREC_CHASSIS_TABLE_FOR_EACH (chassis, sbrec_chassis_table) {\n+ for (size_t i = 0; i < chassis->n_encaps; i++) {\n+ const struct sbrec_encap *encap = chassis->encaps[i];\n+ if (!encap || !encap->ip || !encap->type || !encap->chassis_name) {\n+ continue;\n+ }\n+\n+ enum chassis_tunnel_type tun_type = get_tunnel_type(encap->type);\n+ if (tun_type == TUNNEL_TYPE_INVALID) {\n+ continue;\n+ }\n+\n+ char *key = xasprintf(\"%s@%s\", encap->chassis_name, encap->ip);\n+ struct shash_node *node = shash_find(encap_by_ip, key);\n+ if (!node) {\n+ shash_add_nocopy(encap_by_ip, key, (void *) encap);\n+ } else {\n+ free(key);\n+ const struct sbrec_encap *existing = node->data;\n+ /* Pick the highest-preference tunnel type (geneve > vxlan)\n+ * when multiple encap types share the same chassis+IP. */\n+ if (get_tunnel_type(existing->type) < tun_type) {\n+ node->data = (void *) encap;\n+ }\n+ }\n+ }\n+ }\n+}\n+\n+static const struct sbrec_encap *\n+encap_ip_map_lookup(const struct shash *encap_by_ip, const char *chassis_name,\n+ const char *ip)\n+{\n+ if (!encap_by_ip || !chassis_name || !chassis_name[0] || !ip || !ip[0]) {\n+ return NULL;\n+ }\n+ char *key = xasprintf(\"%s@%s\", chassis_name, ip);\n+ const struct sbrec_encap *encap = shash_find_data(encap_by_ip, key);\n+ free(key);\n+ return encap;\n+}\n+\n+static void\n+ovn_port_update_requested_encap(const struct shash *encap_by_ip,\n+ const struct ovn_port *op)\n+{\n+ if (is_cr_port(op)) {\n+ return;\n+ }\n+\n+ /* requested-chassis is resolved into SB first; reuse that binding. */\n+ const struct smap *options = op->nbsp ? &op->nbsp->options\n+ : &op->nbrp->options;\n+ const char *requested_ip = smap_get(options, \"requested-encap-ip\");\n+ const struct sbrec_encap *encap = NULL;\n+ if (requested_ip && requested_ip[0] && op->sb->requested_chassis) {\n+ encap = encap_ip_map_lookup(encap_by_ip,\n+ op->sb->requested_chassis->name,\n+ requested_ip);\n+ }\n+\n+ if (op->sb->encap != encap) {\n+ sbrec_port_binding_set_encap(op->sb, encap);\n+ }\n+}\n+\n static void\n check_and_do_sb_mirror_deletion(const struct ovn_port *op)\n {\n@@ -2601,6 +2677,7 @@ ovn_port_update_sbrec(struct ovsdb_idl_txn *ovnsb_txn,\n struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name,\n const struct sbrec_mirror_table *sbrec_mirror_table,\n+ const struct shash *encap_by_ip,\n const struct ovn_port *op,\n unsigned long *queue_id_bitmap,\n struct sset *active_ha_chassis_grps)\n@@ -2937,6 +3014,10 @@ common:\n sbrec_port_binding_set_tunnel_key(op->sb, op->tunnel_key);\n }\n \n+ if (encap_by_ip) {\n+ ovn_port_update_requested_encap(encap_by_ip, op);\n+ }\n+\n /* ovn-controller will update 'Port_Binding.up' only if it was explicitly\n * set to 'false'.\n */\n@@ -4096,6 +4177,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,\n const struct sbrec_mirror_table *sbrec_mirror_table,\n const struct sbrec_mac_binding_table *sbrec_mac_binding_table,\n const struct sbrec_ha_chassis_group_table *sbrec_ha_chassis_group_table,\n+ const struct sbrec_chassis_table *sbrec_chassis_table,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name,\n@@ -4113,6 +4195,9 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,\n struct sset active_ha_chassis_grps =\n SSET_INITIALIZER(&active_ha_chassis_grps);\n \n+ struct shash encap_by_ip;\n+ encap_ip_map_init(&encap_by_ip, sbrec_chassis_table);\n+\n /* Borrow ls_ports for joining NB and SB for both LSPs and LRPs.\n * We will split them later. */\n struct hmap *ports = ls_ports;\n@@ -4172,6 +4257,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,\n sbrec_chassis_by_hostname,\n sbrec_ha_chassis_grp_by_name,\n sbrec_mirror_table,\n+ &encap_by_ip,\n op, queue_id_bitmap,\n &active_ha_chassis_grps);\n op->od->is_transit_router |= is_transit_router_port(op);\n@@ -4185,6 +4271,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,\n sbrec_chassis_by_hostname,\n sbrec_ha_chassis_grp_by_name,\n sbrec_mirror_table,\n+ &encap_by_ip,\n op, queue_id_bitmap,\n &active_ha_chassis_grps);\n sbrec_port_binding_set_logical_port(op->sb, op->key);\n@@ -4215,6 +4302,7 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,\n cleanup_mac_bindings(sbrec_mac_binding_table, lr_datapaths, lr_ports);\n }\n \n+ shash_destroy(&encap_by_ip);\n tag_alloc_destroy(&tag_alloc_table);\n bitmap_free(queue_id_bitmap);\n cleanup_sb_ha_chassis_groups(sbrec_ha_chassis_group_table,\n@@ -4401,7 +4489,8 @@ ls_port_init(struct ovn_port *op, struct ovsdb_idl_txn *ovnsb_txn,\n const struct sbrec_port_binding *sb,\n const struct sbrec_mirror_table *sbrec_mirror_table,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n- struct ovsdb_idl_index *sbrec_chassis_by_hostname)\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n+ const struct shash *encap_by_ip)\n {\n op->od = od;\n parse_lsp_addrs(op);\n@@ -4431,6 +4520,7 @@ ls_port_init(struct ovn_port *op, struct ovsdb_idl_txn *ovnsb_txn,\n }\n ovn_port_update_sbrec(ovnsb_txn, sbrec_chassis_by_name,\n sbrec_chassis_by_hostname, NULL, sbrec_mirror_table,\n+ encap_by_ip,\n op, NULL, NULL);\n return true;\n }\n@@ -4441,13 +4531,15 @@ ls_port_create(struct ovsdb_idl_txn *ovnsb_txn, struct hmap *ls_ports,\n struct ovn_datapath *od,\n const struct sbrec_mirror_table *sbrec_mirror_table,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n- struct ovsdb_idl_index *sbrec_chassis_by_hostname)\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n+ const struct shash *encap_by_ip)\n {\n struct ovn_port *op = ovn_port_create(ls_ports, key, nbsp, NULL,\n NULL);\n hmap_insert(&od->ports, &op->dp_node, hmap_node_hash(&op->key_node));\n if (!ls_port_init(op, ovnsb_txn, od, NULL, sbrec_mirror_table,\n- sbrec_chassis_by_name, sbrec_chassis_by_hostname)) {\n+ sbrec_chassis_by_name, sbrec_chassis_by_hostname,\n+ encap_by_ip)) {\n ovn_port_destroy(ls_ports, op);\n return NULL;\n }\n@@ -4462,14 +4554,16 @@ ls_port_reinit(struct ovn_port *op, struct ovsdb_idl_txn *ovnsb_txn,\n const struct sbrec_port_binding *sb,\n const struct sbrec_mirror_table *sbrec_mirror_table,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n- struct ovsdb_idl_index *sbrec_chassis_by_hostname)\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n+ const struct shash *encap_by_ip)\n {\n ovn_port_cleanup(op);\n op->sb = sb;\n ovn_port_set_nb(op, nbsp, NULL);\n op->primary_port = op->cr_port = NULL;\n return ls_port_init(op, ovnsb_txn, od, sb, sbrec_mirror_table,\n- sbrec_chassis_by_name, sbrec_chassis_by_hostname);\n+ sbrec_chassis_by_name, sbrec_chassis_by_hostname,\n+ encap_by_ip);\n }\n \n /* Returns true if the logical switch has changes which can be\n@@ -4632,6 +4726,9 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,\n return true;\n }\n \n+ struct shash encap_by_ip;\n+ encap_ip_map_init(&encap_by_ip, ni->sbrec_chassis_table);\n+\n bool ls_had_only_router_ports = (!vector_is_empty(&od->router_ports)\n && (vector_len(&od->router_ports) == hmap_count(&od->ports)));\n \n@@ -4658,7 +4755,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,\n new_nbsp->name, new_nbsp, od,\n ni->sbrec_mirror_table,\n ni->sbrec_chassis_by_name,\n- ni->sbrec_chassis_by_hostname);\n+ ni->sbrec_chassis_by_hostname,\n+ &encap_by_ip);\n if (!op) {\n goto fail;\n }\n@@ -4697,7 +4795,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,\n new_nbsp,\n od, sb, ni->sbrec_mirror_table,\n ni->sbrec_chassis_by_name,\n- ni->sbrec_chassis_by_hostname)) {\n+ ni->sbrec_chassis_by_hostname,\n+ &encap_by_ip)) {\n if (sb) {\n sbrec_port_binding_delete(sb);\n }\n@@ -4798,9 +4897,11 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,\n }\n sset_destroy(&created_or_deleted_ports);\n \n+ shash_destroy(&encap_by_ip);\n return true;\n \n fail:\n+ shash_destroy(&encap_by_ip);\n destroy_tracked_ovn_ports(trk_lsps);\n return false;\n }\n@@ -20622,6 +20723,7 @@ ovnnb_db_run(struct northd_input *input_data,\n input_data->sbrec_mirror_table,\n input_data->sbrec_mac_binding_table,\n input_data->sbrec_ha_chassis_group_table,\n+ input_data->sbrec_chassis_table,\n input_data->sbrec_chassis_by_name,\n input_data->sbrec_chassis_by_hostname,\n input_data->sbrec_ha_chassis_grp_by_name,\ndiff --git a/ovn-nb.xml b/ovn-nb.xml\nindex 1acbf202b..33bf8993a 100644\n--- a/ovn-nb.xml\n+++ b/ovn-nb.xml\n@@ -1550,6 +1550,15 @@\n </p>\n </column>\n \n+ <column name=\"options\" key=\"requested-encap-ip\">\n+ Requests the encapsulation IP address for the port binding. If set,\n+ <code>ovn-northd</code> uses this IP to select the\n+ <ref table=\"Encap\" db=\"OVN_Southbound\"/> entry written to\n+ <ref table=\"Port_Binding\" column=\"encap\" db=\"OVN_Southbound\"/>.\n+ This is intended for ports without a local OVS interface, e.g. remote\n+ transit switch ports in ovn-kubernetes interconnect mode.\n+ </column>\n+\n <column name=\"options\" key=\"activation-strategy\">\n If used with multiple chassis set in\n <ref column=\"requested-chassis\"/>, specifies an activation strategy\n@@ -4393,6 +4402,15 @@ or\n </p>\n </column>\n \n+ <column name=\"options\" key=\"requested-encap-ip\">\n+ Requests the encapsulation IP address for the port binding. If set,\n+ <code>ovn-northd</code> uses this IP to select the\n+ <ref table=\"Encap\" db=\"OVN_Southbound\"/> entry written to\n+ <ref table=\"Port_Binding\" column=\"encap\" db=\"OVN_Southbound\"/>.\n+ This is intended for ports without a local OVS interface, e.g. remote\n+ transit router ports in ovn-kubernetes interconnect mode.\n+ </column>\n+\n <column name=\"options\" key=\"dynamic-routing-redistribute\"\n type='{\"type\": \"string\"}'>\n <p>\ndiff --git a/tests/ovn-northd.at b/tests/ovn-northd.at\nindex 512e42036..9245ff639 100644\n--- a/tests/ovn-northd.at\n+++ b/tests/ovn-northd.at\n@@ -2896,6 +2896,69 @@ OVN_CLEANUP_NORTHD\n AT_CLEANUP\n ])\n \n+OVN_FOR_EACH_NORTHD_NO_HV([\n+AT_SETUP([check options:requested-encap-ip fills port binding encap col])\n+AT_KEYWORDS([requested encap ip])\n+ovn_start\n+\n+check_uuid ovn-sbctl \\\n+ -- --id=@e11 create encap chassis_name=ch1 ip=\"192.168.1.1\" type=\"geneve\" \\\n+ -- --id=@e12 create encap chassis_name=ch1 ip=\"192.168.1.2\" type=\"geneve\" \\\n+ -- --id=@c1 create chassis name=ch1 encaps=@e11,@e12\n+check_uuid ovn-sbctl \\\n+ -- --id=@e21 create encap chassis_name=ch2 ip=\"192.168.2.1\" type=\"geneve\" \\\n+ -- --id=@e22 create encap chassis_name=ch2 ip=\"192.168.2.2\" type=\"geneve\" \\\n+ -- --id=@c2 create chassis name=ch2 encaps=@e21,@e22\n+\n+wait_row_count Chassis 2\n+wait_row_count Encap 4\n+en11_uuid=`ovn-sbctl --bare --columns _uuid find Encap ip=\"192.168.1.1\"`\n+en12_uuid=`ovn-sbctl --bare --columns _uuid find Encap ip=\"192.168.1.2\"`\n+en21_uuid=`ovn-sbctl --bare --columns _uuid find Encap ip=\"192.168.2.1\"`\n+en22_uuid=`ovn-sbctl --bare --columns _uuid find Encap ip=\"192.168.2.2\"`\n+ovn-sbctl show\n+\n+echo \"__file__:__line__: encap uuid: $en11_uuid, ip: 192.168.1.1\"\n+echo \"__file__:__line__: encap uuid: $en12_uuid, ip: 192.168.1.2\"\n+echo \"__file__:__line__: encap uuid: $en21_uuid, ip: 192.168.2.1\"\n+echo \"__file__:__line__: encap uuid: $en22_uuid, ip: 192.168.2.2\"\n+\n+check ovn-nbctl --wait=sb ls-add ls1\n+check ovn-nbctl --wait=sb lsp-add ls1 lsp1\n+check ovn-nbctl --wait=sb lsp-add ls1 lsp2\n+ovn-nbctl show\n+\n+echo \"options:requested-chassis is required to set options:requested-encap-ip\"\n+check ovn-nbctl --wait=sb set logical-switch-port lsp1 \\\n+ options:requested-encap-ip=192.168.1.1\n+check ovn-nbctl --wait=sb sync\n+wait_row_count Port_Binding 1 logical_port=lsp1 'encap=[[]]'\n+\n+# Now set both options\n+check ovn-nbctl --wait=sb set logical-switch-port lsp1 \\\n+ options:requested-chassis=ch1 \\\n+ options:requested-encap-ip=192.168.1.1\n+check ovn-nbctl --wait=sb set logical-switch-port lsp2 \\\n+ options:requested-chassis=ch2 \\\n+ options:requested-encap-ip=192.168.2.2\n+\n+wait_row_count Port_Binding 1 logical_port=lsp1 encap=\"$en11_uuid\"\n+wait_row_count Port_Binding 1 logical_port=lsp2 encap=\"$en22_uuid\"\n+\n+# remove options:requested-encap-ip from lsp1\n+check ovn-nbctl --wait=sb remove logical_switch_port lsp1 \\\n+ options requested-encap-ip=192.168.1.1\n+wait_row_count Port_Binding 1 logical_port=lsp1 'encap=[[]]'\n+\n+# remove options:requested-chassis from lsp2\n+check ovn-nbctl --wait=sb remove logical_switch_port lsp2 \\\n+ options requested-chassis=ch2\n+wait_row_count Port_Binding 1 logical_port=lsp2 'encap=[[]]'\n+\n+OVN_CLEANUP_NORTHD\n+AT_CLEANUP\n+])\n+\n OVN_FOR_EACH_NORTHD_NO_HV([\n AT_SETUP([port requested-tnl-key])\n AT_KEYWORDS([requested tnl tunnel key keys])\n", "prefixes": [ "ovs-dev", "1/1" ] }