From patchwork Fri Aug 5 16:27:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1664129 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.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=NFf8T3hX; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Lzrbb1H3wz9sB4 for ; Sat, 6 Aug 2022 02:27:23 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 2861D41DC4; Fri, 5 Aug 2022 16:27:21 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 2861D41DC4 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=NFf8T3hX X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id W_dePND1yvO3; Fri, 5 Aug 2022 16:27:19 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 3067A41DDE; Fri, 5 Aug 2022 16:27:18 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 3067A41DDE Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 01975C0032; Fri, 5 Aug 2022 16:27:18 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5B057C002D for ; Fri, 5 Aug 2022 16:27:16 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 30CEE83EEF for ; Fri, 5 Aug 2022 16:27:16 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 30CEE83EEF Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=NFf8T3hX X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TDu98KwrmwFb for ; Fri, 5 Aug 2022 16:27:12 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 567C783F17 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 567C783F17 for ; Fri, 5 Aug 2022 16:27:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1659716831; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Yz5T6tjczL4jmqG/QqN4QCPT+BWMWKKLB4BPt+XWUDY=; b=NFf8T3hXjdPmaJ0TsKQGU+j5vgSGQNeQ+L8xhB/eORFc8HHXuJKRR7ElpO+cUjG9PDjrHF xVt0YSWogOWGqeeLQXedMlH4ef4uK7ltAPDzJH3X+x2JIk4lOeUuCxdF4lGhWGQZmttNWh 8okU160HW5AF0QqwSpzztV7TLbA1jWk= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-611--MaCHRE2N0WrUb-I6oaV2w-1; Fri, 05 Aug 2022 12:27:09 -0400 X-MC-Unique: -MaCHRE2N0WrUb-I6oaV2w-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 30A2F811E75 for ; Fri, 5 Aug 2022 16:27:09 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.192.97]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3EDAB1121314; Fri, 5 Aug 2022 16:27:08 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Fri, 5 Aug 2022 18:27:05 +0200 Message-Id: <165971682264.246236.16785225575256752280.stgit@dceara.remote.csb> In-Reply-To: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> References: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: surya@redhat.com Subject: [ovs-dev] [RFC PATCH ovn 1/5] Add NB and SB Template_Var tables. 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" Propagate the contents of the NB table to the Southbound. Signed-off-by: Dumitru Ceara --- TODO: - Document the new Template_Var tables. --- lib/automake.mk | 2 ++ lib/template-var.c | 41 +++++++++++++++++++++++++++++++++++++++++ lib/template-var.h | 28 ++++++++++++++++++++++++++++ northd/en-northd.c | 6 ++++++ northd/inc-proc-northd.c | 14 ++++++++++++-- northd/northd.c | 33 +++++++++++++++++++++++++++++++++ northd/northd.h | 2 ++ ovn-nb.ovsschema | 16 +++++++++++++--- ovn-nb.xml | 7 +++++++ ovn-sb.ovsschema | 11 +++++++++-- ovn-sb.xml | 6 ++++++ 11 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 lib/template-var.c create mode 100644 lib/template-var.h diff --git a/lib/automake.mk b/lib/automake.mk index 3a2da1fe4..7ae5528fb 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -41,6 +41,8 @@ lib_libovn_la_SOURCES = \ lib/static-mac-binding-index.c \ lib/static-mac-binding-index.h \ lib/stopwatch-names.h \ + lib/template-var.c \ + lib/template-var.h \ lib/vif-plug-provider.h \ lib/vif-plug-provider.c \ lib/vif-plug-providers/dummy/vif-plug-dummy.c diff --git a/lib/template-var.c b/lib/template-var.c new file mode 100644 index 000000000..1a6d4dfbb --- /dev/null +++ b/lib/template-var.c @@ -0,0 +1,41 @@ +/* Copyright (c) 2022 Red Hat, Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "lib/template-var.h" + +struct ovsdb_idl_index * +sbrec_template_var_by_name_chassis_index_create(struct ovsdb_idl *idl) +{ + return ovsdb_idl_index_create2(idl, &sbrec_template_var_col_name, + &sbrec_template_var_col_chassis); +} + +const struct sbrec_template_var * +sb_template_var_lookup_by_name_chassis( + struct ovsdb_idl_index *sbrec_template_var_by_name_chassis, + const char *name, const char *chassis) +{ + struct sbrec_template_var *target = + sbrec_template_var_index_init_row(sbrec_template_var_by_name_chassis); + sbrec_template_var_index_set_name(target, name); + sbrec_template_var_index_set_chassis(target, chassis); + + struct sbrec_template_var *retval = + sbrec_template_var_index_find(sbrec_template_var_by_name_chassis, + target); + sbrec_template_var_index_destroy_row(target); + return retval; +} diff --git a/lib/template-var.h b/lib/template-var.h new file mode 100644 index 000000000..33351055f --- /dev/null +++ b/lib/template-var.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2022, Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OVN_TEMPLATE_VAR_H +#define OVN_TEMPLATE_VAR_H 1 + +#include "ovn-sb-idl.h" + +struct ovsdb_idl_index *sbrec_template_var_by_name_chassis_index_create( + struct ovsdb_idl *idl); + +const struct sbrec_template_var *sb_template_var_lookup_by_name_chassis( + struct ovsdb_idl_index *sbrec_template_var_by_name_chassis, + const char *name, const char *chassis); + +#endif /* lib/template-var.h */ diff --git a/northd/en-northd.c b/northd/en-northd.c index 4907a1ff2..ec89ec002 100644 --- a/northd/en-northd.c +++ b/northd/en-northd.c @@ -59,6 +59,10 @@ void en_northd_run(struct engine_node *node, void *data) engine_ovsdb_node_get_index( engine_get_input("SB_static_mac_binding", node), "sbrec_static_mac_binding_by_lport_ip"); + input_data.sbrec_template_var_by_name_chassis = + engine_ovsdb_node_get_index( + engine_get_input("SB_template_var", node), + "sbrec_template_var_by_name_chassis"); input_data.nbrec_nb_global_table = EN_OVSDB_GET(engine_get_input("NB_nb_global", node)); @@ -78,6 +82,8 @@ void en_northd_run(struct engine_node *node, void *data) EN_OVSDB_GET(engine_get_input("NB_acl", node)); input_data.nbrec_static_mac_binding_table = EN_OVSDB_GET(engine_get_input("NB_static_mac_binding", node)); + input_data.nbrec_template_var_table = + EN_OVSDB_GET(engine_get_input("NB_template_var", node)); input_data.sbrec_sb_global_table = EN_OVSDB_GET(engine_get_input("SB_sb_global", node)); diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index 43093cb5a..feb0ffe04 100644 --- a/northd/inc-proc-northd.c +++ b/northd/inc-proc-northd.c @@ -24,6 +24,7 @@ #include "lib/inc-proc-eng.h" #include "lib/ovn-nb-idl.h" #include "lib/ovn-sb-idl.h" +#include "lib/template-var.h" #include "mcast-group-index.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" @@ -62,7 +63,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd); NB_NODE(ha_chassis_group, "ha_chassis_group") \ NB_NODE(ha_chassis, "ha_chassis") \ NB_NODE(bfd, "bfd") \ - NB_NODE(static_mac_binding, "static_mac_binding") + NB_NODE(static_mac_binding, "static_mac_binding") \ + NB_NODE(template_var, "template_var") enum nb_engine_node { #define NB_NODE(NAME, NAME_STR) NB_##NAME, @@ -112,7 +114,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_northd); SB_NODE(load_balancer, "load_balancer") \ SB_NODE(bfd, "bfd") \ SB_NODE(fdb, "fdb") \ - SB_NODE(static_mac_binding, "static_mac_binding") + SB_NODE(static_mac_binding, "static_mac_binding") \ + SB_NODE(template_var, "template_var") enum sb_engine_node { #define SB_NODE(NAME, NAME_STR) SB_##NAME, @@ -182,6 +185,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_northd, &en_nb_ha_chassis_group, NULL); engine_add_input(&en_northd, &en_nb_ha_chassis, NULL); engine_add_input(&en_northd, &en_nb_static_mac_binding, NULL); + engine_add_input(&en_northd, &en_nb_template_var, NULL); engine_add_input(&en_northd, &en_sb_sb_global, NULL); engine_add_input(&en_northd, &en_sb_chassis, NULL); @@ -211,6 +215,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_northd, &en_sb_load_balancer, NULL); engine_add_input(&en_northd, &en_sb_fdb, NULL); engine_add_input(&en_northd, &en_sb_static_mac_binding, NULL); + engine_add_input(&en_northd, &en_sb_template_var, NULL); engine_add_input(&en_lflow, &en_nb_bfd, NULL); engine_add_input(&en_lflow, &en_sb_bfd, NULL); engine_add_input(&en_lflow, &en_sb_logical_flow, NULL); @@ -235,6 +240,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, chassis_hostname_index_create(sb->idl); struct ovsdb_idl_index *sbrec_static_mac_binding_by_lport_ip = static_mac_binding_index_create(sb->idl); + struct ovsdb_idl_index *sbrec_template_var_by_name_chassis + = sbrec_template_var_by_name_chassis_index_create(sb->idl); engine_init(&en_lflow, &engine_arg); @@ -256,6 +263,9 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_ovsdb_node_add_index(&en_sb_static_mac_binding, "sbrec_static_mac_binding_by_lport_ip", sbrec_static_mac_binding_by_lport_ip); + engine_ovsdb_node_add_index(&en_sb_template_var, + "sbrec_template_var_by_name_chassis", + sbrec_template_var_by_name_chassis); } void inc_proc_northd_run(struct ovsdb_idl_txn *ovnnb_txn, diff --git a/northd/northd.c b/northd/northd.c index 0fcd3a642..c4769ea07 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -36,6 +36,7 @@ #include "lib/ovn-sb-idl.h" #include "lib/ovn-util.h" #include "lib/lb.h" +#include "lib/template-var.h" #include "memory.h" #include "northd.h" #include "lib/ovn-parallel-hmap.h" @@ -14973,6 +14974,36 @@ sync_dns_entries(struct northd_input *input_data, } hmap_destroy(&dns_map); } + +static void +sync_template_var(struct ovsdb_idl_txn *ovnsb_txn, + struct ovsdb_idl_index *sbrec_template_var_by_name_chassis, + const char *name, const char *value, const char *chassis) +{ + const struct sbrec_template_var *sb_tv = + sb_template_var_lookup_by_name_chassis( + sbrec_template_var_by_name_chassis, name, chassis); + + if (!sb_tv) { + sb_tv = sbrec_template_var_insert(ovnsb_txn); + sbrec_template_var_set_name(sb_tv, name); + sbrec_template_var_set_chassis(sb_tv, chassis); + } + sbrec_template_var_set_value(sb_tv, value); +} + +static void +sync_template_vars(struct northd_input *input_data, + struct ovsdb_idl_txn *ovnsb_txn) +{ + const struct nbrec_template_var *nb_tv; + NBREC_TEMPLATE_VAR_TABLE_FOR_EACH (nb_tv, + input_data->nbrec_template_var_table) { + sync_template_var(ovnsb_txn, + input_data->sbrec_template_var_by_name_chassis, + nb_tv->name, nb_tv->value, nb_tv->chassis); + } +} static void destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ports, @@ -15476,6 +15507,8 @@ ovnnb_db_run(struct northd_input *input_data, sync_port_groups(input_data, ovnsb_txn, &data->port_groups); sync_meters(input_data, ovnsb_txn, &data->meter_groups); sync_dns_entries(input_data, ovnsb_txn, &data->datapaths); + sync_template_vars(input_data, ovnsb_txn); + cleanup_stale_fdb_entries(input_data, &data->datapaths); stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec()); diff --git a/northd/northd.h b/northd/northd.h index 677b35877..33dd210fd 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -30,6 +30,7 @@ struct northd_input { const struct nbrec_acl_table *nbrec_acl_table; const struct nbrec_static_mac_binding_table *nbrec_static_mac_binding_table; + const struct nbrec_template_var_table *nbrec_template_var_table; /* Southbound table references */ const struct sbrec_sb_global_table *sbrec_sb_global_table; @@ -56,6 +57,7 @@ struct northd_input { struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name; struct ovsdb_idl_index *sbrec_ip_mcast_by_dp; struct ovsdb_idl_index *sbrec_static_mac_binding_by_lport_ip; + struct ovsdb_idl_index *sbrec_template_var_by_name_chassis; }; struct chassis_features { diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema index 174364c8b..c38ed4f69 100644 --- a/ovn-nb.ovsschema +++ b/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "6.3.0", - "cksum": "4042813038 31869", + "version": "6.4.0", + "cksum": "337369157 32292", "tables": { "NB_Global": { "columns": { @@ -620,6 +620,16 @@ "mac": {"type": "string"}, "override_dynamic_mac": {"type": "boolean"}}, "indexes": [["logical_port", "ip"]], - "isRoot": true} + "isRoot": true}, + "Template_Var": { + "columns": { + "name": {"type": "string"}, + "value": {"type": "string"}, + "chassis": {"type": "string"}, + "external_ids": { + "type": {"key": "string", "value": "string", + "min": 0, "max": "unlimited"}}}, + "indexes": [["name", "chassis"]], + "isRoot": true} } } diff --git a/ovn-nb.xml b/ovn-nb.xml index e26afd83c..b9bfb59d4 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -4421,4 +4421,11 @@ + + + + + + +
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index 3b78ea6f6..94487a894 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "20.23.0", - "cksum": "4045988377 28575", + "version": "20.24.0", + "cksum": "2495293843 28838", "tables": { "SB_Global": { "columns": { @@ -560,6 +560,13 @@ "key": {"type": "uuid", "refTable": "Datapath_Binding"}}}}, "indexes": [["logical_port", "ip"]], + "isRoot": true}, + "Template_Var": { + "columns": { + "name": {"type": "string"}, + "value": {"type": "string"}, + "chassis": {"type": "string"}}, + "indexes": [["name", "chassis"]], "isRoot": true} } } diff --git a/ovn-sb.xml b/ovn-sb.xml index 59ad3aa2d..e991899bb 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -4739,4 +4739,10 @@ tcp.flags = RST; The logical datapath to which the logical router port belongs. + + + + + +
From patchwork Fri Aug 5 16:27:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1664130 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.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=FxfIq916; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Lzrbq6LtPz9sB4 for ; Sat, 6 Aug 2022 02:27:35 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 5956883E8C; Fri, 5 Aug 2022 16:27:34 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 5956883E8C Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=FxfIq916 X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yKoHh_1EXebh; Fri, 5 Aug 2022 16:27:32 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 9007183ECA; Fri, 5 Aug 2022 16:27:31 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 9007183ECA Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 58D4AC0032; Fri, 5 Aug 2022 16:27:31 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 46DC1C002D for ; Fri, 5 Aug 2022 16:27:29 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id AFA1940AA1 for ; Fri, 5 Aug 2022 16:27:25 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org AFA1940AA1 Authentication-Results: smtp2.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=FxfIq916 X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OOcZif45FkfS for ; Fri, 5 Aug 2022 16:27:23 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 8ECB341CDA Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp2.osuosl.org (Postfix) with ESMTPS id 8ECB341CDA for ; Fri, 5 Aug 2022 16:27:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1659716842; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XWiiOXZAmeD+gGLXD0prLjSOzcTv1Qmlbj0yMyZcrag=; b=FxfIq916QxPdied4E4yblva3wg3aH/qACv2ybqAQ5ME2s4GXJGxnlAZh0fX+ISnjbFtpVL kxY5uJdQZMW397gX4R95kHrc3CwX4gn8Z01JsLorWyID9FReYT3nDxtIcgLguk6FDg11b1 UPqvh51MbsN3Q5ocI9k7LkiIE8h2hK8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-586-1GnTh-yhO_CaZ3xFLQKLrw-1; Fri, 05 Aug 2022 12:27:21 -0400 X-MC-Unique: 1GnTh-yhO_CaZ3xFLQKLrw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 19BD585A584 for ; Fri, 5 Aug 2022 16:27:21 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.192.97]) by smtp.corp.redhat.com (Postfix) with ESMTP id EC5DF2166B2A; Fri, 5 Aug 2022 16:27:19 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Fri, 5 Aug 2022 18:27:17 +0200 Message-Id: <165971683444.246236.2794689442446640148.stgit@dceara.remote.csb> In-Reply-To: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> References: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: surya@redhat.com Subject: [ovs-dev] [RFC PATCH ovn 2/5] controller: Add support for templated actions and matches. 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" Expand SB.Template_Var records in two stages: 1. first expand them to local values in match/action strings 2. then reparse the expanded strings For the case when a lflow references a Template_Var also track references (similar to the ones maintained for multicast groups, address sets, port_groups, port bindings). Signed-off-by: Dumitru Ceara --- TODO: - reduce the number of xstrdups. - figure out a way to deal with templates in ovn-trace - determine if we need to allow Template_Var to match against chassis hostname or other IDs. - Make ofctrl_inject_pkt() work with template_vars. - Make test-ovn work with template_vars. --- controller/lflow.c | 66 ++++++++++-- controller/lflow.h | 4 + controller/ofctrl.c | 9 +- controller/ofctrl.h | 3 - controller/ovn-controller.c | 232 ++++++++++++++++++++++++++++++++++++++++++- include/ovn/expr.h | 4 + include/ovn/lex.h | 14 ++- lib/actions.c | 9 +- lib/expr.c | 14 ++- lib/lex.c | 55 ++++++++++ tests/ovn.at | 2 tests/test-ovn.c | 16 ++- utilities/ovn-trace.c | 26 ++++- 13 files changed, 417 insertions(+), 37 deletions(-) diff --git a/controller/lflow.c b/controller/lflow.c index 6055097b5..c1a30b2a4 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -80,6 +80,8 @@ convert_match_to_expr(const struct sbrec_logical_flow *, const struct local_datapath *ldp, struct expr **prereqs, const struct shash *addr_sets, const struct shash *port_groups, + const struct smap *template_vars, + struct sset *template_vars_ref, struct lflow_resource_ref *, bool *pg_addr_set_ref); static void add_matches_to_flow_table(const struct sbrec_logical_flow *, @@ -597,10 +599,15 @@ consider_lflow_for_added_as_ips__( .n_tables = LOG_PIPELINE_LEN, .cur_ltable = lflow->table_id, }; + struct sset template_vars_ref = SSET_INITIALIZER(&template_vars_ref); struct expr *prereqs = NULL; char *error; - error = ovnacts_parse_string(lflow->actions, &pp, &ovnacts, &prereqs); + char *actions_s = lexer_parse_template_string(xstrdup(lflow->actions), + l_ctx_in->template_vars, + &template_vars_ref); + error = ovnacts_parse_string(actions_s, &pp, &ovnacts, &prereqs); + free(actions_s); if (error) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_WARN_RL(&rl, "error parsing actions \"%s\": %s", @@ -608,6 +615,7 @@ consider_lflow_for_added_as_ips__( free(error); ovnacts_free(ovnacts.data, ovnacts.size); ofpbuf_uninit(&ovnacts); + sset_destroy(&template_vars_ref); return true; } @@ -671,6 +679,8 @@ consider_lflow_for_added_as_ips__( struct expr *expr = convert_match_to_expr(lflow, ldp, &prereqs, l_ctx_in->addr_sets, l_ctx_in->port_groups, + l_ctx_in->template_vars, + &template_vars_ref, l_ctx_out->lfrr, NULL); shash_replace((struct shash *)l_ctx_in->addr_sets, as_name, real_as); if (new_fake_as) { @@ -742,6 +752,14 @@ done: ofpbuf_uninit(&ovnacts); expr_destroy(expr); expr_matches_destroy(&matches); + + const char *tv_name; + SSET_FOR_EACH (tv_name, &template_vars_ref) { + lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_TEMPLATE, tv_name, + &lflow->header_.uuid, 0); + } + sset_destroy(&template_vars_ref); + return handled; } @@ -781,8 +799,8 @@ consider_lflow_for_added_as_ips( as_name, as_ref_count, as_diff_added, dhcp_opts, dhcpv6_opts, nd_ra_opts, - controller_event_opts, l_ctx_in, - l_ctx_out)) { + controller_event_opts, + l_ctx_in, l_ctx_out)) { return false; } } @@ -1256,6 +1274,8 @@ convert_match_to_expr(const struct sbrec_logical_flow *lflow, struct expr **prereqs, const struct shash *addr_sets, const struct shash *port_groups, + const struct smap *template_vars, + struct sset *template_vars_ref, struct lflow_resource_ref *lfrr, bool *pg_addr_set_ref) { @@ -1263,11 +1283,16 @@ convert_match_to_expr(const struct sbrec_logical_flow *lflow, struct sset port_groups_ref = SSET_INITIALIZER(&port_groups_ref); char *error = NULL; - struct expr *e = expr_parse_string(lflow->match, &symtab, addr_sets, + char *match_s = lexer_parse_template_string(xstrdup(lflow->match), + template_vars, + template_vars_ref); + struct expr *e = expr_parse_string(match_s, &symtab, addr_sets, port_groups, &addr_sets_ref, &port_groups_ref, ldp->datapath->tunnel_key, &error); + free(match_s); + struct shash_node *addr_sets_ref_node; SHASH_FOR_EACH (addr_sets_ref_node, &addr_sets_ref) { lflow_resource_add(lfrr, REF_TYPE_ADDRSET, addr_sets_ref_node->name, @@ -1374,7 +1399,12 @@ consider_logical_flow__(const struct sbrec_logical_flow *lflow, struct expr *prereqs = NULL; char *error; - error = ovnacts_parse_string(lflow->actions, &pp, &ovnacts, &prereqs); + struct sset template_vars_ref = SSET_INITIALIZER(&template_vars_ref); + char *actions_s = lexer_parse_template_string(xstrdup(lflow->actions), + l_ctx_in->template_vars, + &template_vars_ref); + error = ovnacts_parse_string(actions_s, &pp, &ovnacts, &prereqs); + free(actions_s); if (error) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_WARN_RL(&rl, "error parsing actions \"%s\": %s", @@ -1382,6 +1412,7 @@ consider_logical_flow__(const struct sbrec_logical_flow *lflow, free(error); ovnacts_free(ovnacts.data, ovnacts.size); ofpbuf_uninit(&ovnacts); + sset_destroy(&template_vars_ref); return; } @@ -1431,7 +1462,10 @@ consider_logical_flow__(const struct sbrec_logical_flow *lflow, switch (lcv_type) { case LCACHE_T_NONE: expr = convert_match_to_expr(lflow, ldp, &prereqs, l_ctx_in->addr_sets, - l_ctx_in->port_groups, l_ctx_out->lfrr, + l_ctx_in->port_groups, + l_ctx_in->template_vars, + &template_vars_ref, + l_ctx_out->lfrr, &pg_addr_set_ref); if (!expr) { goto done; @@ -1445,11 +1479,13 @@ consider_logical_flow__(const struct sbrec_logical_flow *lflow, } /* If caching is enabled and this is a not cached expr that doesn't refer - * to address sets or port groups, save it to potentially cache it later. + * to address sets, port groups, or template variables, save it to + * potentially cache it later. */ if (lcv_type == LCACHE_T_NONE && lflow_cache_is_enabled(l_ctx_out->lflow_cache) - && !pg_addr_set_ref) { + && !pg_addr_set_ref + && sset_is_empty(&template_vars_ref)) { cached_expr = expr_clone(expr); } @@ -1534,6 +1570,13 @@ done: expr_destroy(cached_expr); expr_matches_destroy(matches); free(matches); + + const char *tv_name; + SSET_FOR_EACH (tv_name, &template_vars_ref) { + lflow_resource_add(l_ctx_out->lfrr, REF_TYPE_TEMPLATE, tv_name, + &lflow->header_.uuid, 0); + } + sset_destroy(&template_vars_ref); } static struct lflow_processed_node * @@ -2331,8 +2374,7 @@ add_lb_ct_snat_hairpin_flows(struct ovn_controller_lb *lb, static void consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, - const struct hmap *local_datapaths, - bool use_ct_mark, + const struct hmap *local_datapaths, bool use_ct_mark, struct ovn_desired_flow_table *flow_table, struct simap *ids) { @@ -2408,8 +2450,8 @@ add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table, ovs_assert(id_pool_alloc_id(pool, &id)); simap_put(ids, lb->name, id); } - consider_lb_hairpin_flows(lb, local_datapaths, use_ct_mark, - flow_table, ids); + consider_lb_hairpin_flows(lb, local_datapaths, use_ct_mark, flow_table, + ids); } } diff --git a/controller/lflow.h b/controller/lflow.h index 342967917..d4480c2a2 100644 --- a/controller/lflow.h +++ b/controller/lflow.h @@ -84,7 +84,8 @@ enum ref_type { REF_TYPE_ADDRSET, REF_TYPE_PORTGROUP, REF_TYPE_PORTBINDING, - REF_TYPE_MC_GROUP + REF_TYPE_MC_GROUP, + REF_TYPE_TEMPLATE, }; struct ref_lflow_node { @@ -160,6 +161,7 @@ struct lflow_ctx_in { const struct sset *related_lport_ids; const struct shash *binding_lports; const struct hmap *chassis_tunnels; + const struct smap *template_vars; bool lb_hairpin_use_ct_mark; }; diff --git a/controller/ofctrl.c b/controller/ofctrl.c index 432fe2d37..8fd1638d7 100644 --- a/controller/ofctrl.c +++ b/controller/ofctrl.c @@ -2899,7 +2899,8 @@ ofctrl_lookup_port(const void *br_int_, const char *port_name, char * ofctrl_inject_pkt(const struct ovsrec_bridge *br_int, const char *flow_s, const struct shash *addr_sets, - const struct shash *port_groups) + const struct shash *port_groups, + const struct smap *template_vars) { int version = rconn_get_version(swconn); if (version < 0) { @@ -2907,9 +2908,13 @@ ofctrl_inject_pkt(const struct ovsrec_bridge *br_int, const char *flow_s, } struct flow uflow; - char *error = expr_parse_microflow(flow_s, &symtab, addr_sets, + char *flow_exp_s = lexer_parse_template_string(xstrdup(flow_s), + template_vars, + NULL); + char *error = expr_parse_microflow(flow_exp_s, &symtab, addr_sets, port_groups, ofctrl_lookup_port, br_int, &uflow); + free(flow_exp_s); if (error) { return error; } diff --git a/controller/ofctrl.h b/controller/ofctrl.h index 330b0b6ca..bd58bb07d 100644 --- a/controller/ofctrl.h +++ b/controller/ofctrl.h @@ -70,7 +70,8 @@ void ofctrl_ct_flush_zone(uint16_t zone_id); char *ofctrl_inject_pkt(const struct ovsrec_bridge *br_int, const char *flow_s, const struct shash *addr_sets, - const struct shash *port_groups); + const struct shash *port_groups, + const struct smap *template_vars); /* Flow table interfaces to the rest of ovn-controller. */ diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 5449743e8..1fe0efa2b 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -978,7 +978,8 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) SB_NODE(load_balancer, "load_balancer") \ SB_NODE(fdb, "fdb") \ SB_NODE(meter, "meter") \ - SB_NODE(static_mac_binding, "static_mac_binding") + SB_NODE(static_mac_binding, "static_mac_binding") \ + SB_NODE(template_var, "template_var") enum sb_engine_node { #define SB_NODE(NAME, NAME_STR) SB_##NAME, @@ -1537,6 +1538,167 @@ runtime_data_sb_datapath_binding_handler(struct engine_node *node OVS_UNUSED, return true; } +struct ed_type_template_vars { + struct smap local_vars; + + bool change_tracked; + struct sset new; + struct sset deleted; + struct sset updated; +}; + +static void +template_vars_init(const struct sbrec_template_var_table *template_var_table, + const struct sbrec_chassis *chassis, + struct smap *local_vars) +{ + const struct sbrec_template_var *tv; + SBREC_TEMPLATE_VAR_TABLE_FOR_EACH (tv, template_var_table) { + if (!strcmp(tv->chassis, chassis->name)) { + smap_add(local_vars, tv->name, tv->value); + } + } +} + +static void +template_vars_clear(struct smap *local_vars) +{ + smap_clear(local_vars); +} + +static void +template_vars_update(const struct sbrec_template_var_table *template_var_table, + const struct sbrec_chassis *chassis, + struct smap *local_vars, + struct sset *new, struct sset *deleted, + struct sset *updated) +{ + const struct sbrec_template_var *tv; + SBREC_TEMPLATE_VAR_TABLE_FOR_EACH_TRACKED (tv, template_var_table) { + if (strcmp(tv->chassis, chassis->name)) { + continue; + } + + if (sbrec_template_var_is_deleted(tv)) { + smap_remove(local_vars, tv->name); + sset_add(deleted, tv->name); + } + } + + SBREC_TEMPLATE_VAR_TABLE_FOR_EACH_TRACKED (tv, template_var_table) { + if (strcmp(tv->chassis, chassis->name)) { + continue; + } + + if (!sbrec_template_var_is_deleted(tv)) { + if (sbrec_template_var_is_new(tv)) { + sset_add(new, tv->name); + } else { + sset_add(updated, tv->name); + } + smap_replace(local_vars, tv->name, tv->value); + } + } +} + +static void * +en_template_vars_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct ed_type_template_vars *tv = xzalloc(sizeof *tv); + smap_init(&tv->local_vars); + tv->change_tracked = false; + sset_init(&tv->new); + sset_init(&tv->deleted); + sset_init(&tv->updated); + return tv; +} + +static void +en_template_vars_run(struct engine_node *node, void *data) +{ + struct ed_type_template_vars *tv = data; + + struct ovsrec_open_vswitch_table *ovs_table = + (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET( + engine_get_input("OVS_open_vswitch", node)); + + const char *chassis_id = get_ovs_chassis_id(ovs_table); + ovs_assert(chassis_id); + + const struct sbrec_chassis *chassis; + struct ovsdb_idl_index *sbrec_chassis_by_name = + engine_ovsdb_node_get_index( + engine_get_input("SB_chassis", node), + "name"); + chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id); + ovs_assert(chassis); + + template_vars_clear(&tv->local_vars); + + const struct sbrec_template_var_table *tv_table = + EN_OVSDB_GET(engine_get_input("SB_template_var", node)); + template_vars_init(tv_table, chassis, &tv->local_vars); + engine_set_node_state(node, EN_UPDATED); +} + +static bool +template_vars_sb_template_var_handler(struct engine_node *node, void *data) +{ + struct ed_type_template_vars *tv = data; + + struct ovsrec_open_vswitch_table *ovs_table = + (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET( + engine_get_input("OVS_open_vswitch", node)); + + const char *chassis_id = get_ovs_chassis_id(ovs_table); + ovs_assert(chassis_id); + + const struct sbrec_chassis *chassis; + struct ovsdb_idl_index *sbrec_chassis_by_name = + engine_ovsdb_node_get_index( + engine_get_input("SB_chassis", node), + "name"); + chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id); + ovs_assert(chassis); + + const struct sbrec_template_var_table *tv_table = + EN_OVSDB_GET(engine_get_input("SB_template_var", node)); + template_vars_update(tv_table, chassis, &tv->local_vars, + &tv->new, &tv->deleted, &tv->updated); + + if (!sset_is_empty(&tv->new) || !sset_is_empty(&tv->deleted) || + !sset_is_empty(&tv->updated)) { + engine_set_node_state(node, EN_UPDATED); + } else { + engine_set_node_state(node, EN_UNCHANGED); + } + + tv->change_tracked = true; + return true; +} + +static void +en_template_vars_clear_tracked_data(void *data) +{ + struct ed_type_template_vars *tv = data; + sset_clear(&tv->new); + sset_clear(&tv->deleted); + sset_clear(&tv->updated); + tv->change_tracked = false; +} + +static void +en_template_vars_cleanup(void *data) +{ + struct ed_type_template_vars *tv = data; + smap_destroy(&tv->local_vars); + + sset_destroy(&tv->new); + sset_destroy(&tv->deleted); + sset_destroy(&tv->updated); +} + struct ed_type_addr_sets { struct shash addr_sets; bool change_tracked; @@ -2540,6 +2702,9 @@ init_lflow_ctx(struct engine_node *node, struct ed_type_northd_options *n_opts = engine_get_input_data("northd_options", node); + struct ed_type_template_vars *template_vars = + engine_get_input_data("template_vars", node); + l_ctx_in->sbrec_multicast_group_by_name_datapath = sbrec_mc_group_by_name_dp; l_ctx_in->sbrec_logical_flow_by_logical_datapath = @@ -2570,6 +2735,7 @@ init_lflow_ctx(struct engine_node *node, l_ctx_in->binding_lports = &rt_data->lbinding_data.lports; l_ctx_in->chassis_tunnels = &non_vif_data->chassis_tunnels; l_ctx_in->lb_hairpin_use_ct_mark = n_opts->lb_hairpin_use_ct_mark; + l_ctx_in->template_vars = &template_vars->local_vars; l_ctx_out->flow_table = &fo->flow_table; l_ctx_out->group_table = &fo->group_table; @@ -2878,6 +3044,56 @@ lflow_output_port_groups_handler(struct engine_node *node, void *data) return true; } +static bool +lflow_output_template_vars_handler(struct engine_node *node, void *data) +{ + struct ed_type_template_vars *tv_data = + engine_get_input_data("template_vars", node); + + struct ed_type_lflow_output *fo = data; + + struct lflow_ctx_in l_ctx_in; + struct lflow_ctx_out l_ctx_out; + init_lflow_ctx(node, fo, &l_ctx_in, &l_ctx_out); + + bool changed; + const char *ref_name; + + if (!tv_data->change_tracked) { + return false; + } + + SSET_FOR_EACH (ref_name, &tv_data->deleted) { + if (!lflow_handle_changed_ref(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { + return false; + } + if (changed) { + engine_set_node_state(node, EN_UPDATED); + } + } + SSET_FOR_EACH (ref_name, &tv_data->updated) { + if (!lflow_handle_changed_ref(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { + return false; + } + if (changed) { + engine_set_node_state(node, EN_UPDATED); + } + } + SSET_FOR_EACH (ref_name, &tv_data->new) { + if (!lflow_handle_changed_ref(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { + return false; + } + if (changed) { + engine_set_node_state(node, EN_UPDATED); + } + } + + return true; +} + static bool lflow_output_runtime_data_handler(struct engine_node *node, void *data OVS_UNUSED) @@ -3534,6 +3750,7 @@ main(int argc, char *argv[]) stopwatch_create(VIF_PLUG_RUN_STOPWATCH_NAME, SW_MS); /* Define inc-proc-engine nodes. */ + ENGINE_NODE_WITH_CLEAR_TRACK_DATA(template_vars, "template_vars"); ENGINE_NODE_WITH_CLEAR_TRACK_DATA_IS_VALID(ct_zones, "ct_zones"); ENGINE_NODE_WITH_CLEAR_TRACK_DATA(ovs_interface_shadow, "ovs_interface_shadow"); @@ -3558,6 +3775,10 @@ main(int argc, char *argv[]) #undef OVS_NODE /* Add dependencies between inc-proc-engine nodes. */ + engine_add_input(&en_template_vars, &en_ovs_open_vswitch, NULL); + engine_add_input(&en_template_vars, &en_sb_chassis, NULL); + engine_add_input(&en_template_vars, &en_sb_template_var, + template_vars_sb_template_var_handler); engine_add_input(&en_addr_sets, &en_sb_address_set, addr_sets_sb_address_set_handler); @@ -3621,6 +3842,8 @@ main(int argc, char *argv[]) lflow_output_addr_sets_handler); engine_add_input(&en_lflow_output, &en_port_groups, lflow_output_port_groups_handler); + engine_add_input(&en_lflow_output, &en_template_vars, + lflow_output_template_vars_handler); engine_add_input(&en_lflow_output, &en_runtime_data, lflow_output_runtime_data_handler); engine_add_input(&en_lflow_output, &en_non_vif_data, @@ -4166,9 +4389,12 @@ main(int argc, char *argv[]) engine_get_data(&en_addr_sets); struct ed_type_port_groups *pg_data = engine_get_data(&en_port_groups); - if (br_int && chassis && as_data && pg_data) { + struct ed_type_template_vars *tv_data = + engine_get_data(&en_template_vars); + if (br_int && chassis && as_data && pg_data && tv_data) { char *error = ofctrl_inject_pkt(br_int, pending_pkt.flow_s, - &as_data->addr_sets, &pg_data->port_groups_cs_local); + &as_data->addr_sets, &pg_data->port_groups_cs_local, + &tv_data->local_vars); if (error) { unixctl_command_reply_error(pending_pkt.conn, error); free(error); diff --git a/include/ovn/expr.h b/include/ovn/expr.h index 3b141b034..80d95ff67 100644 --- a/include/ovn/expr.h +++ b/include/ovn/expr.h @@ -59,6 +59,7 @@ #include "openvswitch/match.h" #include "openvswitch/meta-flow.h" #include "logical-fields.h" +#include "smap.h" struct ds; struct expr; @@ -521,7 +522,8 @@ union expr_constant { char *string; }; -bool expr_constant_parse(struct lexer *, const struct expr_field *, +bool expr_constant_parse(struct lexer *, + const struct expr_field *, union expr_constant *); void expr_constant_format(const union expr_constant *, enum expr_constant_type, struct ds *); diff --git a/include/ovn/lex.h b/include/ovn/lex.h index ecb7ace24..38c4aa9f3 100644 --- a/include/ovn/lex.h +++ b/include/ovn/lex.h @@ -23,6 +23,8 @@ * This is a simple lexical analyzer (or tokenizer) for OVN match expressions * and ACLs. */ +#include "smap.h" +#include "sset.h" #include "openvswitch/meta-flow.h" struct ds; @@ -37,7 +39,8 @@ enum lex_type { LEX_T_INTEGER, /* 12345 or 1.2.3.4 or ::1 or 01:02:03:04:05 */ LEX_T_MASKED_INTEGER, /* 12345/10 or 1.2.0.0/16 or ::2/127 or... */ LEX_T_MACRO, /* $NAME */ - LEX_T_PORT_GROUP, /* @NAME */ + LEX_T_PORT_GROUP, /* @NAME */ + LEX_T_TEMPLATE, /* ^NAME */ LEX_T_ERROR, /* invalid input */ /* Bare tokens. */ @@ -86,9 +89,9 @@ struct lex_token { /* One of LEX_*. */ enum lex_type type; - /* Meaningful for LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO only. - * For these token types, 's' may point to 'buffer'; otherwise, it points - * to malloc()ed memory owned by the token. + /* Meaningful for LEX_T_ID, LEX_T_STRING, LEX_T_ERROR, LEX_T_MACRO, + * LEX_T_TEMPLATE only. For these token types, 's' may point to 'buffer'; + * otherwise, it points to malloc()ed memory owned by the token. * * Must be NULL for other token types. * @@ -151,4 +154,7 @@ void lexer_syntax_error(struct lexer *, const char *message, ...) char *lexer_steal_error(struct lexer *); +char *lexer_parse_template_string(char *s, const struct smap *template_vars, + struct sset *template_vars_ref); + #endif /* ovn/lex.h */ diff --git a/lib/actions.c b/lib/actions.c index aab044306..032ba0965 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -257,8 +257,8 @@ add_prerequisite(struct action_context *ctx, const char *prerequisite) struct expr *expr; char *error; - expr = expr_parse_string(prerequisite, ctx->pp->symtab, NULL, NULL, - NULL, NULL, 0, &error); + expr = expr_parse_string(prerequisite, ctx->pp->symtab, NULL, NULL, NULL, + NULL, 0, &error); ovs_assert(!error); ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr); } @@ -4365,6 +4365,11 @@ parse_set_action(struct action_context *ctx) static bool parse_action(struct action_context *ctx) { + if (ctx->lexer->token.type == LEX_T_TEMPLATE) { + lexer_error(ctx->lexer, "Unexpanded template."); + return false; + } + if (ctx->lexer->token.type != LEX_T_ID) { lexer_syntax_error(ctx->lexer, NULL); return false; diff --git a/lib/expr.c b/lib/expr.c index d1f9d28ca..1311b09fe 100644 --- a/lib/expr.c +++ b/lib/expr.c @@ -894,7 +894,10 @@ parse_constant(struct expr_context *ctx, struct expr_constant_set *cs, cs->as_name = NULL; } - if (ctx->lexer->token.type == LEX_T_STRING) { + if (ctx->lexer->token.type == LEX_T_TEMPLATE) { + lexer_error(ctx->lexer, "Unexpanded template."); + return false; + } else if (ctx->lexer->token.type == LEX_T_STRING) { if (!assign_constant_set_type(ctx, cs, EXPR_C_STRING)) { return false; } @@ -978,7 +981,9 @@ expr_constant_parse(struct lexer *lexer, const struct expr_field *f, return false; } - struct expr_context ctx = { .lexer = lexer }; + struct expr_context ctx = { + .lexer = lexer, + }; struct expr_constant_set cs; memset(&cs, 0, sizeof cs); @@ -1332,7 +1337,10 @@ expr_parse_primary(struct expr_context *ctx, bool *atomic) return e; } - if (ctx->lexer->token.type == LEX_T_ID) { + if (ctx->lexer->token.type == LEX_T_TEMPLATE) { + lexer_error(ctx->lexer, "Unexpanded template."); + return NULL; + } else if (ctx->lexer->token.type == LEX_T_ID) { struct expr_field f; enum expr_relop r; struct expr_constant_set c; diff --git a/lib/lex.c b/lib/lex.c index c84d52aa8..b01a7d75c 100644 --- a/lib/lex.c +++ b/lib/lex.c @@ -235,6 +235,10 @@ lex_token_format(const struct lex_token *token, struct ds *s) ds_put_format(s, "@%s", token->s); break; + case LEX_T_TEMPLATE: + ds_put_format(s, "^%s", token->s); + break; + case LEX_T_LPAREN: ds_put_cstr(s, "("); break; @@ -588,6 +592,18 @@ lex_parse_port_group(const char *p, struct lex_token *token) return lex_parse_id(p, LEX_T_PORT_GROUP, token); } +static const char * +lex_parse_template(const char *p, struct lex_token *token) +{ + p++; + if (!lex_is_id1(*p)) { + lex_error(token, "`^' must be followed by a valid identifier."); + return p; + } + + return lex_parse_id(p, LEX_T_TEMPLATE, token); +} + /* Initializes 'token' and parses the first token from the beginning of * null-terminated string 'p' into 'token'. Stores a pointer to the start of * the token (after skipping white space and comments, if any) into '*startp'. @@ -766,6 +782,10 @@ next: p = lex_parse_port_group(p, token); break; + case '^': + p = lex_parse_template(p, token); + break; + case ':': if (p[1] != ':') { token->type = LEX_T_COLON; @@ -1031,3 +1051,38 @@ lexer_steal_error(struct lexer *lexer) lexer->error = NULL; return error; } + +/* Takes ownership of 's' and expands all templates that are encountered + * in the contents of 's', if possible. Adds the encountered template names + * to 'template_vars_ref'. + */ +char * +lexer_parse_template_string(char *s, const struct smap *template_vars, + struct sset *template_vars_ref) +{ + /* No '^' means no templates. */ + if (!strchr(s, '^')) { + return s; + } + + struct ds expanded = DS_EMPTY_INITIALIZER; + + struct lexer lexer; + lexer_init(&lexer, s); + + while (lexer_get(&lexer) != LEX_T_END) { + if (lexer.token.type == LEX_T_TEMPLATE) { + ds_put_cstr(&expanded, smap_get_def(template_vars, lexer.token.s, + lexer.token.s)); + if (template_vars_ref) { + sset_add(template_vars_ref, lexer.token.s); + } + } else { + lex_token_format(&lexer.token, &expanded); + } + } + + lexer_destroy(&lexer); + free(s); + return ds_steal_cstr(&expanded); +} \ No newline at end of file diff --git a/tests/ovn.at b/tests/ovn.at index 3ba6ced4e..1bf5da6d5 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -226,7 +226,7 @@ fe:x => error("Invalid numeric constant.") & => error("`&' is only valid as part of `&&'.") | => error("`|' is only valid as part of `||'.") -^ => error("Invalid character `^' in input.") +^ => error("`^' must be followed by a valid identifier.") ]) AT_CAPTURE_FILE([input.txt]) sed 's/ =>.*//' test-cases.txt > input.txt diff --git a/tests/test-ovn.c b/tests/test-ovn.c index a241f150d..7842cd915 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -291,12 +291,14 @@ test_parse_expr__(int steps) struct shash symtab; struct shash addr_sets; struct shash port_groups; + struct smap template_vars; struct simap ports; struct ds input; create_symtab(&symtab); create_addr_sets(&addr_sets); create_port_groups(&port_groups); + smap_init(&template_vars); simap_init(&ports); simap_put(&ports, "eth0", 5); @@ -355,6 +357,7 @@ test_parse_expr__(int steps) shash_destroy(&addr_sets); expr_const_sets_destroy(&port_groups); shash_destroy(&port_groups); + smap_destroy(&template_vars); } static void @@ -913,8 +916,8 @@ test_tree_shape_exhaustively(struct expr *expr, struct shash *symtab, expr_format(expr, &s); char *error; - modified = expr_parse_string(ds_cstr(&s), symtab, NULL, - NULL, NULL, NULL, 0, &error); + modified = expr_parse_string(ds_cstr(&s), symtab, NULL, NULL, NULL, + NULL, 0, &error); if (error) { fprintf(stderr, "%s fails to parse (%s)\n", ds_cstr(&s), error); @@ -1286,6 +1289,8 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) struct ds input; bool ok = true; + struct smap template_vars = SMAP_INITIALIZER(&template_vars); + create_symtab(&symtab); create_gen_opts(&dhcp_opts, &dhcpv6_opts, &nd_ra_opts, &event_opts); @@ -1322,7 +1327,10 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) .n_tables = 24, .cur_ltable = 10, }; - error = ovnacts_parse_string(ds_cstr(&input), &pp, &ovnacts, &prereqs); + char *exp_input = lexer_parse_template_string(xstrdup(ds_cstr(&input)), + &template_vars, + NULL); + error = ovnacts_parse_string(exp_input, &pp, &ovnacts, &prereqs); if (!error) { /* Convert the parsed representation back to a string and print it, * if it's different from the input. */ @@ -1409,6 +1417,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) expr_destroy(prereqs); ovnacts_free(ovnacts.data, ovnacts.size); ofpbuf_uninit(&ovnacts); + free(exp_input); } ds_destroy(&input); @@ -1419,6 +1428,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) dhcp_opts_destroy(&dhcpv6_opts); nd_ra_opts_destroy(&nd_ra_opts); controller_event_opts_destroy(&event_opts); + smap_destroy(&template_vars); ovn_extend_table_destroy(&group_table); ovn_extend_table_destroy(&meter_table); exit(ok ? EXIT_SUCCESS : EXIT_FAILURE); diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index baf489202..c8836d313 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -505,6 +505,7 @@ static struct hmap dhcp_opts; /* Contains "struct gen_opts_map"s. */ static struct hmap dhcpv6_opts; /* Contains "struct gen_opts_map"s. */ static struct hmap nd_ra_opts; /* Contains "struct gen_opts_map"s. */ static struct controller_event_options event_opts; +static struct smap template_vars; static struct ovntrace_datapath * ovntrace_datapath_find_by_sb_uuid(const struct uuid *sb_uuid) @@ -955,9 +956,13 @@ parse_lflow_for_datapath(const struct sbrec_logical_flow *sblf, char *error; struct expr *match; - match = expr_parse_string(sblf->match, &symtab, &address_sets, + char *match_s = lexer_parse_template_string(xstrdup(sblf->match), + &template_vars, + NULL); + match = expr_parse_string(match_s, &symtab, &address_sets, &port_groups, NULL, NULL, dp->tunnel_key, &error); + free(match_s); if (error) { VLOG_WARN("%s: parsing expression failed (%s)", sblf->match, error); @@ -980,7 +985,11 @@ parse_lflow_for_datapath(const struct sbrec_logical_flow *sblf, uint64_t stub[1024 / 8]; struct ofpbuf ovnacts = OFPBUF_STUB_INITIALIZER(stub); struct expr *prereqs; - error = ovnacts_parse_string(sblf->actions, &pp, &ovnacts, &prereqs); + char *actions_s = lexer_parse_template_string(xstrdup(sblf->actions), + &template_vars, + NULL); + error = ovnacts_parse_string(actions_s, &pp, &ovnacts, &prereqs); + free(actions_s); if (error) { VLOG_WARN("%s: parsing actions failed (%s)", sblf->actions, error); free(error); @@ -1078,6 +1087,7 @@ read_gen_opts(void) nd_ra_opts_init(&nd_ra_opts); controller_event_opts_init(&event_opts); + smap_init(&template_vars); } static void @@ -3422,9 +3432,13 @@ trace_parse(const char *dp_s, const char *flow_s, * * First make sure that the expression parses. */ char *error; - struct expr *e = expr_parse_string(flow_s, &symtab, &address_sets, + char *flow_exp_s = lexer_parse_template_string(xstrdup(flow_s), + &template_vars, + NULL); + struct expr *e = expr_parse_string(flow_exp_s, &symtab, &address_sets, &port_groups, NULL, NULL, 0, &error); + free(flow_exp_s); if (!e) { return trace_parse_error(error); } @@ -3449,9 +3463,13 @@ trace_parse(const char *dp_s, const char *flow_s, free(port_name); } - char *error = expr_parse_microflow(flow_s, &symtab, &address_sets, + char *flow_exp_s = lexer_parse_template_string(xstrdup(flow_s), + &template_vars, + NULL); + char *error = expr_parse_microflow(flow_exp_s, &symtab, &address_sets, &port_groups, ovntrace_lookup_port, *dpp, uflow); + free(flow_exp_s); if (error) { return trace_parse_error(error); } From patchwork Fri Aug 5 16:27:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1664131 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.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=VlrSAp1b; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Lzrc604kvz9sB4 for ; Sat, 6 Aug 2022 02:27:49 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id DE1D040AA4; Fri, 5 Aug 2022 16:27:47 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org DE1D040AA4 Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=VlrSAp1b X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7PCS--kEBSur; Fri, 5 Aug 2022 16:27:46 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id 4876A40B15; Fri, 5 Aug 2022 16:27:45 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 4876A40B15 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id EBD4CC0032; Fri, 5 Aug 2022 16:27:44 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 16023C002D for ; Fri, 5 Aug 2022 16:27:43 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 61BE26F992 for ; Fri, 5 Aug 2022 16:27:37 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 61BE26F992 Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=VlrSAp1b X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4kMp4-r__6GL for ; Fri, 5 Aug 2022 16:27:35 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org B011E6F98A Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id B011E6F98A for ; Fri, 5 Aug 2022 16:27:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1659716853; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3X0KQaNqFZvQCPf0deZe9kfglxVqBnJa2cMyH78foQI=; b=VlrSAp1br1ZXauk3Q/ZboTn0ovlXpblfT9s9GLaoo0WGljxkf+f5n9aWy32OPbHADSVSf2 vAGlk0yQ/G9NdXGcs9wEMhsfJOxeY5ziyMVh7z+F8Ww4KMvWCCHG6kAJxGYQp4kl57ABQD PBaTYgUGbBMzqhkmOyZFu8/r3Wo3lT8= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-619-QyF5Ecd_PY2kZfT2q3fikw-1; Fri, 05 Aug 2022 12:27:32 -0400 X-MC-Unique: QyF5Ecd_PY2kZfT2q3fikw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 39348101A54E for ; Fri, 5 Aug 2022 16:27:32 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.192.97]) by smtp.corp.redhat.com (Postfix) with ESMTP id 705ED1415122; Fri, 5 Aug 2022 16:27:31 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Fri, 5 Aug 2022 18:27:28 +0200 Message-Id: <165971684632.246236.5126286132315139482.stgit@dceara.remote.csb> In-Reply-To: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> References: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: surya@redhat.com Subject: [ovs-dev] [RFC PATCH ovn 3/5] controller: Make resource references more generic. 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" Signed-off-by: Dumitru Ceara --- TODO: - Rename resource references to make it clear that they're not only about lflows. --- controller/lflow.c | 108 +++++++++++++++++++++++++++---------------- controller/lflow.h | 95 ++++++++++++++++++++------------------ controller/ovn-controller.c | 36 +++++++------- 3 files changed, 134 insertions(+), 105 deletions(-) diff --git a/controller/lflow.c b/controller/lflow.c index c1a30b2a4..6e60728f0 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -989,43 +989,12 @@ done: return ret; } -bool +static void lflow_handle_changed_ref(enum ref_type ref_type, const char *ref_name, struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out, - bool *changed) + struct ovs_list *lflows_todo) { - struct ref_lflow_node *rlfn = - ref_lflow_lookup(&l_ctx_out->lfrr->ref_lflow_table, ref_type, - ref_name); - if (!rlfn) { - *changed = false; - return true; - } - VLOG_DBG("Handle changed lflow reference for resource type: %d," - " name: %s.", ref_type, ref_name); - *changed = false; - bool ret = true; - - struct ovs_list lflows_todo = OVS_LIST_INITIALIZER(&lflows_todo); - - struct lflow_ref_list_node *lrln, *lrln_uuid; - HMAP_FOR_EACH (lrln, hmap_node, &rlfn->lflow_uuids) { - if (lflows_processed_find(l_ctx_out->lflows_processed, - &lrln->lflow_uuid)) { - continue; - } - /* Use lflow_ref_list_node as list node to store the uuid. - * Other fields are not used here. */ - lrln_uuid = xmalloc(sizeof *lrln_uuid); - lrln_uuid->lflow_uuid = lrln->lflow_uuid; - ovs_list_push_back(&lflows_todo, &lrln_uuid->list_node); - } - if (ovs_list_is_empty(&lflows_todo)) { - return true; - } - *changed = true; - struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts); struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts); const struct sbrec_dhcp_options *dhcp_opt_row; @@ -1050,8 +1019,9 @@ lflow_handle_changed_ref(enum ref_type ref_type, const char *ref_name, /* Re-parse the related lflows. */ /* Firstly, flood remove the flows from desired flow table. */ + struct lflow_ref_list_node *lrln_uuid; struct hmap flood_remove_nodes = HMAP_INITIALIZER(&flood_remove_nodes); - LIST_FOR_EACH_SAFE (lrln_uuid, list_node, &lflows_todo) { + LIST_FOR_EACH_SAFE (lrln_uuid, list_node, lflows_todo) { VLOG_DBG("Reprocess lflow "UUID_FMT" for resource type: %d," " name: %s.", UUID_ARGS(&lrln_uuid->lflow_uuid), @@ -1104,7 +1074,6 @@ lflow_handle_changed_ref(enum ref_type ref_type, const char *ref_name, dhcp_opts_destroy(&dhcpv6_opts); nd_ra_opts_destroy(&nd_ra_opts); controller_event_opts_destroy(&controller_event_opts); - return ret; } static void @@ -2769,8 +2738,8 @@ lflow_handle_flows_for_lport(const struct sbrec_port_binding *pb, { bool changed; - if (!lflow_handle_changed_ref(REF_TYPE_PORTBINDING, pb->logical_port, - l_ctx_in, l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_PORTBINDING, pb->logical_port, + l_ctx_in, l_ctx_out, &changed)) { return false; } @@ -2804,8 +2773,8 @@ lflow_handle_changed_port_bindings(struct lflow_ctx_in *l_ctx_in, && !sbrec_port_binding_is_deleted(pb)) { continue; } - if (!lflow_handle_changed_ref(REF_TYPE_PORTBINDING, pb->logical_port, - l_ctx_in, l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_PORTBINDING, pb->logical_port, + l_ctx_in, l_ctx_out, &changed)) { ret = false; break; } @@ -2828,8 +2797,8 @@ lflow_handle_changed_mc_groups(struct lflow_ctx_in *l_ctx_in, && !sbrec_multicast_group_is_deleted(mg)) { continue; } - if (!lflow_handle_changed_ref(REF_TYPE_MC_GROUP, ds_cstr(&mg_key), - l_ctx_in, l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_MC_GROUP, ds_cstr(&mg_key), + l_ctx_in, l_ctx_out, &changed)) { ret = false; break; } @@ -3699,3 +3668,60 @@ consider_port_sec_flows(const struct sbrec_port_binding *pb, } free(ps_addrs); } + +/* Allow potentially different reference change handlers per type. */ +typedef void (*ref_change_handler)(enum ref_type ref_type, + const char *ref_name, + struct lflow_ctx_in *l_ctx_in, + struct lflow_ctx_out *l_ctx_out, + struct ovs_list *ref_nodes); + +static ref_change_handler ref_change_handlers[REF_TYPE_MAX] = { + [REF_TYPE_ADDRSET] = lflow_handle_changed_ref, + [REF_TYPE_PORTGROUP] = lflow_handle_changed_ref, + [REF_TYPE_PORTBINDING] = lflow_handle_changed_ref, + [REF_TYPE_MC_GROUP] = lflow_handle_changed_ref, + [REF_TYPE_TEMPLATE] = lflow_handle_changed_ref, +}; + +bool +ref_change_handle(enum ref_type ref_type, const char *ref_name, + struct lflow_ctx_in *l_ctx_in, + struct lflow_ctx_out *l_ctx_out, + bool *changed) +{ + struct ref_lflow_node *rlfn = + ref_lflow_lookup(&l_ctx_out->lfrr->ref_lflow_table, ref_type, + ref_name); + if (!rlfn) { + *changed = false; + return true; + } + VLOG_DBG("Handle changed lflow reference for resource type: %d," + " name: %s.", ref_type, ref_name); + *changed = false; + + struct ovs_list lflows_todo = OVS_LIST_INITIALIZER(&lflows_todo); + + struct lflow_ref_list_node *lrln, *lrln_uuid; + HMAP_FOR_EACH (lrln, hmap_node, &rlfn->lflow_uuids) { + if (lflows_processed_find(l_ctx_out->lflows_processed, + &lrln->lflow_uuid)) { + continue; + } + /* Use lflow_ref_list_node as list node to store the uuid. + * Other fields are not used here. */ + lrln_uuid = xmalloc(sizeof *lrln_uuid); + lrln_uuid->lflow_uuid = lrln->lflow_uuid; + ovs_list_push_back(&lflows_todo, &lrln_uuid->list_node); + } + if (ovs_list_is_empty(&lflows_todo)) { + return true; + } + *changed = true; + + /* This takes ownership of lflows_todo. */ + ref_change_handlers[ref_type](ref_type, ref_name, l_ctx_in, l_ctx_out, + &lflows_todo); + return true; +} diff --git a/controller/lflow.h b/controller/lflow.h index d4480c2a2..21e682017 100644 --- a/controller/lflow.h +++ b/controller/lflow.h @@ -80,14 +80,63 @@ struct uuid; #define OFTABLE_CHK_IN_PORT_SEC_ND 74 #define OFTABLE_CHK_OUT_PORT_SEC 75 +struct lflow_ctx_in { + struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath; + struct ovsdb_idl_index *sbrec_logical_flow_by_logical_datapath; + struct ovsdb_idl_index *sbrec_logical_flow_by_logical_dp_group; + struct ovsdb_idl_index *sbrec_port_binding_by_name; + struct ovsdb_idl_index *sbrec_fdb_by_dp_key; + struct ovsdb_idl_index *sbrec_mac_binding_by_datapath; + struct ovsdb_idl_index *sbrec_static_mac_binding_by_datapath; + const struct sbrec_port_binding_table *port_binding_table; + const struct sbrec_dhcp_options_table *dhcp_options_table; + const struct sbrec_dhcpv6_options_table *dhcpv6_options_table; + const struct sbrec_datapath_binding_table *dp_binding_table; + const struct sbrec_mac_binding_table *mac_binding_table; + const struct sbrec_logical_flow_table *logical_flow_table; + const struct sbrec_logical_dp_group_table *logical_dp_group_table; + const struct sbrec_multicast_group_table *mc_group_table; + const struct sbrec_fdb_table *fdb_table; + const struct sbrec_chassis *chassis; + const struct sbrec_load_balancer_table *lb_table; + const struct sbrec_static_mac_binding_table *static_mac_binding_table; + const struct hmap *local_datapaths; + const struct shash *addr_sets; + const struct shash *port_groups; + const struct sset *active_tunnels; + const struct sset *related_lport_ids; + const struct shash *binding_lports; + const struct hmap *chassis_tunnels; + const struct smap *template_vars; + bool lb_hairpin_use_ct_mark; +}; + +struct lflow_ctx_out { + struct ovn_desired_flow_table *flow_table; + struct ovn_extend_table *group_table; + struct ovn_extend_table *meter_table; + struct lflow_resource_ref *lfrr; + struct lflow_cache *lflow_cache; + struct conj_ids *conj_ids; + struct hmap *lflows_processed; + struct simap *hairpin_lb_ids; + struct id_pool *hairpin_id_pool; +}; + enum ref_type { REF_TYPE_ADDRSET, REF_TYPE_PORTGROUP, REF_TYPE_PORTBINDING, REF_TYPE_MC_GROUP, REF_TYPE_TEMPLATE, + REF_TYPE_MAX, }; +bool ref_change_handle(enum ref_type ref_type, const char *ref_name, + struct lflow_ctx_in *l_ctx_in, + struct lflow_ctx_out *l_ctx_out, + bool *changed); + struct ref_lflow_node { struct hmap_node node; /* node in lflow_resource_ref.ref_lflow_table. */ enum ref_type type; /* key */ @@ -134,49 +183,6 @@ void lflow_resource_init(struct lflow_resource_ref *); void lflow_resource_destroy(struct lflow_resource_ref *); void lflow_resource_clear(struct lflow_resource_ref *); -struct lflow_ctx_in { - struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath; - struct ovsdb_idl_index *sbrec_logical_flow_by_logical_datapath; - struct ovsdb_idl_index *sbrec_logical_flow_by_logical_dp_group; - struct ovsdb_idl_index *sbrec_port_binding_by_name; - struct ovsdb_idl_index *sbrec_fdb_by_dp_key; - struct ovsdb_idl_index *sbrec_mac_binding_by_datapath; - struct ovsdb_idl_index *sbrec_static_mac_binding_by_datapath; - const struct sbrec_port_binding_table *port_binding_table; - const struct sbrec_dhcp_options_table *dhcp_options_table; - const struct sbrec_dhcpv6_options_table *dhcpv6_options_table; - const struct sbrec_datapath_binding_table *dp_binding_table; - const struct sbrec_mac_binding_table *mac_binding_table; - const struct sbrec_logical_flow_table *logical_flow_table; - const struct sbrec_logical_dp_group_table *logical_dp_group_table; - const struct sbrec_multicast_group_table *mc_group_table; - const struct sbrec_fdb_table *fdb_table; - const struct sbrec_chassis *chassis; - const struct sbrec_load_balancer_table *lb_table; - const struct sbrec_static_mac_binding_table *static_mac_binding_table; - const struct hmap *local_datapaths; - const struct shash *addr_sets; - const struct shash *port_groups; - const struct sset *active_tunnels; - const struct sset *related_lport_ids; - const struct shash *binding_lports; - const struct hmap *chassis_tunnels; - const struct smap *template_vars; - bool lb_hairpin_use_ct_mark; -}; - -struct lflow_ctx_out { - struct ovn_desired_flow_table *flow_table; - struct ovn_extend_table *group_table; - struct ovn_extend_table *meter_table; - struct lflow_resource_ref *lfrr; - struct lflow_cache *lflow_cache; - struct conj_ids *conj_ids; - struct hmap *lflows_processed; - struct simap *hairpin_lb_ids; - struct id_pool *hairpin_id_pool; -}; - struct lflow_processed_node { struct hmap_node hmap_node; /* In ed_type_lflow_output.lflows_processed. */ struct uuid lflow_uuid; @@ -188,9 +194,6 @@ void lflow_run(struct lflow_ctx_in *, struct lflow_ctx_out *); void lflow_handle_cached_flows(struct lflow_cache *, const struct sbrec_logical_flow_table *); bool lflow_handle_changed_flows(struct lflow_ctx_in *, struct lflow_ctx_out *); -bool lflow_handle_changed_ref(enum ref_type, const char *ref_name, - struct lflow_ctx_in *, struct lflow_ctx_out *, - bool *changed); struct addr_set_diff { struct expr_constant_set *added; diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 1fe0efa2b..207ea4e51 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -2957,8 +2957,8 @@ lflow_output_addr_sets_handler(struct engine_node *node, void *data) } SSET_FOR_EACH (ref_name, &as_data->deleted) { - if (!lflow_handle_changed_ref(REF_TYPE_ADDRSET, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_ADDRSET, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { @@ -2972,8 +2972,8 @@ lflow_output_addr_sets_handler(struct engine_node *node, void *data) &l_ctx_out, &changed)) { VLOG_DBG("Can't incrementally handle the change of address set %s." " Reprocess related lflows.", shash_node->name); - if (!lflow_handle_changed_ref(REF_TYPE_ADDRSET, shash_node->name, - &l_ctx_in, &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_ADDRSET, shash_node->name, + &l_ctx_in, &l_ctx_out, &changed)) { return false; } } @@ -2982,8 +2982,8 @@ lflow_output_addr_sets_handler(struct engine_node *node, void *data) } } SSET_FOR_EACH (ref_name, &as_data->new) { - if (!lflow_handle_changed_ref(REF_TYPE_ADDRSET, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_ADDRSET, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { @@ -3014,8 +3014,8 @@ lflow_output_port_groups_handler(struct engine_node *node, void *data) } SSET_FOR_EACH (ref_name, &pg_data->deleted) { - if (!lflow_handle_changed_ref(REF_TYPE_PORTGROUP, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_PORTGROUP, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { @@ -3023,8 +3023,8 @@ lflow_output_port_groups_handler(struct engine_node *node, void *data) } } SSET_FOR_EACH (ref_name, &pg_data->updated) { - if (!lflow_handle_changed_ref(REF_TYPE_PORTGROUP, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_PORTGROUP, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { @@ -3032,8 +3032,8 @@ lflow_output_port_groups_handler(struct engine_node *node, void *data) } } SSET_FOR_EACH (ref_name, &pg_data->new) { - if (!lflow_handle_changed_ref(REF_TYPE_PORTGROUP, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_PORTGROUP, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { @@ -3064,8 +3064,8 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) } SSET_FOR_EACH (ref_name, &tv_data->deleted) { - if (!lflow_handle_changed_ref(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { @@ -3073,8 +3073,8 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) } } SSET_FOR_EACH (ref_name, &tv_data->updated) { - if (!lflow_handle_changed_ref(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { @@ -3082,8 +3082,8 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) } } SSET_FOR_EACH (ref_name, &tv_data->new) { - if (!lflow_handle_changed_ref(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, - &l_ctx_out, &changed)) { + if (!ref_change_handle(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { return false; } if (changed) { From patchwork Fri Aug 5 16:27:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1664132 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.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=WZUuWR+K; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4LzrcV75jCz9sB4 for ; Sat, 6 Aug 2022 02:28:10 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id C760E41D20; Fri, 5 Aug 2022 16:28:08 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org C760E41D20 Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WZUuWR+K X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id NnWQ-SkAyLUr; Fri, 5 Aug 2022 16:28:05 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id B016941CFB; Fri, 5 Aug 2022 16:28:02 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org B016941CFB Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 6DFF0C0032; Fri, 5 Aug 2022 16:28:02 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3147DC002D for ; Fri, 5 Aug 2022 16:28:01 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 810B141E15 for ; Fri, 5 Aug 2022 16:27:47 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 810B141E15 Authentication-Results: smtp4.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=WZUuWR+K X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id E8M31l_gNNYT for ; Fri, 5 Aug 2022 16:27:45 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 84CAC41E03 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 84CAC41E03 for ; Fri, 5 Aug 2022 16:27:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1659716864; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=frYLuQQXhzvsIub6e1L074j4M/VuBnn5QXDDJb2LEUU=; b=WZUuWR+KH27XwsmKSi9e+8YsfgwfmKn8TVd/s1VZRh4RdsQJCn0+Bc0erqDC8xVGmm7bFh J/gV7ElTpCoWyM2pFGKv+XRtLO8ddsVFqGlTAbygeWyTerNjWom+nv7rhpa2P4WdB2+jOI jwrwpJz36+vFf/2shgZshdVd57bsvlg= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-590-Pk1rt4vvMui4fAntXRucgA-1; Fri, 05 Aug 2022 12:27:43 -0400 X-MC-Unique: Pk1rt4vvMui4fAntXRucgA-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 398C1801585 for ; Fri, 5 Aug 2022 16:27:43 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.192.97]) by smtp.corp.redhat.com (Postfix) with ESMTP id 60942492C3B; Fri, 5 Aug 2022 16:27:42 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Fri, 5 Aug 2022 18:27:40 +0200 Message-Id: <165971685758.246236.7896816324623213286.stgit@dceara.remote.csb> In-Reply-To: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> References: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: surya@redhat.com Subject: [ovs-dev] [RFC PATCH ovn 4/5] lb: Support using templates. 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" Signed-off-by: Dumitru Ceara --- TODO: - No support for LB health check if the LB is templated. - No support for VIP ARP responder if the LB is templated. - No support for routed VIPs if the LB is templated. - No 'ovn-nbctl lb-*' commands support for templated LBs. Signed-off-by: Dumitru Ceara --- controller/lflow.c | 18 +++-- lib/lb.c | 200 +++++++++++++++++++++++++++++++++++++++++++++------- lib/lb.h | 35 +++++++-- northd/northd.c | 64 +++++++++-------- 4 files changed, 245 insertions(+), 72 deletions(-) diff --git a/controller/lflow.c b/controller/lflow.c index 6e60728f0..fe887d3cb 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -2343,7 +2343,9 @@ add_lb_ct_snat_hairpin_flows(struct ovn_controller_lb *lb, static void consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, - const struct hmap *local_datapaths, bool use_ct_mark, + const struct hmap *local_datapaths, + const struct smap *template_vars, + bool use_ct_mark, struct ovn_desired_flow_table *flow_table, struct simap *ids) { @@ -2366,7 +2368,8 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, return; } - struct ovn_controller_lb *lb = ovn_controller_lb_create(sbrec_lb); + struct ovn_controller_lb *lb = ovn_controller_lb_create(sbrec_lb, + template_vars); uint8_t lb_proto = IPPROTO_TCP; if (lb->slb->protocol && lb->slb->protocol[0]) { if (!strcmp(lb->slb->protocol, "udp")) { @@ -2396,7 +2399,9 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, * backends to handle the load balanced hairpin traffic. */ static void add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table, - const struct hmap *local_datapaths, bool use_ct_mark, + const struct hmap *local_datapaths, + const struct smap *template_vars, + bool use_ct_mark, struct ovn_desired_flow_table *flow_table, struct simap *ids, struct id_pool *pool) @@ -2419,8 +2424,8 @@ add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table, ovs_assert(id_pool_alloc_id(pool, &id)); simap_put(ids, lb->name, id); } - consider_lb_hairpin_flows(lb, local_datapaths, use_ct_mark, flow_table, - ids); + consider_lb_hairpin_flows(lb, local_datapaths, template_vars, + use_ct_mark, flow_table, ids); } } @@ -2557,6 +2562,7 @@ lflow_run(struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out) l_ctx_in->local_datapaths, l_ctx_out->flow_table); add_lb_hairpin_flows(l_ctx_in->lb_table, l_ctx_in->local_datapaths, + l_ctx_in->template_vars, l_ctx_in->lb_hairpin_use_ct_mark, l_ctx_out->flow_table, l_ctx_out->hairpin_lb_ids, @@ -2721,6 +2727,7 @@ lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *dp, * associated. */ for (size_t i = 0; i < n_dp_lbs; i++) { consider_lb_hairpin_flows(dp_lbs[i], l_ctx_in->local_datapaths, + l_ctx_in->template_vars, l_ctx_in->lb_hairpin_use_ct_mark, l_ctx_out->flow_table, l_ctx_out->hairpin_lb_ids); @@ -2852,6 +2859,7 @@ lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in, VLOG_DBG("Add load balancer hairpin flows for "UUID_FMT, UUID_ARGS(&lb->header_.uuid)); consider_lb_hairpin_flows(lb, l_ctx_in->local_datapaths, + l_ctx_in->template_vars, l_ctx_in->lb_hairpin_use_ct_mark, l_ctx_out->flow_table, l_ctx_out->hairpin_lb_ids); diff --git a/lib/lb.c b/lib/lb.c index 7b0ed1abe..56944ace8 100644 --- a/lib/lb.c +++ b/lib/lb.c @@ -19,6 +19,7 @@ #include "lib/ovn-nb-idl.h" #include "lib/ovn-sb-idl.h" #include "lib/ovn-util.h" +#include "ovn/lex.h" /* OpenvSwitch lib includes. */ #include "openvswitch/vlog.h" @@ -26,29 +27,13 @@ VLOG_DEFINE_THIS_MODULE(lb); -static -bool ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key, - const char *lb_value) +/* Format for backend ips: "IP1:port1,IP2:port2,...". */ +static size_t +ovn_lb_backends_init_explicit(struct ovn_lb_vip *lb_vip, const char *value) { - int addr_family; - - if (!ip_address_and_port_from_lb_key(lb_key, &lb_vip->vip_str, - &lb_vip->vip_port, &addr_family)) { - return false; - } - - if (addr_family == AF_INET) { - ovs_be32 vip4; - ip_parse(lb_vip->vip_str, &vip4); - in6_addr_set_mapped_ipv4(&lb_vip->vip, vip4); - } else { - ipv6_parse(lb_vip->vip_str, &lb_vip->vip); - } - - /* Format for backend ips: "IP1:port1,IP2:port2,...". */ size_t n_backends = 0; size_t n_allocated_backends = 0; - char *tokstr = xstrdup(lb_value); + char *tokstr = xstrdup(value); char *save_ptr = NULL; for (char *token = strtok_r(tokstr, ",", &save_ptr); token != NULL; @@ -68,12 +53,15 @@ bool ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key, continue; } - if (addr_family != backend_addr_family) { + if (lb_vip->address_family != backend_addr_family) { free(backend->ip_str); continue; } - if (addr_family == AF_INET) { + backend->port_str = + backend->port ? xasprintf("%"PRIu16, backend->port) : NULL; + + if (lb_vip->address_family == AF_INET) { ovs_be32 ip4; ip_parse(backend->ip_str, &ip4); in6_addr_set_mapped_ipv4(&backend->ip, ip4); @@ -83,16 +71,156 @@ bool ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key, n_backends++; } free(tokstr); - lb_vip->n_backends = n_backends; + return n_backends; +} + +static +bool ovn_lb_vip_init_explicit(struct ovn_lb_vip *lb_vip, const char *lb_key, + const char *lb_value) +{ + if (!ip_address_and_port_from_lb_key(lb_key, &lb_vip->vip_str, + &lb_vip->vip_port, + &lb_vip->address_family)) { + return false; + } + + lb_vip->port_str = lb_vip->vip_port + ? xasprintf("%"PRIu16, lb_vip->vip_port) + : NULL; + + if (lb_vip->address_family == AF_INET) { + ovs_be32 vip4; + ip_parse(lb_vip->vip_str, &vip4); + in6_addr_set_mapped_ipv4(&lb_vip->vip, vip4); + } else { + ipv6_parse(lb_vip->vip_str, &lb_vip->vip); + } + lb_vip->n_backends = ovn_lb_backends_init_explicit(lb_vip, lb_value); return true; } +/* Parses backends of a templated LB VIP. + * For now only the following template forms are supported: + * A. + * ^backendip_variable1[:^port_variable1|:port], + * ^backendip_variable2[:^port_variable2|:port] + * + * B. + * ^backends_variable1,^backends_variable2 is also a thing + * where 'backends_variable1' may expand to IP1_1:PORT1_1 on chassis-1 + * IP1_2:PORT1_2 on chassis-2 + * and 'backends_variable2' may expand to IP2_1:PORT2_1 on chassis-1 + * IP2_2:PORT2_2 on chassis-2 + * + * Returns the number of successfully parsed backends. + */ +static size_t +ovn_lb_backends_init_template(struct ovn_lb_vip *lb_vip, const char *value_) +{ + char *value = xstrdup(value_); + char *save_ptr = NULL; + size_t n_allocated_backends = 0; + size_t n_backends = 0; + + for (char *backend = strtok_r(value, ",", &save_ptr); backend; + backend = strtok_r(NULL, ",", &save_ptr)) { + + char *atom = xstrdup(backend); + char *save_ptr2 = NULL; + bool success = false; + char *backend_ip = NULL; + char *backend_port = NULL; + + for (char *subatom = strtok_r(atom, ":", &save_ptr2); subatom; + subatom = strtok_r(NULL, ":", &save_ptr2)) { + if (backend_ip && backend_port) { + /* XXX: Log when there are more than two tokens? */ + success = false; + break; + } + success = true; + if (!backend_ip) { + backend_ip = xstrdup(subatom); + } else { + backend_port = xstrdup(subatom); + } + } + + if (success) { + if (n_backends == n_allocated_backends) { + lb_vip->backends = x2nrealloc(lb_vip->backends, + &n_allocated_backends, + sizeof *lb_vip->backends); + } + lb_vip->backends[n_backends].ip_str = backend_ip; + lb_vip->backends[n_backends].port_str = backend_port; + lb_vip->backends[n_backends].port = 0; + n_backends++; + } + free(atom); + } + + free(value); + return n_backends; +} + +/* Parses a VIP of a templated LB. + * For now only the following template forms are supported: + * ^vip_variable[:^port_variable|:port] + */ +static bool +ovn_lb_vip_init_template(struct ovn_lb_vip *lb_vip, const char *lb_key_, + const char *lb_value, int address_family) +{ + char *save_ptr = NULL; + char *lb_key = xstrdup(lb_key_); + bool success = false; + + for (char *atom = strtok_r(lb_key, ":", &save_ptr); atom; + atom = strtok_r(NULL, ":", &save_ptr)) { + if (lb_vip->vip_str && lb_vip->port_str) { + /* XXX: Log when there are more than two tokens? */ + success = false; + break; + } + success = true; + if (!lb_vip->vip_str) { + lb_vip->vip_str = xstrdup(atom); + } else { + lb_vip->port_str = xstrdup(atom); + } + } + + free(lb_key); + + lb_vip->address_family = address_family; + if (success) { + lb_vip->n_backends = ovn_lb_backends_init_template(lb_vip, lb_value); + } + return success; +} + +static +bool ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key, + const char *lb_value, bool is_template, + int address_family) +{ + if (!is_template) { + return ovn_lb_vip_init_explicit(lb_vip, lb_key, lb_value); + } else { + return ovn_lb_vip_init_template(lb_vip, lb_key, lb_value, + address_family); + } +} + static void ovn_lb_vip_destroy(struct ovn_lb_vip *vip) { free(vip->vip_str); + free(vip->port_str); for (size_t i = 0; i < vip->n_backends; i++) { free(vip->backends[i].ip_str); + free(vip->backends[i].port_str); } free(vip->backends); } @@ -167,12 +295,19 @@ ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb) bool is_udp = nullable_string_is_equal(nbrec_lb->protocol, "udp"); bool is_sctp = nullable_string_is_equal(nbrec_lb->protocol, "sctp"); struct ovn_northd_lb *lb = xzalloc(sizeof *lb); + int address_family = !strcmp(smap_get_def(&nbrec_lb->options, + "address-family", "ipv4"), + "ipv4") + ? AF_INET + : AF_INET6; lb->nlb = nbrec_lb; lb->proto = is_udp ? "udp" : is_sctp ? "sctp" : "tcp"; lb->n_vips = smap_count(&nbrec_lb->vips); lb->vips = xcalloc(lb->n_vips, sizeof *lb->vips); lb->vips_nb = xcalloc(lb->n_vips, sizeof *lb->vips_nb); + lb->is_template = smap_get_bool(&nbrec_lb->options, "template", false); + sset_init(&lb->ips_v4); sset_init(&lb->ips_v6); struct smap_node *node; @@ -184,7 +319,8 @@ ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb) lb_vip->empty_backend_rej = smap_get_bool(&nbrec_lb->options, "reject", false); - if (!ovn_lb_vip_init(lb_vip, node->key, node->value)) { + if (!ovn_lb_vip_init(lb_vip, node->key, node->value, lb->is_template, + address_family)) { continue; } ovn_northd_lb_vip_init(lb_vip_nb, lb_vip, nbrec_lb, @@ -276,7 +412,8 @@ ovn_northd_lb_destroy(struct ovn_northd_lb *lb) } struct ovn_controller_lb * -ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb) +ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb, + const struct smap *template_vars) { struct ovn_controller_lb *lb = xzalloc(sizeof *lb); @@ -290,10 +427,17 @@ ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb) SMAP_FOR_EACH (node, &sbrec_lb->vips) { struct ovn_lb_vip *lb_vip = &lb->vips[n_vips]; - if (!ovn_lb_vip_init(lb_vip, node->key, node->value)) { - continue; + char *key_s = lexer_parse_template_string(xstrdup(node->key), + template_vars, + NULL); + char *value_s = lexer_parse_template_string(xstrdup(node->value), + template_vars, + NULL); + if (ovn_lb_vip_init_explicit(lb_vip, key_s, value_s)) { + n_vips++; } - n_vips++; + free(key_s); + free(value_s); } /* It's possible that parsing VIPs fails. Update the lb->n_vips to the diff --git a/lib/lb.h b/lib/lb.h index 832ed31fb..192ec7ed2 100644 --- a/lib/lb.h +++ b/lib/lb.h @@ -50,27 +50,43 @@ struct ovn_northd_lb { size_t n_nb_lr; size_t n_allocated_nb_lr; struct ovn_datapath **nb_lr; + + bool is_template; }; struct ovn_lb_vip { - struct in6_addr vip; - char *vip_str; - uint16_t vip_port; - + struct in6_addr vip; /* Only used in ovn-controller. */ + char *vip_str; /* Actual VIP string representation (without port). + * To be used in ovn-northd. + */ + uint16_t vip_port; /* Only used in ovn-controller. */ + char *port_str; /* Actual port string representation. To be used + * in ovn-controller. + */ struct ovn_lb_backend *backends; size_t n_backends; bool empty_backend_rej; + int address_family; }; struct ovn_lb_backend { - struct in6_addr ip; - char *ip_str; - uint16_t port; + struct in6_addr ip; /* Only used in ovn-controller. */ + char *ip_str; /* Actual IP string representation. To be used in + * ovn-northd. + */ + uint16_t port; /* Mostly used in ovn-controller but also for + * healthcheck in ovn-northd. + */ + char *port_str; /* Actual port string representation. To be used + * in ovn-northd. + */ }; /* ovn-northd specific backend information. */ struct ovn_northd_lb_vip { - char *vip_port_str; + char *vip_port_str; /* VIP string representation of the form: + * "VIP[:port]" + */ char *backend_ips; struct ovn_northd_lb_backend *backends_nb; size_t n_backends; @@ -109,7 +125,8 @@ struct ovn_controller_lb { }; struct ovn_controller_lb *ovn_controller_lb_create( - const struct sbrec_load_balancer *); + const struct sbrec_load_balancer *, + const struct smap *template_vars); void ovn_controller_lb_destroy(struct ovn_controller_lb *); #endif /* OVN_LIB_LB_H 1 */ diff --git a/northd/northd.c b/northd/northd.c index c4769ea07..e9a6dad38 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -3821,6 +3821,10 @@ static void ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, struct ovn_northd_lb *lb, struct hmap *monitor_map, struct hmap *ports) { + if (lb->is_template) { + return; + } + for (size_t i = 0; i < lb->n_vips; i++) { struct ovn_lb_vip *lb_vip = &lb->vips[i]; struct ovn_northd_lb_vip *lb_vip_nb = &lb->vips_nb[i]; @@ -4097,7 +4101,7 @@ build_lrouter_lb_reachable_ips(struct ovn_datapath *od, */ if (!strcmp(neighbor_responder_mode, "all")) { for (size_t i = 0; i < lb->n_vips; i++) { - if (IN6_IS_ADDR_V4MAPPED(&lb->vips[i].vip)) { + if (lb->vips[i].address_family == AF_INET) { sset_add(&od->lb_ips_v4_reachable, lb->vips[i].vip_str); } else { sset_add(&od->lb_ips_v6_reachable, lb->vips[i].vip_str); @@ -4110,7 +4114,7 @@ build_lrouter_lb_reachable_ips(struct ovn_datapath *od, * subnet that includes it. */ for (size_t i = 0; i < lb->n_vips; i++) { - if (IN6_IS_ADDR_V4MAPPED(&lb->vips[i].vip)) { + if (lb->vips[i].address_family == AF_INET) { ovs_be32 vip_ip4 = in6_addr_get_mapped_ipv4(&lb->vips[i].vip); struct ovn_port *op; @@ -5782,17 +5786,17 @@ build_empty_lb_event_flow(struct ovn_lb_vip *lb_vip, ds_clear(action); ds_clear(match); - bool ipv4 = IN6_IS_ADDR_V4MAPPED(&lb_vip->vip); + bool ipv4 = lb_vip->address_family == AF_INET; ds_put_format(match, "ip%s.dst == %s && %s", ipv4 ? "4": "6", lb_vip->vip_str, lb->protocol); char *vip = lb_vip->vip_str; - if (lb_vip->vip_port) { - ds_put_format(match, " && %s.dst == %u", lb->protocol, - lb_vip->vip_port); - vip = xasprintf("%s%s%s:%u", ipv4 ? "" : "[", lb_vip->vip_str, - ipv4 ? "" : "]", lb_vip->vip_port); + if (lb_vip->port_str) { + ds_put_format(match, " && %s.dst == %s", lb->protocol, + lb_vip->port_str); + vip = xasprintf("%s%s%s:%s", ipv4 ? "" : "[", lb_vip->vip_str, + ipv4 ? "" : "]", lb_vip->port_str); } ds_put_format(action, @@ -5803,7 +5807,7 @@ build_empty_lb_event_flow(struct ovn_lb_vip *lb_vip, event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS), vip, lb->protocol, UUID_ARGS(&lb->header_.uuid)); - if (lb_vip->vip_port) { + if (lb_vip->port_str) { free(vip); } return true; @@ -6893,7 +6897,7 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, bool ct_lb_mark, /* Store the original destination IP to be used when generating * hairpin flows. */ - if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) { + if (lb->vips[i].address_family == AF_INET) { ip_match = "ip4"; ds_put_format(action, REG_ORIG_DIP_IPV4 " = %s; ", lb_vip->vip_str); @@ -6904,7 +6908,7 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, bool ct_lb_mark, } const char *proto = NULL; - if (lb_vip->vip_port) { + if (lb_vip->port_str) { proto = "tcp"; if (lb->nlb->protocol) { if (!strcmp(lb->nlb->protocol, "udp")) { @@ -6917,8 +6921,8 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, bool ct_lb_mark, /* Store the original destination port to be used when generating * hairpin flows. */ - ds_put_format(action, REG_ORIG_TP_DPORT " = %"PRIu16"; ", - lb_vip->vip_port); + ds_put_format(action, REG_ORIG_TP_DPORT " = %s; ", + lb_vip->port_str); } /* New connections in Ingress table. */ @@ -6930,8 +6934,8 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, bool ct_lb_mark, ds_put_format(match, "ct.new && %s.dst == %s", ip_match, lb_vip->vip_str); int priority = 110; - if (lb_vip->vip_port) { - ds_put_format(match, " && %s.dst == %d", proto, lb_vip->vip_port); + if (lb_vip->port_str) { + ds_put_format(match, " && %s.dst == %s", proto, lb_vip->port_str); priority = 120; } @@ -9848,7 +9852,7 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, * of "ct_lb_mark($targets);". The other flow is for ct.est with * an action of "next;". */ - if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) { + if (lb_vip->address_family == AF_INET) { ds_put_format(match, "ip4 && "REG_NEXT_HOP_IPV4" == %s", lb_vip->vip_str); } else { @@ -9865,14 +9869,14 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, } int prio = 110; - if (lb_vip->vip_port) { + if (lb_vip->port_str) { prio = 120; new_match = xasprintf("ct.new && %s && %s && " - REG_ORIG_TP_DPORT_ROUTER" == %d", - ds_cstr(match), lb->proto, lb_vip->vip_port); + REG_ORIG_TP_DPORT_ROUTER" == %s", + ds_cstr(match), lb->proto, lb_vip->port_str); est_match = xasprintf("ct.est && %s && %s && " - REG_ORIG_TP_DPORT_ROUTER" == %d && %s == 1", - ds_cstr(match), lb->proto, lb_vip->vip_port, + REG_ORIG_TP_DPORT_ROUTER" == %s && %s == 1", + ds_cstr(match), lb->proto, lb_vip->port_str, ct_natted); } else { new_match = xasprintf("ct.new && %s", ds_cstr(match)); @@ -9881,7 +9885,7 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, } const char *ip_match = NULL; - if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) { + if (lb_vip->address_family == AF_INET) { ip_match = "ip4"; } else { ip_match = "ip6"; @@ -9899,9 +9903,9 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, ds_put_format(&undnat_match, "(%s.src == %s", ip_match, backend->ip_str); - if (backend->port) { - ds_put_format(&undnat_match, " && %s.src == %d) || ", - lb->proto, backend->port); + if (backend->port_str) { + ds_put_format(&undnat_match, " && %s.src == %s) || ", + lb->proto, backend->port_str); } else { ds_put_cstr(&undnat_match, ") || "); } @@ -9914,9 +9918,9 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, struct ds unsnat_match = DS_EMPTY_INITIALIZER; ds_put_format(&unsnat_match, "%s && %s.dst == %s && %s", ip_match, ip_match, lb_vip->vip_str, lb->proto); - if (lb_vip->vip_port) { - ds_put_format(&unsnat_match, " && %s.dst == %d", lb->proto, - lb_vip->vip_port); + if (lb_vip->port_str) { + ds_put_format(&unsnat_match, " && %s.dst == %s", lb->proto, + lb_vip->port_str); } struct ovn_datapath **gw_router_skip_snat = @@ -10154,7 +10158,7 @@ build_lrouter_defrag_flows_for_lb(struct ovn_northd_lb *lb, ds_clear(&defrag_actions); ds_clear(match); - if (IN6_IS_ADDR_V4MAPPED(&lb_vip->vip)) { + if (lb_vip->address_family == AF_INET) { ds_put_format(match, "ip && ip4.dst == %s", lb_vip->vip_str); ds_put_format(&defrag_actions, REG_NEXT_HOP_IPV4" = %s; ", lb_vip->vip_str); @@ -10164,7 +10168,7 @@ build_lrouter_defrag_flows_for_lb(struct ovn_northd_lb *lb, lb_vip->vip_str); } - if (lb_vip->vip_port) { + if (lb_vip->port_str) { ds_put_format(match, " && %s", lb->proto); prio = 110; From patchwork Fri Aug 5 16:27:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1664133 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.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=V5NWFmic; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Lzrcb5HnLz9sB4 for ; Sat, 6 Aug 2022 02:28:15 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 32CA283F16; Fri, 5 Aug 2022 16:28:14 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 32CA283F16 Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=V5NWFmic X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fmXn8j0uWVZK; Fri, 5 Aug 2022 16:28:13 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 311F483F1F; Fri, 5 Aug 2022 16:28:12 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 311F483F1F Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 05A75C0032; Fri, 5 Aug 2022 16:28:12 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 25D93C0078 for ; Fri, 5 Aug 2022 16:28:10 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id DCA396F994 for ; Fri, 5 Aug 2022 16:27:58 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org DCA396F994 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=V5NWFmic X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id i-KRg_bCk7vl for ; Fri, 5 Aug 2022 16:27:58 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org C7CAD60EC4 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id C7CAD60EC4 for ; Fri, 5 Aug 2022 16:27:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1659716876; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UbMxnQ2jtXyVu1sYtm+ug9GhYfaHMiEd77c6gu2OivE=; b=V5NWFmicCXCwXOTYY3KOIBMMDYZfsJnwHYkByjmHNIO0Zf6pMl7wkfQys+b7rzTDSwZpVe vMg9+5nAhT9e+wx1LZXAA1JELV5KhxMnbUEEJU6uxQ89ba6nCllmEJye/jqPGP9/NlCe1A BEUMxkN41BVdyhSS3QWKc2fb/N2xbts= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-26-FuFzk1GjOyWgbTQuqeLhkw-1; Fri, 05 Aug 2022 12:27:53 -0400 X-MC-Unique: FuFzk1GjOyWgbTQuqeLhkw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3990938005C5 for ; Fri, 5 Aug 2022 16:27:53 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.192.97]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4AB172166B26; Fri, 5 Aug 2022 16:27:52 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Fri, 5 Aug 2022 18:27:49 +0200 Message-Id: <165971686843.246236.12572451498600321275.stgit@dceara.remote.csb> In-Reply-To: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> References: <165971680356.246236.1723217950402767004.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: surya@redhat.com Subject: [ovs-dev] [RFC PATCH ovn 5/5] controller: Add Template_Var <- LB references. 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" Signed-off-by: Dumitru Ceara --- controller/lflow.c | 72 ++++++++++++++++++++++++++++++++++++++----- controller/lflow.h | 1 + controller/ovn-controller.c | 21 +++++++++++++ lib/lb.c | 7 ++-- lib/lb.h | 3 +- 5 files changed, 92 insertions(+), 12 deletions(-) diff --git a/controller/lflow.c b/controller/lflow.c index fe887d3cb..f3ec5528e 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -54,6 +54,7 @@ lflow_init(void) { ovn_init_symtab(&symtab); } + struct lookup_port_aux { struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath; @@ -98,6 +99,14 @@ consider_logical_flow(const struct sbrec_logical_flow *lflow, bool is_recompute, struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out); +static void +consider_lb_hairpin_flows(struct lflow_resource_ref *lfrr, + const struct sbrec_load_balancer *sbrec_lb, + const struct hmap *local_datapaths, + const struct smap *template_vars, + bool use_ct_mark, + struct ovn_desired_flow_table *flow_table, + struct simap *ids); static struct lflow_processed_node * lflows_processed_find(struct hmap *lflows_processed, const struct uuid *lflow_uuid); @@ -1076,6 +1085,40 @@ lflow_handle_changed_ref(enum ref_type ref_type, const char *ref_name, controller_event_opts_destroy(&controller_event_opts); } +static void +lb_handle_changed_ref(enum ref_type ref_type, const char *ref_name, + struct lflow_ctx_in *l_ctx_in, + struct lflow_ctx_out *l_ctx_out, + struct ovs_list *lbs_todo) +{ + struct lflow_ref_list_node *lrln_uuid; + LIST_FOR_EACH_POP (lrln_uuid, list_node, lbs_todo) { + VLOG_DBG("Reprocess LB "UUID_FMT" for resource type: %d," + " name: %s", + UUID_ARGS(&lrln_uuid->lflow_uuid), + ref_type, ref_name); + + const struct sbrec_load_balancer *lb = + sbrec_load_balancer_table_get_for_uuid(l_ctx_in->lb_table, + &lrln_uuid->lflow_uuid); + if (!lb) { + VLOG_DBG("Failed to find LB "UUID_FMT" referred by: %s", + UUID_ARGS(&lrln_uuid->lflow_uuid), ref_name); + } else { + ofctrl_remove_flows(l_ctx_out->flow_table, &lrln_uuid->lflow_uuid); + + consider_lb_hairpin_flows(l_ctx_out->lfrr, lb, + l_ctx_in->local_datapaths, + l_ctx_in->template_vars, + l_ctx_in->lb_hairpin_use_ct_mark, + l_ctx_out->flow_table, + l_ctx_out->hairpin_lb_ids); + } + + free(lrln_uuid); + } +} + static void lflow_parse_ctrl_meter(const struct sbrec_logical_flow *lflow, struct ovn_extend_table *meter_table, @@ -2342,7 +2385,8 @@ add_lb_ct_snat_hairpin_flows(struct ovn_controller_lb *lb, } static void -consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, +consider_lb_hairpin_flows(struct lflow_resource_ref *lfrr, + const struct sbrec_load_balancer *sbrec_lb, const struct hmap *local_datapaths, const struct smap *template_vars, bool use_ct_mark, @@ -2368,8 +2412,9 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, return; } - struct ovn_controller_lb *lb = ovn_controller_lb_create(sbrec_lb, - template_vars); + struct sset template_vars_ref = SSET_INITIALIZER(&template_vars_ref); + struct ovn_controller_lb *lb = + ovn_controller_lb_create(sbrec_lb, template_vars, &template_vars_ref); uint8_t lb_proto = IPPROTO_TCP; if (lb->slb->protocol && lb->slb->protocol[0]) { if (!strcmp(lb->slb->protocol, "udp")) { @@ -2379,6 +2424,11 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, } } + const char *tv_name; + SSET_FOR_EACH (tv_name, &template_vars_ref) { + lflow_resource_add(lfrr, REF_TYPE_TEMPLATE_LB, tv_name, + &sbrec_lb->header_.uuid, 0); + } for (i = 0; i < lb->n_vips; i++) { struct ovn_lb_vip *lb_vip = &lb->vips[i]; @@ -2393,12 +2443,14 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, add_lb_ct_snat_hairpin_flows(lb, id, lb_proto, flow_table); ovn_controller_lb_destroy(lb); + sset_destroy(&template_vars_ref); } /* Adds OpenFlow flows to flow tables for each Load balancer VIPs and * backends to handle the load balanced hairpin traffic. */ static void -add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table, +add_lb_hairpin_flows(struct lflow_resource_ref *lfrr, + const struct sbrec_load_balancer_table *lb_table, const struct hmap *local_datapaths, const struct smap *template_vars, bool use_ct_mark, @@ -2424,7 +2476,7 @@ add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table, ovs_assert(id_pool_alloc_id(pool, &id)); simap_put(ids, lb->name, id); } - consider_lb_hairpin_flows(lb, local_datapaths, template_vars, + consider_lb_hairpin_flows(lfrr, lb, local_datapaths, template_vars, use_ct_mark, flow_table, ids); } } @@ -2561,7 +2613,8 @@ lflow_run(struct lflow_ctx_in *l_ctx_in, struct lflow_ctx_out *l_ctx_out) l_ctx_in->static_mac_binding_table, l_ctx_in->local_datapaths, l_ctx_out->flow_table); - add_lb_hairpin_flows(l_ctx_in->lb_table, l_ctx_in->local_datapaths, + add_lb_hairpin_flows(l_ctx_out->lfrr, l_ctx_in->lb_table, + l_ctx_in->local_datapaths, l_ctx_in->template_vars, l_ctx_in->lb_hairpin_use_ct_mark, l_ctx_out->flow_table, @@ -2726,7 +2779,8 @@ lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *dp, /* Add load balancer hairpin flows if the datapath has any load balancers * associated. */ for (size_t i = 0; i < n_dp_lbs; i++) { - consider_lb_hairpin_flows(dp_lbs[i], l_ctx_in->local_datapaths, + consider_lb_hairpin_flows(l_ctx_out->lfrr, dp_lbs[i], + l_ctx_in->local_datapaths, l_ctx_in->template_vars, l_ctx_in->lb_hairpin_use_ct_mark, l_ctx_out->flow_table, @@ -2858,7 +2912,8 @@ lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in, VLOG_DBG("Add load balancer hairpin flows for "UUID_FMT, UUID_ARGS(&lb->header_.uuid)); - consider_lb_hairpin_flows(lb, l_ctx_in->local_datapaths, + consider_lb_hairpin_flows(l_ctx_out->lfrr, lb, + l_ctx_in->local_datapaths, l_ctx_in->template_vars, l_ctx_in->lb_hairpin_use_ct_mark, l_ctx_out->flow_table, @@ -3690,6 +3745,7 @@ static ref_change_handler ref_change_handlers[REF_TYPE_MAX] = { [REF_TYPE_PORTBINDING] = lflow_handle_changed_ref, [REF_TYPE_MC_GROUP] = lflow_handle_changed_ref, [REF_TYPE_TEMPLATE] = lflow_handle_changed_ref, + [REF_TYPE_TEMPLATE_LB] = lb_handle_changed_ref, }; bool diff --git a/controller/lflow.h b/controller/lflow.h index 21e682017..aa08d911d 100644 --- a/controller/lflow.h +++ b/controller/lflow.h @@ -129,6 +129,7 @@ enum ref_type { REF_TYPE_PORTBINDING, REF_TYPE_MC_GROUP, REF_TYPE_TEMPLATE, + REF_TYPE_TEMPLATE_LB, REF_TYPE_MAX, }; diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 207ea4e51..0f33dac9e 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -3071,6 +3071,13 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) if (changed) { engine_set_node_state(node, EN_UPDATED); } + if (!ref_change_handle(REF_TYPE_TEMPLATE_LB, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { + return false; + } + if (changed) { + engine_set_node_state(node, EN_UPDATED); + } } SSET_FOR_EACH (ref_name, &tv_data->updated) { if (!ref_change_handle(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, @@ -3080,6 +3087,13 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) if (changed) { engine_set_node_state(node, EN_UPDATED); } + if (!ref_change_handle(REF_TYPE_TEMPLATE_LB, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { + return false; + } + if (changed) { + engine_set_node_state(node, EN_UPDATED); + } } SSET_FOR_EACH (ref_name, &tv_data->new) { if (!ref_change_handle(REF_TYPE_TEMPLATE, ref_name, &l_ctx_in, @@ -3089,6 +3103,13 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) if (changed) { engine_set_node_state(node, EN_UPDATED); } + if (!ref_change_handle(REF_TYPE_TEMPLATE_LB, ref_name, &l_ctx_in, + &l_ctx_out, &changed)) { + return false; + } + if (changed) { + engine_set_node_state(node, EN_UPDATED); + } } return true; diff --git a/lib/lb.c b/lib/lb.c index 56944ace8..a81de7ca6 100644 --- a/lib/lb.c +++ b/lib/lb.c @@ -413,7 +413,8 @@ ovn_northd_lb_destroy(struct ovn_northd_lb *lb) struct ovn_controller_lb * ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb, - const struct smap *template_vars) + const struct smap *template_vars, + struct sset *template_vars_ref) { struct ovn_controller_lb *lb = xzalloc(sizeof *lb); @@ -429,10 +430,10 @@ ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb, char *key_s = lexer_parse_template_string(xstrdup(node->key), template_vars, - NULL); + template_vars_ref); char *value_s = lexer_parse_template_string(xstrdup(node->value), template_vars, - NULL); + template_vars_ref); if (ovn_lb_vip_init_explicit(lb_vip, key_s, value_s)) { n_vips++; } diff --git a/lib/lb.h b/lib/lb.h index 192ec7ed2..99146b6ab 100644 --- a/lib/lb.h +++ b/lib/lb.h @@ -126,7 +126,8 @@ struct ovn_controller_lb { struct ovn_controller_lb *ovn_controller_lb_create( const struct sbrec_load_balancer *, - const struct smap *template_vars); + const struct smap *template_vars, + struct sset *template_vars_ref); void ovn_controller_lb_destroy(struct ovn_controller_lb *); #endif /* OVN_LIB_LB_H 1 */