Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1524522/?format=api
{ "id": 1524522, "url": "http://patchwork.ozlabs.org/api/patches/1524522/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20210903192748.1408062-2-frode.nordahl@canonical.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": "<20210903192748.1408062-2-frode.nordahl@canonical.com>", "list_archive_url": null, "date": "2021-09-03T19:27:40", "name": "[ovs-dev,v4,1/9] ovn-sb: Add requested_chassis column to Port_Binding.", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": false, "hash": "1083533b07c4450cb7931da2912b637affa8bafe", "submitter": { "id": 77851, "url": "http://patchwork.ozlabs.org/api/people/77851/?format=api", "name": "Frode Nordahl", "email": "frode.nordahl@canonical.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20210903192748.1408062-2-frode.nordahl@canonical.com/mbox/", "series": [ { "id": 260950, "url": "http://patchwork.ozlabs.org/api/series/260950/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/list/?series=260950", "date": "2021-09-03T19:27:42", "name": "Introduce infrastructure for plugging providers", "version": 4, "mbox": "http://patchwork.ozlabs.org/series/260950/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1524522/comments/", "check": "fail", "checks": "http://patchwork.ozlabs.org/api/patches/1524522/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@bilbo.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=canonical.com header.i=@canonical.com\n header.a=rsa-sha256 header.s=20210705 header.b=jRlGssJu;\n\tdkim-atps=neutral", "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.138; helo=smtp1.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN>)", "smtp2.osuosl.org (amavisd-new);\n dkim=pass (2048-bit key) header.d=canonical.com" ], "Received": [ "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4H1SWG6dS0z9sSs\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 4 Sep 2021 05:28:10 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 907C383F31;\n\tFri, 3 Sep 2021 19:28:08 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n\tby localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id KJAFwjWHzvwx; Fri, 3 Sep 2021 19:28:04 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp1.osuosl.org (Postfix) with ESMTPS id 9664E83F2D;\n\tFri, 3 Sep 2021 19:28:02 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 1F6C5C0033;\n\tFri, 3 Sep 2021 19:27:59 +0000 (UTC)", "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 4FD48C0023\n for <dev@openvswitch.org>; Fri, 3 Sep 2021 19:27:55 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 7CCA64027D\n for <dev@openvswitch.org>; Fri, 3 Sep 2021 19:27:54 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id ukEJMf_QmyTu for <dev@openvswitch.org>;\n Fri, 3 Sep 2021 19:27:52 +0000 (UTC)", "from smtp-relay-canonical-1.canonical.com\n (smtp-relay-canonical-1.canonical.com [185.125.188.121])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 7A569400AE\n for <dev@openvswitch.org>; Fri, 3 Sep 2021 19:27:52 +0000 (UTC)", "from frode-threadripper.. (1.general.frode.uk.vpn [10.172.193.250])\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 smtp-relay-canonical-1.canonical.com (Postfix) with ESMTPSA id 5950C40192;\n Fri, 3 Sep 2021 19:27:49 +0000 (UTC)" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.8.0", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com;\n s=20210705; t=1630697269;\n bh=qN738PGGkB8fpw63A/O3UUUFmgoFD06EtZii1QjR7TE=;\n h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:\n MIME-Version;\n b=jRlGssJucpj+s0EHB16nZOMsqvdkxvCRhqsLoBKmsdmDFcbQiKsr1QYt45p/hiu03\n PYZb9yaOQPavTlzywYqJVMR9msauZv/VtqTLsQxM/EjdKNJ4OEMgv0Mt9Hsm8Vxw9l\n 5bQjELEBPBHG3W7JE7dOfIKeimKIt1R1ftP7MU7hxqbZSjC03xX0qyr2yl1jEC/NW2\n P5COWbnex42k/+OVSn2LKjzpWTH+RCwKDTGcTxnmqO2lu5qL/T496NvVrzs+nYokOH\n HA2v6G2BsjBSaHegEQWdKIz4JelUMrqBfR1OdLO2GYAKOUhqfmOuJTELic52TWKyeV\n pQH/1oPKkTJFw==", "From": "Frode Nordahl <frode.nordahl@canonical.com>", "To": "dev@openvswitch.org", "Date": "Fri, 3 Sep 2021 21:27:40 +0200", "Message-Id": "<20210903192748.1408062-2-frode.nordahl@canonical.com>", "X-Mailer": "git-send-email 2.32.0", "In-Reply-To": "<20210903192748.1408062-1-frode.nordahl@canonical.com>", "References": "<20210903192748.1408062-1-frode.nordahl@canonical.com>", "MIME-Version": "1.0", "Subject": "[ovs-dev] [PATCH ovn v4 1/9] ovn-sb: Add requested_chassis column\n\tto Port_Binding.", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.15", "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>", "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": "To allow for ovn-controller to efficiently process unbound ports\nthat may be destined to it, for example for use in the optional\nplugging support, we add a new requested_chassis column with\nweakRef to the Chassis table. The ovn-controller can monitor\nthis column and only process events for its chassis UUID even\nbefore a local binding appears.\n\nnorthd will fill this column with UUID of Chassis referenced\nin Logical_Switch_Port options:requested-chassis by name or\nhostname.\n\nDeprecate the OVN_Southbound:Port_Binding:options\n\"requested-chassis\" key. In a subsequent update to the\ncontroller we will improve the efficiency of the requested-chassis\nfeature by using the new column instead of each chassis performing\noption processing and string comparison.\n\nNote that the CMS facing Northbound Logical_Switch_Port:options\nAPI remains the same.\n\nSigned-off-by: Frode Nordahl <frode.nordahl@canonical.com>\n---\n lib/chassis-index.c | 24 +++++++++\n lib/chassis-index.h | 3 ++\n northd/ovn-northd.c | 55 +++++++++++++++++--\n northd/ovn_northd.dl | 124 ++++++++++++++++++++++++++++++++++++++++---\n ovn-nb.xml | 33 ++++++++++--\n ovn-sb.ovsschema | 10 ++--\n ovn-sb.xml | 37 ++++++++++---\n tests/ovn-northd.at | 45 ++++++++++++++++\n 8 files changed, 307 insertions(+), 24 deletions(-)", "diff": "diff --git a/lib/chassis-index.c b/lib/chassis-index.c\nindex 13120fe3e..4b38036cb 100644\n--- a/lib/chassis-index.c\n+++ b/lib/chassis-index.c\n@@ -22,6 +22,12 @@ chassis_index_create(struct ovsdb_idl *idl)\n return ovsdb_idl_index_create1(idl, &sbrec_chassis_col_name);\n }\n \n+struct ovsdb_idl_index *\n+chassis_hostname_index_create(struct ovsdb_idl *idl)\n+{\n+ return ovsdb_idl_index_create1(idl, &sbrec_chassis_col_hostname);\n+}\n+\n /* Finds and returns the chassis with the given 'name', or NULL if no such\n * chassis exists. */\n const struct sbrec_chassis *\n@@ -40,6 +46,24 @@ chassis_lookup_by_name(struct ovsdb_idl_index *sbrec_chassis_by_name,\n return retval;\n }\n \n+/* Finds and returns the chassis with the given 'hostname', or NULL if no such\n+ * chassis exists. */\n+const struct sbrec_chassis *\n+chassis_lookup_by_hostname(struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n+ const char *hostname)\n+{\n+ struct sbrec_chassis *target = sbrec_chassis_index_init_row(\n+ sbrec_chassis_by_hostname);\n+ sbrec_chassis_index_set_hostname(target, hostname);\n+\n+ struct sbrec_chassis *retval = sbrec_chassis_index_find(\n+ sbrec_chassis_by_hostname, target);\n+\n+ sbrec_chassis_index_destroy_row(target);\n+\n+ return retval;\n+}\n+\n struct ovsdb_idl_index *\n chassis_private_index_create(struct ovsdb_idl *idl)\n {\ndiff --git a/lib/chassis-index.h b/lib/chassis-index.h\nindex b9b331f34..bc654da13 100644\n--- a/lib/chassis-index.h\n+++ b/lib/chassis-index.h\n@@ -19,9 +19,12 @@\n struct ovsdb_idl;\n \n struct ovsdb_idl_index *chassis_index_create(struct ovsdb_idl *);\n+struct ovsdb_idl_index *chassis_hostname_index_create(struct ovsdb_idl *);\n \n const struct sbrec_chassis *chassis_lookup_by_name(\n struct ovsdb_idl_index *sbrec_chassis_by_name, const char *name);\n+const struct sbrec_chassis *chassis_lookup_by_hostname(\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname, const char *hostname);\n \n struct ovsdb_idl_index *chassis_private_index_create(struct ovsdb_idl *);\n \ndiff --git a/northd/ovn-northd.c b/northd/ovn-northd.c\nindex ee761cef0..fdcc58e28 100644\n--- a/northd/ovn-northd.c\n+++ b/northd/ovn-northd.c\n@@ -76,6 +76,7 @@ struct northd_context {\n struct ovsdb_idl_txn *ovnnb_txn;\n struct ovsdb_idl_txn *ovnsb_txn;\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 struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp;\n struct ovsdb_idl_index *sbrec_ip_mcast_by_dp;\n@@ -3047,6 +3048,7 @@ ovn_update_ipv6_prefix(struct hmap *ports)\n static void\n ovn_port_update_sbrec(struct northd_context *ctx,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n const struct ovn_port *op,\n struct hmap *chassis_qdisc_queues,\n struct sset *active_ha_chassis_grps)\n@@ -3228,6 +3230,36 @@ ovn_port_update_sbrec(struct northd_context *ctx,\n * ha_chassis_group cleared in the same transaction. */\n sbrec_port_binding_set_ha_chassis_group(op->sb, NULL);\n }\n+\n+ const char *requested_chassis; /* May be NULL. */\n+ bool reset_requested_chassis = false;\n+ requested_chassis = smap_get(&op->nbsp->options,\n+ \"requested-chassis\");\n+ if (requested_chassis) {\n+ const struct sbrec_chassis *chassis; /* May be NULL. */\n+ chassis = chassis_lookup_by_name(sbrec_chassis_by_name,\n+ requested_chassis);\n+ chassis = chassis ? chassis : chassis_lookup_by_hostname(\n+ sbrec_chassis_by_hostname, requested_chassis);\n+\n+ if (chassis) {\n+ sbrec_port_binding_set_requested_chassis(op->sb, chassis);\n+ } else {\n+ reset_requested_chassis = true;\n+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(\n+ 1, 1);\n+ VLOG_WARN_RL(\n+ &rl,\n+ \"Unknown chassis '%s' set as \"\n+ \"options:requested-chassis on LSP '%s'.\",\n+ requested_chassis, op->nbsp->name);\n+ }\n+ } else if (op->sb->requested_chassis) {\n+ reset_requested_chassis = true;\n+ }\n+ if (reset_requested_chassis) {\n+ sbrec_port_binding_set_requested_chassis(op->sb, NULL);\n+ }\n } else {\n const char *chassis = NULL;\n if (op->peer && op->peer->od && op->peer->od->nbr) {\n@@ -3856,6 +3888,7 @@ ovn_port_allocate_key(struct hmap *ports, struct ovn_port *op)\n static void\n build_ports(struct northd_context *ctx,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n struct hmap *datapaths, struct hmap *ports)\n {\n struct ovs_list sb_only, nb_only, both;\n@@ -3911,6 +3944,7 @@ build_ports(struct northd_context *ctx,\n tag_alloc_create_new_tag(&tag_alloc_table, op->nbsp);\n }\n ovn_port_update_sbrec(ctx, sbrec_chassis_by_name,\n+ sbrec_chassis_by_hostname,\n op, &chassis_qdisc_queues,\n &active_ha_chassis_grps);\n }\n@@ -3918,7 +3952,8 @@ build_ports(struct northd_context *ctx,\n /* Add southbound record for each unmatched northbound record. */\n LIST_FOR_EACH_SAFE (op, next, list, &nb_only) {\n op->sb = sbrec_port_binding_insert(ctx->ovnsb_txn);\n- ovn_port_update_sbrec(ctx, sbrec_chassis_by_name, op,\n+ ovn_port_update_sbrec(ctx, sbrec_chassis_by_name,\n+ sbrec_chassis_by_hostname, op,\n &chassis_qdisc_queues,\n &active_ha_chassis_grps);\n sbrec_port_binding_set_logical_port(op->sb, op->key);\n@@ -14157,6 +14192,7 @@ get_probe_interval(const char *db, const struct nbrec_nb_global *nb)\n static void\n ovnnb_db_run(struct northd_context *ctx,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n struct ovsdb_idl_loop *sb_loop,\n struct hmap *datapaths, struct hmap *ports,\n struct ovs_list *lr_list,\n@@ -14260,7 +14296,8 @@ ovnnb_db_run(struct northd_context *ctx,\n build_datapaths(ctx, datapaths, lr_list);\n build_ovn_lbs(ctx, datapaths, &lbs);\n build_lrouter_lbs(datapaths, &lbs);\n- build_ports(ctx, sbrec_chassis_by_name, datapaths, ports);\n+ build_ports(ctx, sbrec_chassis_by_name, sbrec_chassis_by_hostname,\n+ datapaths, ports);\n build_ovn_lr_lbs(datapaths, &lbs);\n build_ovn_lb_svcs(ctx, ports, &lbs);\n build_ipam(datapaths, ports);\n@@ -14974,6 +15011,7 @@ ovnsb_db_run(struct northd_context *ctx,\n static void\n ovn_db_run(struct northd_context *ctx,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname,\n struct ovsdb_idl_loop *ovnsb_idl_loop,\n const char *ovn_internal_version)\n {\n@@ -14985,8 +15023,8 @@ ovn_db_run(struct northd_context *ctx,\n \n int64_t start_time = time_wall_msec();\n stopwatch_start(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());\n- ovnnb_db_run(ctx, sbrec_chassis_by_name, ovnsb_idl_loop,\n- &datapaths, &ports, &lr_list, start_time,\n+ ovnnb_db_run(ctx, sbrec_chassis_by_name, sbrec_chassis_by_hostname,\n+ ovnsb_idl_loop, &datapaths, &ports, &lr_list, start_time,\n ovn_internal_version);\n stopwatch_stop(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());\n stopwatch_start(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec());\n@@ -15237,6 +15275,8 @@ main(int argc, char *argv[])\n add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_mac);\n add_column_noalert(ovnsb_idl_loop.idl,\n &sbrec_port_binding_col_nat_addresses);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_requested_chassis);\n ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_chassis);\n ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n &sbrec_port_binding_col_gateway_chassis);\n@@ -15308,6 +15348,7 @@ main(int argc, char *argv[])\n \n ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis);\n ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_hostname);\n ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_other_config);\n ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_encaps);\n \n@@ -15416,6 +15457,9 @@ main(int argc, char *argv[])\n struct ovsdb_idl_index *sbrec_chassis_by_name\n = chassis_index_create(ovnsb_idl_loop.idl);\n \n+ struct ovsdb_idl_index *sbrec_chassis_by_hostname\n+ = chassis_hostname_index_create(ovnsb_idl_loop.idl);\n+\n struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name\n = ha_chassis_group_index_create(ovnsb_idl_loop.idl);\n \n@@ -15493,7 +15537,8 @@ main(int argc, char *argv[])\n }\n \n if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {\n- ovn_db_run(&ctx, sbrec_chassis_by_name, &ovnsb_idl_loop,\n+ ovn_db_run(&ctx, sbrec_chassis_by_name,\n+ sbrec_chassis_by_hostname, &ovnsb_idl_loop,\n ovn_internal_version);\n if (ctx.ovnsb_txn) {\n check_and_add_supported_dhcp_opts_to_sb_db(&ctx);\ndiff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl\nindex ff92c989c..85c62c547 100644\n--- a/northd/ovn_northd.dl\n+++ b/northd/ovn_northd.dl\n@@ -105,6 +105,22 @@ sb::Out_Datapath_Binding(uuid, tunkey, load_balancers, external_ids) :-\n */\n var load_balancers = set_empty().\n \n+function get_requested_chassis(options: Map<string,string>) : string = {\n+ var requested_chassis = match(options.get(\"requested-chassis\")) {\n+ None -> \"\",\n+ Some{requested_chassis} -> requested_chassis,\n+ };\n+ requested_chassis\n+}\n+\n+relation RequestedChassis(\n+ name: string,\n+ chassis: uuid,\n+)\n+RequestedChassis(name, chassis) :-\n+ sb::Chassis(._uuid = chassis, .name=name).\n+RequestedChassis(hostname, chassis) :-\n+ sb::Chassis(._uuid = chassis, .hostname=hostname).\n \n /* Proxy table for Out_Datapath_Binding: contains all Datapath_Binding fields,\n * except tunnel id, which is allocated separately (see PortTunKeyAllocation). */\n@@ -120,10 +136,12 @@ relation OutProxy_Port_Binding (\n tag: Option<integer>,\n mac: Set<string>,\n nat_addresses: Set<string>,\n- external_ids: Map<string,string>\n+ external_ids: Map<string,string>,\n+ requested_chassis: Option<uuid>\n )\n \n-/* Case 1: Create a Port_Binding per logical switch port that is not of type \"router\" */\n+/* Case 1a: Create a Port_Binding per logical switch port that is not of type\n+ * \"router\" */\n OutProxy_Port_Binding(._uuid = lsp._uuid,\n .logical_port = lsp.name,\n .__type = lsp.__type,\n@@ -135,7 +153,8 @@ OutProxy_Port_Binding(._uuid = lsp._uuid,\n .tag = tag,\n .mac = lsp.addresses,\n .nat_addresses = set_empty(),\n- .external_ids = eids) :-\n+ .external_ids = eids,\n+ .requested_chassis = None) :-\n sp in &SwitchPort(.lsp = lsp, .sw = sw),\n SwitchPortNewDynamicTag(lsp._uuid, opt_tag),\n var tag = match (opt_tag) {\n@@ -143,6 +162,8 @@ OutProxy_Port_Binding(._uuid = lsp._uuid,\n Some{t} -> Some{t}\n },\n lsp.__type != \"router\",\n+ var chassis_name_or_hostname = get_requested_chassis(lsp.options),\n+ chassis_name_or_hostname == \"\",\n var eids = {\n var eids = lsp.external_ids;\n match (lsp.external_ids.get(\"neutron:port_name\")) {\n@@ -160,6 +181,91 @@ OutProxy_Port_Binding(._uuid = lsp._uuid,\n options\n }.\n \n+/* Case 1b: Create a Port_Binding per logical switch port that is not of type\n+ * \"router\" and has options \"requested-chassis\" pointing at chassis name or\n+ * hostname. */\n+OutProxy_Port_Binding(._uuid = lsp._uuid,\n+ .logical_port = lsp.name,\n+ .__type = lsp.__type,\n+ .gateway_chassis = set_empty(),\n+ .ha_chassis_group = sp.hac_group_uuid,\n+ .options = options,\n+ .datapath = sw._uuid,\n+ .parent_port = lsp.parent_name,\n+ .tag = tag,\n+ .mac = lsp.addresses,\n+ .nat_addresses = set_empty(),\n+ .external_ids = eids,\n+ .requested_chassis = Some{requested_chassis}) :-\n+ sp in &SwitchPort(.lsp = lsp, .sw = sw),\n+ SwitchPortNewDynamicTag(lsp._uuid, opt_tag),\n+ var tag = match (opt_tag) {\n+ None -> lsp.tag,\n+ Some{t} -> Some{t}\n+ },\n+ lsp.__type != \"router\",\n+ var chassis_name_or_hostname = get_requested_chassis(lsp.options),\n+ chassis_name_or_hostname != \"\",\n+ RequestedChassis(chassis_name_or_hostname, requested_chassis),\n+ var eids = {\n+ var eids = lsp.external_ids;\n+ match (lsp.external_ids.get(\"neutron:port_name\")) {\n+ None -> (),\n+ Some{name} -> eids.insert(\"name\", name)\n+ };\n+ eids\n+ },\n+ var options = {\n+ var options = lsp.options;\n+ match (sw.other_config.get(\"vlan-passthru\")) {\n+ Some{\"true\"} -> options.insert(\"vlan-passthru\", \"true\"),\n+ _ -> ()\n+ };\n+ options\n+ }.\n+\n+/* Case 1c: Create a Port_Binding per logical switch port that is not of type\n+ * \"router\" and has options \"requested-chassis\" pointing at non-existent\n+ * chassis name or hostname. */\n+OutProxy_Port_Binding(._uuid = lsp._uuid,\n+ .logical_port = lsp.name,\n+ .__type = lsp.__type,\n+ .gateway_chassis = set_empty(),\n+ .ha_chassis_group = sp.hac_group_uuid,\n+ .options = options,\n+ .datapath = sw._uuid,\n+ .parent_port = lsp.parent_name,\n+ .tag = tag,\n+ .mac = lsp.addresses,\n+ .nat_addresses = set_empty(),\n+ .external_ids = eids,\n+ .requested_chassis = None) :-\n+ sp in &SwitchPort(.lsp = lsp, .sw = sw),\n+ SwitchPortNewDynamicTag(lsp._uuid, opt_tag),\n+ var tag = match (opt_tag) {\n+ None -> lsp.tag,\n+ Some{t} -> Some{t}\n+ },\n+ lsp.__type != \"router\",\n+ var chassis_name_or_hostname = get_requested_chassis(lsp.options),\n+ chassis_name_or_hostname != \"\",\n+ not RequestedChassis(chassis_name_or_hostname, _),\n+ var eids = {\n+ var eids = lsp.external_ids;\n+ match (lsp.external_ids.get(\"neutron:port_name\")) {\n+ None -> (),\n+ Some{name} -> eids.insert(\"name\", name)\n+ };\n+ eids\n+ },\n+ var options = {\n+ var options = lsp.options;\n+ match (sw.other_config.get(\"vlan-passthru\")) {\n+ Some{\"true\"} -> options.insert(\"vlan-passthru\", \"true\"),\n+ _ -> ()\n+ };\n+ options\n+ }.\n \n /* Case 2: Create a Port_Binding per logical switch port of type \"router\" */\n OutProxy_Port_Binding(._uuid = lsp._uuid,\n@@ -173,7 +279,8 @@ OutProxy_Port_Binding(._uuid = lsp._uuid,\n .tag = None,\n .mac = lsp.addresses,\n .nat_addresses = nat_addresses,\n- .external_ids = eids) :-\n+ .external_ids = eids,\n+ .requested_chassis = None) :-\n &SwitchPort(.lsp = lsp, .sw = sw, .peer = peer),\n var eids = {\n var eids = lsp.external_ids;\n@@ -263,7 +370,8 @@ OutProxy_Port_Binding(._uuid = lrp._uuid,\n .tag = None, // always empty for router ports\n .mac = set_singleton(\"${lrp.mac} ${lrp.networks.join(\\\" \\\")}\"),\n .nat_addresses = set_empty(),\n- .external_ids = lrp.external_ids) :-\n+ .external_ids = lrp.external_ids,\n+ .requested_chassis = None) :-\n rp in &RouterPort(.lrp = lrp, .router = router, .peer = peer),\n RouterPortRAOptionsComplete(lrp._uuid, options0),\n (var __type, var options1) = match (router.options.get(\"chassis\")) {\n@@ -471,7 +579,8 @@ OutProxy_Port_Binding(// lrp._uuid is already in use; generate a new UUID by\n .tag = None, //always empty for router ports\n .mac = set_singleton(\"${lrp.mac} ${lrp.networks.join(\\\" \\\")}\"),\n .nat_addresses = set_empty(),\n- .external_ids = lrp.external_ids) :-\n+ .external_ids = lrp.external_ids,\n+ .requested_chassis = None) :-\n DistributedGatewayPort(lrp, lr_uuid),\n DistributedGatewayPortHAChassisGroup(lrp, hacg_uuid),\n var redirect_type = match (lrp.options.get(\"redirect-type\")) {\n@@ -516,7 +625,8 @@ sb::Out_Port_Binding(._uuid = pbinding._uuid,\n .mac = pbinding.mac,\n .nat_addresses = pbinding.nat_addresses,\n .external_ids = pbinding.external_ids,\n- .up = Some{up}) :-\n+ .up = Some{up},\n+ .requested_chassis = pbinding.requested_chassis) :-\n pbinding in OutProxy_Port_Binding(),\n PortTunKeyAllocation(pbinding._uuid, tunkey),\n QueueIDAllocation(pbinding._uuid, qid),\ndiff --git a/ovn-nb.xml b/ovn-nb.xml\nindex 390cc5a44..ef2677d94 100644\n--- a/ovn-nb.xml\n+++ b/ovn-nb.xml\n@@ -995,11 +995,16 @@\n \n <column name=\"options\" key=\"requested-chassis\">\n If set, identifies a specific chassis (by name or hostname) that\n- is allowed to bind this port. Using this option will prevent\n+ is allowed to bind or plug this port. Using this option will prevent\n thrashing between two chassis trying to bind the same port during\n- a live migration. It can also prevent similar thrashing due to a\n+ a live migration. It can also prevent similar thrashing due to a\n mis-configuration, if a port is accidentally created on more than\n- one chassis.\n+ one chassis. This is also used to allow the controller consider\n+ unbound ports for plugging without having to process ports not\n+ destined for its chassis.\n+\n+ Setting this option is a prerequisite for using the\n+ <ref column=\"options\" key=\"plug-type\"/> option (see below).\n </column>\n \n <column name=\"options\" key=\"iface-id-ver\">\n@@ -1028,6 +1033,28 @@\n DHCP reply.\n </p>\n </column>\n+\n+ <group title=\"VIF Plugging Options\">\n+ <column name=\"options\" key=\"plug-type\">\n+ If set, OVN will attempt to to perform plugging of this VIF. In\n+ order to get this port plugged by the OVN controller, OVN must be\n+ built with support for VIF plugging. The default behavior is for\n+ the CMS to do the VIF plugging. Each plug provider have their own\n+ options namespaced by name, for example \"plug:representor:key\".\n+ Please refer to the plug provider documentation for more\n+ information.\n+\n+ Supported values: representor\n+ </column>\n+\n+ <column name=\"options\" key=\"plug-mtu-request\">\n+ Requested MTU for plugged interfaces. When set the OVN controller\n+ will fill the <ref table=\"Interface\" column=\"mtu_request\"/> column\n+ of the Open vSwitch database's\n+ <ref table=\"Interface\" db=\"vswitch\"/> table. This in turn will\n+ make OVS vswitchd update the MTU of the linked interface.\n+ </column>\n+ </group>\n </group>\n \n <group title=\"Virtual port Options\">\ndiff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema\nindex e5ab41db9..122614dd5 100644\n--- a/ovn-sb.ovsschema\n+++ b/ovn-sb.ovsschema\n@@ -1,7 +1,7 @@\n {\n \"name\": \"OVN_Southbound\",\n- \"version\": \"20.20.0\",\n- \"cksum\": \"605270161 26670\",\n+ \"version\": \"20.21.0\",\n+ \"cksum\": \"2362446865 26963\",\n \"tables\": {\n \"SB_Global\": {\n \"columns\": {\n@@ -232,7 +232,11 @@\n \"external_ids\": {\"type\": {\"key\": \"string\",\n \"value\": \"string\",\n \"min\": 0,\n- \"max\": \"unlimited\"}}},\n+ \"max\": \"unlimited\"}},\n+ \"requested_chassis\": {\"type\": {\"key\": {\"type\": \"uuid\",\n+ \"refTable\": \"Chassis\",\n+ \"refType\": \"weak\"},\n+ \"min\": 0, \"max\": 1}}},\n \"indexes\": [[\"datapath\", \"tunnel_key\"], [\"logical_port\"]],\n \"isRoot\": true},\n \"MAC_Binding\": {\ndiff --git a/ovn-sb.xml b/ovn-sb.xml\nindex 2d4d47d10..c966542e7 100644\n--- a/ovn-sb.xml\n+++ b/ovn-sb.xml\n@@ -2983,6 +2983,26 @@ tcp.flags = RST;\n </dd>\n </dl>\n </column>\n+ <column name=\"requested_chassis\">\n+ If set, identifies a specific chassis that is allowed to bind or plug\n+ this port. Having a value in this column will prevent thrashing\n+ between two chassis trying to bind the same port during a live\n+ migration.\n+ It can also prevent similar thrashing due to a mis-configuration, if a\n+ port is accidentally created on more than one chassis. This is also\n+ used to allow the controller consider unbound ports for plugging\n+ without having to process ports not destined for its chassis.\n+\n+ This column must be a\n+ <ref table=\"Chassis\"/> record. This is populated by\n+ <code>ovn-northd</code> when the <ref\n+ table=\"Logical_Switch_Port\"\n+ column=\"options\"\n+ key=\"requested-chassis\"\n+ db=\"OVN_Northbound\"/>\n+ is defined and contains a string matching the name or hostname of an\n+ existing chassis.\n+ </column>\n </group>\n \n <group title=\"Patch Options\">\n@@ -3141,12 +3161,17 @@ tcp.flags = RST;\n </p>\n \n <column name=\"options\" key=\"requested-chassis\">\n- If set, identifies a specific chassis (by name or hostname) that\n- is allowed to bind this port. Using this option will prevent\n- thrashing between two chassis trying to bind the same port during\n- a live migration. It can also prevent similar thrashing due to a\n- mis-configuration, if a port is accidentally created on more than\n- one chassis.\n+ Deprecated. This option has been replaced by a separate column\n+ <ref\n+ table=\"Port_Binding\"\n+ column=\"requested_chassis\"\n+ db=\"OVN_Southbound\"/>\n+ and may at some point in the future no longer be copied over from\n+ <ref\n+ table=\"Logical_Switch_Port\"\n+ column=\"options\"\n+ key=\"requested-chassis\"\n+ db=\"OVN_Northbound\"/>.\n </column>\n \n <column name=\"options\" key=\"iface-id-ver\">\ndiff --git a/tests/ovn-northd.at b/tests/ovn-northd.at\nindex 11886b94e..8ccf806c7 100644\n--- a/tests/ovn-northd.at\n+++ b/tests/ovn-northd.at\n@@ -5225,3 +5225,48 @@ AT_CHECK([grep lr_in_gw_redirect lrflows | grep cr-DR | sed 's/table=../table=??\n \n AT_CLEANUP\n ])\n+\n+OVN_FOR_EACH_NORTHD([\n+AT_SETUP([check options:requested-chassis fills requested_chassis col])\n+ovn_start NORTHD_TYPE\n+\n+# Add chassis ch1.\n+check ovn-sbctl chassis-add ch1 geneve 127.0.0.2\n+check ovn-sbctl chassis-add ch2 geneve 127.0.0.3\n+\n+wait_row_count Chassis 2\n+\n+ch1_uuid=`ovn-sbctl --bare --columns _uuid find Chassis name=\"ch1\"`\n+ch2_uuid=`ovn-sbctl --bare --columns _uuid find Chassis name=\"ch2\"`\n+\n+check ovn-sbctl set chassis $ch2_uuid hostname=ch2-hostname\n+\n+ovn-nbctl ls-add S1\n+ovn-nbctl --wait=sb lsp-add S1 S1-vm1\n+ovn-nbctl --wait=sb lsp-add S1 S1-vm2\n+\n+wait_row_count Port_Binding 1 logical_port=S1-vm1 requested_chassis!=$ch1_uuid\n+wait_row_count Port_Binding 1 logical_port=S1-vm2 requested_chassis!=$ch2_uuid\n+\n+ovn-nbctl --wait=sb set logical_switch_port S1-vm1 \\\n+ options:requested-chassis=ch1\n+\n+wait_row_count Port_Binding 1 logical_port=S1-vm1 requested_chassis=$ch1_uuid\n+\n+ovn-nbctl --wait=sb set logical_switch_port S1-vm2 \\\n+ options:requested-chassis=ch2-hostname\n+\n+wait_row_count Port_binding 1 logical-port=S1-vm2 requested_chassis=$ch2_uuid\n+\n+ovn-nbctl --wait=sb remove logical_switch_port S1-vm2 \\\n+ options requested-chassis=ch2-hostname\n+\n+wait_row_count Port_binding 1 logical-port=S1-vm2 requested_chassis!=$ch2_uuid\n+\n+ovn-nbctl --wait=sb set logical_switch_port S1-vm2 \\\n+ options:requested-chassis=ch2\n+\n+wait_row_count Port_binding 1 logical-port=S1-vm2 requested_chassis=$ch2_uuid\n+\n+AT_CLEANUP\n+])\n", "prefixes": [ "ovs-dev", "v4", "1/9" ] }