From patchwork Wed Jan 6 16:37:37 2021
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Dumitru Ceara
X-Patchwork-Id: 1423004
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org
(client-ip=140.211.166.136; helo=silver.osuosl.org;
envelope-from=ovs-dev-bounces@openvswitch.org; receiver=)
Authentication-Results: ozlabs.org;
dmarc=fail (p=none dis=none) header.from=redhat.com
Authentication-Results: ozlabs.org;
dkim=fail reason="signature verification failed" (1024-bit key;
unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256
header.s=mimecast20190719 header.b=TlEe7ozi;
dkim-atps=neutral
Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 4D9w612w2Qz9sVb
for ; Thu, 7 Jan 2021 03:38:17 +1100 (AEDT)
Received: from localhost (localhost [127.0.0.1])
by silver.osuosl.org (Postfix) with ESMTP id 99A9A27366;
Wed, 6 Jan 2021 16:38:15 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from silver.osuosl.org ([127.0.0.1])
by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id 7SvdaYATnAap; Wed, 6 Jan 2021 16:38:00 +0000 (UTC)
Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])
by silver.osuosl.org (Postfix) with ESMTP id DFDDF272BB;
Wed, 6 Jan 2021 16:37:59 +0000 (UTC)
Received: from lf-lists.osuosl.org (localhost [127.0.0.1])
by lists.linuxfoundation.org (Postfix) with ESMTP id C6E2DC0891;
Wed, 6 Jan 2021 16:37:59 +0000 (UTC)
X-Original-To: dev@openvswitch.org
Delivered-To: ovs-dev@lists.linuxfoundation.org
Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])
by lists.linuxfoundation.org (Postfix) with ESMTP id BFF48C013A
for ; Wed, 6 Jan 2021 16:37:58 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by whitealder.osuosl.org (Postfix) with ESMTP id AF49A86BE1
for ; Wed, 6 Jan 2021 16:37:58 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from whitealder.osuosl.org ([127.0.0.1])
by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id zZF01LN+g9g8 for ;
Wed, 6 Jan 2021 16:37:52 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6
Received: from us-smtp-delivery-124.mimecast.com
(us-smtp-delivery-124.mimecast.com [216.205.24.124])
by whitealder.osuosl.org (Postfix) with ESMTPS id DC22786BCB
for ; Wed, 6 Jan 2021 16:37:44 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;
s=mimecast20190719; t=1609951063;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=ucmV4e2Rw0TTqD4/0/6qZgfmdaSwxtmEwKLxPTJh/Sg=;
b=TlEe7ozi+35Tn0woiW97Ej9SchcTZEXOPSnK05l5YYbwwA0qzYvt/gnekFiEyfmJaGfXG9
fuLgSW49+rpjyZgkARXLOAgo3yVLs+3xZ8oBYJrd+GX3Z8wdnP57eIHvraLw7DhQQ03i67
mIoezLen6qDNLB0PTFGEJLK++zuBw/M=
Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com
[209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id
us-mta-313-4xuhZ7cENkGsikUm9By23Q-1; Wed, 06 Jan 2021 11:37:41 -0500
X-MC-Unique: 4xuhZ7cENkGsikUm9By23Q-1
Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com
[10.5.11.16])
(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))
(No client certificate requested)
by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E68708049C4
for ; Wed, 6 Jan 2021 16:37:40 +0000 (UTC)
Received: from dceara.remote.csb (ovpn-113-197.ams2.redhat.com
[10.36.113.197])
by smtp.corp.redhat.com (Postfix) with ESMTP id 198FC5C1C4
for ; Wed, 6 Jan 2021 16:37:39 +0000 (UTC)
From: Dumitru Ceara
To: dev@openvswitch.org
Date: Wed, 6 Jan 2021 17:37:37 +0100
Message-Id: <20210106163734.20347.51643.stgit@dceara.remote.csb>
In-Reply-To: <20210106163634.20347.76943.stgit@dceara.remote.csb>
References: <20210106163634.20347.76943.stgit@dceara.remote.csb>
User-Agent: StGit/0.17.1-dirty
MIME-Version: 1.0
X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16
Authentication-Results: relay.mimecast.com;
auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=dceara@redhat.com
X-Mimecast-Spam-Score: 0
X-Mimecast-Originator: redhat.com
Subject: [ovs-dev] [PATCH ovn 3/3] binding: Set Logical_Switch_Port.up when
all OVS flows are installed.
X-BeenThere: ovs-dev@openvswitch.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id:
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: ovs-dev-bounces@openvswitch.org
Sender: "dev"
Using the ofctrl-seqno generic barrier, register a new type of
notifications for Port_Bindings. This allows us to delay setting
the Logical_Switch_Port.up field until all OVS flows corresponding
to the logical port and underlying OVS interface have been installed.
This commit also marks the OVS interface as "installed by OVN" by
setting a new "ovn-installed" external-id in the OVS Interface record
when the port is fully wired by OVN.
Signed-off-by: Dumitru Ceara
---
NEWS | 6 +
controller/binding.c | 174 +++++++++++++++++++++++++++++++++++++++++++
controller/binding.h | 5 +
controller/ovn-controller.c | 14 +++
northd/ovn-northd.c | 4 +
ovn-sb.ovsschema | 5 +
ovn-sb.xml | 8 ++
utilities/ovn-sbctl.c | 4 +
8 files changed, 214 insertions(+), 6 deletions(-)
diff --git a/NEWS b/NEWS
index f0ac94b..058ebe4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,12 @@
Post-v20.12.0
-------------------------
- Support ECMP multiple nexthops for reroute router policies.
+ - Change the semantic of the "Logical_Switch_Port.up" field such that it is
+ set to "true" only when all corresponding OVS openflow operations have
+ been processed. This also introduces a new "OVS.Interface.external-id",
+ "ovn-installed". This external-id is set by ovn-controller only after all
+ openflow operations corresponding to the OVS interface being added have
+ been processed.
OVN v20.12.0 - xx xxx xxxx
--------------------------
diff --git a/controller/binding.c b/controller/binding.c
index e632203..8582e45 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -18,6 +18,7 @@
#include "ha-chassis.h"
#include "lflow.h"
#include "lport.h"
+#include "ofctrl-seqno.h"
#include "patch.h"
#include "lib/bitmap.h"
@@ -34,6 +35,38 @@
VLOG_DEFINE_THIS_MODULE(binding);
+/* External ID to be set in the OVS.Interface record when the OVS interface
+ * is ready for use, i.e., is bound to an OVN port and its corresponding
+ * flows have been installed.
+ */
+#define OVN_INSTALLED_EXT_ID "ovn-installed"
+
+/* Set of OVS interface IDs that have been released in the most recent
+ * processing iterations. This gets updated in release_lport() and is
+ * periodically emptied in binding_seqno_run().
+ */
+static struct sset binding_iface_released_set =
+ SSET_INITIALIZER(&binding_iface_released_set);
+
+/* Set of OVS interface IDs that have been bound in the most recent
+ * processing iterations. This gets updated in release_lport() and is
+ * periodically emptied in binding_seqno_run().
+ */
+static struct sset binding_iface_bound_set =
+ SSET_INITIALIZER(&binding_iface_bound_set);
+
+static void
+binding_iface_released_add(const char *iface_id)
+{
+ sset_add(&binding_iface_released_set, iface_id);
+}
+
+static void
+binding_iface_bound_add(const char *iface_id)
+{
+ sset_add(&binding_iface_bound_set, iface_id);
+}
+
#define OVN_QOS_TYPE "linux-htb"
struct qos_queue {
@@ -837,6 +870,7 @@ claim_lport(const struct sbrec_port_binding *pb,
return false;
}
+ binding_iface_bound_add(pb->logical_port);
if (pb->chassis) {
VLOG_INFO("Changing chassis for lport %s from %s to %s.",
pb->logical_port, pb->chassis->name,
@@ -900,7 +934,9 @@ release_lport(const struct sbrec_port_binding *pb, bool sb_readonly,
sbrec_port_binding_set_virtual_parent(pb, NULL);
}
+ sbrec_port_binding_set_up(pb, NULL, 0);
update_lport_tracking(pb, tracked_datapaths);
+ binding_iface_released_add(pb->logical_port);
VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port);
return true;
}
@@ -2287,3 +2323,141 @@ binding_handle_port_binding_changes(struct binding_ctx_in *b_ctx_in,
destroy_qos_map(&qos_map);
return handled;
}
+
+/* Registered ofctrl seqno type for port_binding flow installation. */
+static size_t binding_seq_type_pb_cfg;
+
+/* Binding specific seqno to be acked by ofctrl when flows for new interfaces
+ * have been installed.
+ */
+static uint32_t binding_iface_seqno = 0;
+
+/* Map indexed by iface-id containing the sequence numbers that when acked
+ * indicate that the OVS flows for the iface-id have been installed.
+ */
+static struct simap binding_iface_seqno_map =
+ SIMAP_INITIALIZER(&binding_iface_seqno_map);
+
+void
+binding_init(void)
+{
+ binding_seq_type_pb_cfg = ofctrl_seqno_add_type();
+}
+
+/* Processes new release/bind operations OVN ports. For newly bound ports
+ * it creates ofctrl seqno update requests that will be acked when
+ * corresponding OVS flows have been installed.
+ *
+ * NOTE: Should be called only when valid SB and OVS transactions are
+ * available.
+ */
+void
+binding_seqno_run(struct shash *local_bindings)
+{
+ const char *iface_id;
+ const char *iface_id_next;
+
+ SSET_FOR_EACH_SAFE (iface_id, iface_id_next, &binding_iface_released_set) {
+ struct shash_node *lb_node = shash_find(local_bindings, iface_id);
+
+ /* If the local binding still exists (i.e., the OVS interface is
+ * still configured locally) then remove the external id and remove
+ * it from the in-flight seqno map.
+ */
+ if (lb_node) {
+ struct local_binding *lb = lb_node->data;
+
+ if (lb->iface && smap_get(&lb->iface->external_ids,
+ OVN_INSTALLED_EXT_ID)) {
+ ovsrec_interface_update_external_ids_delkey(
+ lb->iface, OVN_INSTALLED_EXT_ID);
+ }
+ }
+ simap_find_and_delete(&binding_iface_seqno_map, iface_id);
+ sset_delete(&binding_iface_released_set,
+ SSET_NODE_FROM_NAME(iface_id));
+ }
+
+ bool new_ifaces = false;
+ uint32_t new_seqno = binding_iface_seqno + 1;
+
+ SSET_FOR_EACH_SAFE (iface_id, iface_id_next, &binding_iface_bound_set) {
+ struct shash_node *lb_node = shash_find(local_bindings, iface_id);
+
+ if (lb_node) {
+ /* This is a newly bound interface, make sure we reset the
+ * Port_Binding 'up' field and the OVS Interface 'external-id'.
+ */
+ struct local_binding *lb = lb_node->data;
+
+ ovs_assert(lb->pb && lb->iface);
+ new_ifaces = true;
+
+ if (lb->iface && smap_get(&lb->iface->external_ids,
+ OVN_INSTALLED_EXT_ID)) {
+ ovsrec_interface_update_external_ids_delkey(
+ lb->iface, OVN_INSTALLED_EXT_ID);
+ }
+ if (lb->pb) {
+ sbrec_port_binding_set_up(lb->pb, NULL, 0);
+ }
+ simap_put(&binding_iface_seqno_map, lb->name, new_seqno);
+ }
+ sset_delete(&binding_iface_bound_set, SSET_NODE_FROM_NAME(iface_id));
+ }
+
+ /* Request a seqno update when the flows for new interfaces have been
+ * installed in OVS.
+ */
+ if (new_ifaces) {
+ binding_iface_seqno = new_seqno;
+ ofctrl_seqno_update_create(binding_seq_type_pb_cfg, new_seqno);
+ }
+}
+
+/* Processes ofctrl seqno ACKs for new bindings. Sets the
+ * 'OVN_INSTALLED_EXT_ID' external-id in the OVS interface and the
+ * Port_Binding.up field for all ports for which OVS flows have been
+ * installed.
+ *
+ * NOTE: Should be called only when valid SB and OVS transactions are
+ * available.
+ */
+void
+binding_seqno_install(struct shash *local_bindings)
+{
+ struct ofctrl_acked_seqnos *acked_seqnos =
+ ofctrl_acked_seqnos_get(binding_seq_type_pb_cfg);
+ struct simap_node *node;
+ struct simap_node *node_next;
+
+ SIMAP_FOR_EACH_SAFE (node, node_next, &binding_iface_seqno_map) {
+ if (!ofctrl_acked_seqnos_contains(acked_seqnos, node->data)) {
+ continue;
+ }
+
+ struct shash_node *lb_node = shash_find(local_bindings, node->name);
+ struct local_binding *lb = lb_node->data;
+ bool up = true;
+
+ ovsrec_interface_update_external_ids_setkey(lb->iface,
+ OVN_INSTALLED_EXT_ID,
+ "true");
+ sbrec_port_binding_set_up(lb->pb, &up, 1);
+
+ struct shash_node *child_node;
+ SHASH_FOR_EACH (child_node, &lb->children) {
+ struct local_binding *lb_child = child_node->data;
+ sbrec_port_binding_set_up(lb_child->pb, &up, 1);
+ }
+ simap_delete(&binding_iface_seqno_map, node);
+ }
+
+ ofctrl_acked_seqnos_destroy(acked_seqnos);
+}
+
+void
+binding_seqno_flush(void)
+{
+ simap_clear(&binding_iface_seqno_map);
+}
diff --git a/controller/binding.h b/controller/binding.h
index c974056..3bb1690 100644
--- a/controller/binding.h
+++ b/controller/binding.h
@@ -134,4 +134,9 @@ bool binding_handle_ovs_interface_changes(struct binding_ctx_in *,
bool binding_handle_port_binding_changes(struct binding_ctx_in *,
struct binding_ctx_out *);
void binding_tracked_dp_destroy(struct hmap *tracked_datapaths);
+
+void binding_init(void);
+void binding_seqno_run(struct shash *local_bindings);
+void binding_seqno_install(struct shash *local_bindings);
+void binding_seqno_flush(void);
#endif /* controller/binding.h */
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 7a7825d..f3951b6 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -981,6 +981,7 @@ en_ofctrl_is_connected_run(struct engine_node *node, void *data)
/* Flush ofctrl seqno requests when the ofctrl connection goes down. */
if (!of_data->connected) {
ofctrl_seqno_flush();
+ binding_seqno_flush();
}
engine_set_node_state(node, EN_UPDATED);
return;
@@ -2404,13 +2405,14 @@ main(int argc, char *argv[])
daemonize_complete();
+ /* Register ofctrl seqno types. */
+ ofctrl_seq_type_nb_cfg = ofctrl_seqno_add_type();
+
+ binding_init();
patch_init();
pinctrl_init();
lflow_init();
- /* Register ofctrl seqno types. */
- ofctrl_seq_type_nb_cfg = ofctrl_seqno_add_type();
-
/* Connect to OVS OVSDB instance. */
struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
@@ -2878,6 +2880,9 @@ main(int argc, char *argv[])
ovnsb_idl_loop.idl),
ovnsb_cond_seqno,
ovnsb_expected_cond_seqno));
+ if (runtime_data && ovs_idl_txn && ovnsb_idl_txn) {
+ binding_seqno_run(&runtime_data->local_bindings);
+ }
flow_output_data = engine_get_data(&en_flow_output);
if (flow_output_data && ct_zones_data) {
@@ -2888,6 +2893,9 @@ main(int argc, char *argv[])
engine_node_changed(&en_flow_output));
}
ofctrl_seqno_run(ofctrl_get_cur_cfg());
+ if (runtime_data && ovs_idl_txn && ovnsb_idl_txn) {
+ binding_seqno_install(&runtime_data->local_bindings);
+ }
}
}
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index f6acdc1..a9e8edf 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -12678,7 +12678,7 @@ handle_port_binding_changes(struct northd_context *ctx, struct hmap *ports,
continue;
}
- bool up = (sb->chassis || lsp_is_router(op->nbsp));
+ bool up = ((sb->up && (*sb->up)) || lsp_is_router(op->nbsp));
if (!op->nbsp->up || *op->nbsp->up != up) {
nbrec_logical_switch_port_set_up(op->nbsp, &up, 1);
}
@@ -13315,6 +13315,8 @@ main(int argc, char *argv[])
ovsdb_idl_add_column(ovnsb_idl_loop.idl,
&sbrec_port_binding_col_virtual_parent);
ovsdb_idl_add_column(ovnsb_idl_loop.idl,
+ &sbrec_port_binding_col_up);
+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,
&sbrec_gateway_chassis_col_chassis);
ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_gateway_chassis_col_name);
ovsdb_idl_add_column(ovnsb_idl_loop.idl,
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index 5228839..b47879a 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
{
"name": "OVN_Southbound",
- "version": "20.12.0",
- "cksum": "3969471120 24441",
+ "version": "20.12.1",
+ "cksum": "1448228268 24513",
"tables": {
"SB_Global": {
"columns": {
@@ -225,6 +225,7 @@
"nat_addresses": {"type": {"key": "string",
"min": 0,
"max": "unlimited"}},
+ "up": {"type": {"key": "boolean", "min": 0, "max": 1}},
"external_ids": {"type": {"key": "string",
"value": "string",
"min": 0,
diff --git a/ovn-sb.xml b/ovn-sb.xml
index c139948..744bbfc 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -2771,6 +2771,14 @@ tcp.flags = RST;
+
+
+ This is set to true
whenever all OVS flows
+ required by this Port_Binding have been installed. This is
+ populated by ovn-controller
.
+
+
+
A number that represents the logical port in the key (e.g. STT key or
diff --git a/utilities/ovn-sbctl.c b/utilities/ovn-sbctl.c
index 0a1b9ff..c38e8ec 100644
--- a/utilities/ovn-sbctl.c
+++ b/utilities/ovn-sbctl.c
@@ -526,6 +526,7 @@ pre_get_info(struct ctl_context *ctx)
ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_tunnel_key);
ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_chassis);
ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_datapath);
+ ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_up);
ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_datapath);
ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_dp_group);
@@ -665,6 +666,7 @@ cmd_lsp_bind(struct ctl_context *ctx)
struct sbctl_chassis *sbctl_ch;
struct sbctl_port_binding *sbctl_bd;
char *lport_name, *ch_name;
+ bool up = true;
/* port_binding must exist, chassis must exist! */
lport_name = ctx->argv[1];
@@ -683,6 +685,7 @@ cmd_lsp_bind(struct ctl_context *ctx)
}
}
sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, sbctl_ch->ch_cfg);
+ sbrec_port_binding_set_up(sbctl_bd->bd_cfg, &up, 1);
sbctl_context_invalidate_cache(ctx);
}
@@ -699,6 +702,7 @@ cmd_lsp_unbind(struct ctl_context *ctx)
sbctl_bd = find_port_binding(sbctl_ctx, lport_name, must_exist);
if (sbctl_bd) {
sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, NULL);
+ sbrec_port_binding_set_up(sbctl_bd->bd_cfg, NULL, 0);
}
}