From patchwork Thu Aug 10 12:44:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1819841 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.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=ilgpvwSM; dkim-atps=neutral Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RM6843s8Qz1yf2 for ; Thu, 10 Aug 2023 22:44:52 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 8092C60B7C; Thu, 10 Aug 2023 12:44:50 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 8092C60B7C 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=ilgpvwSM 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 l4DWpCT-yqmD; Thu, 10 Aug 2023 12:44:49 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 2F71260AB7; Thu, 10 Aug 2023 12:44:48 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 2F71260AB7 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id F0231C0072; Thu, 10 Aug 2023 12:44:47 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 30ADCC0032 for ; Thu, 10 Aug 2023 12:44:46 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id F1BE141B88 for ; Thu, 10 Aug 2023 12:44:45 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org F1BE141B88 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=ilgpvwSM 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 RPvkPISFB3bp for ; Thu, 10 Aug 2023 12:44:44 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp4.osuosl.org (Postfix) with ESMTPS id 6533641B84 for ; Thu, 10 Aug 2023 12:44:44 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 6533641B84 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691671483; 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=M9LxfIQJDXQaHxkz8j1/ATb/GZxgdACpuNZ127EHFs8=; b=ilgpvwSMrYSU2+WZVWvZz2/dAz3GXaNS/KCvecJSBUVS+7AJPKrx7F/A5VSScJGEkUNfeL 5SPVMRLlX8iqxdifezZNOnjZN4sX5ug7h0x5Iygg/1CMrtiqRtbg7dPZH8x5DbK9hCHULS SIATqWbTrK+N8w3nxHxt+STArqyEPDM= 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-551-o862VAKLMl6wbdYjwa5xvg-1; Thu, 10 Aug 2023 08:44:39 -0400 X-MC-Unique: o862VAKLMl6wbdYjwa5xvg-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 801A48DC666; Thu, 10 Aug 2023 12:44:39 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.194.96]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5FD15492C13; Thu, 10 Aug 2023 12:44:38 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Thu, 10 Aug 2023 14:44:35 +0200 Message-Id: <169167147158.2447623.6554641432367089545.stgit@dceara.remote.csb> In-Reply-To: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> References: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn 1/5] ovn-util: Factor out struct sorted_addresses into sorted_array. 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" It's actually a generic wrapper and will be useful for upcoming commits. This commit doesn't perform any functional changes but cleans up a bit the implementation unifying the sorted_array cleanup. Before the change the caller had to track whether it should free the internal 'arr' field or not. It's now taken care of inside the sorted_array_destroy() API which the user always has to call. Signed-off-by: Dumitru Ceara Acked-by: Han Zhou Acked-by: Ales Musil --- lib/ovn-util.h | 78 +++++++++++++++++++++++++++ northd/en-sync-sb.c | 150 +++++++++++++++++---------------------------------- 2 files changed, 127 insertions(+), 101 deletions(-) diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 5ebdd8adb0..2de7725132 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -18,6 +18,8 @@ #include "ovsdb-idl.h" #include "lib/packets.h" +#include "lib/sset.h" +#include "lib/svec.h" #include "include/ovn/version.h" #define ovn_set_program_name(name) \ @@ -409,4 +411,80 @@ void flow_collector_ids_clear(struct flow_collector_ids *); * The returned pointer has to be freed by caller. */ char *encode_fqdn_string(const char *fqdn, size_t *len); +/* A wrapper that holds sorted arrays of strings. */ +struct sorted_array { + const char **arr; + bool owns_array; + size_t n; +}; + +static inline struct sorted_array +sorted_array_create(const char **sorted_data, size_t n, bool take_ownership) +{ + return (struct sorted_array) { + .arr = sorted_data, + .owns_array = take_ownership, + .n = n, + }; +} + +static inline void +sorted_array_destroy(struct sorted_array *a) +{ + if (a->owns_array) { + free(a->arr); + } +} + +static inline struct sorted_array +sorted_array_from_svec(struct svec *v) +{ + svec_sort(v); + return sorted_array_create((const char **) v->names, v->n, false); +} + +static inline struct sorted_array +sorted_array_from_sset(struct sset *s) +{ + return sorted_array_create(sset_sort(s), sset_count(s), true); +} + +/* DB set columns are already sorted, just wrap them into a sorted array. */ +#define sorted_array_from_dbrec(dbrec, column) \ + sorted_array_create((const char **) (dbrec)->column, \ + (dbrec)->n_##column, false) + +static inline void +sorted_array_apply_diff(const struct sorted_array *a1, + const struct sorted_array *a2, + void (*apply_callback)(const void *arg, + const char *item, + bool add), + const void *arg) +{ + size_t idx1, idx2; + + for (idx1 = idx2 = 0; idx1 < a1->n && idx2 < a2->n;) { + int cmp = strcmp(a1->arr[idx1], a2->arr[idx2]); + if (cmp < 0) { + apply_callback(arg, a1->arr[idx1], true); + idx1++; + } else if (cmp > 0) { + apply_callback(arg, a2->arr[idx2], false); + idx2++; + } else { + idx1++; + idx2++; + } + } + + for (; idx1 < a1->n; idx1++) { + apply_callback(arg, a1->arr[idx1], true); + } + + for (; idx2 < a2->n; idx2++) { + apply_callback(arg, a2->arr[idx2], false); + } +} + #endif /* OVN_UTIL_H */ diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c index d7fea981f2..f97771b3b4 100644 --- a/northd/en-sync-sb.c +++ b/northd/en-sync-sb.c @@ -33,15 +33,8 @@ VLOG_DEFINE_THIS_MODULE(en_sync_to_sb); -/* This is just a type wrapper to enforce that it has to be sorted. */ -struct sorted_addresses { - const char **arr; - size_t n; -}; - - static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, - struct sorted_addresses *addresses, + struct sorted_array *addresses, struct shash *sb_address_sets); static void sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn, const struct nbrec_address_set_table *, @@ -50,17 +43,11 @@ static void sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn, const struct ovn_datapaths *lr_datapaths); static const struct sbrec_address_set *sb_address_set_lookup_by_name( struct ovsdb_idl_index *, const char *name); -static void update_sb_addr_set(struct sorted_addresses *, +static void update_sb_addr_set(struct sorted_array *, const struct sbrec_address_set *); static void build_port_group_address_set(const struct nbrec_port_group *, struct svec *ipv4_addrs, struct svec *ipv6_addrs); -static struct sorted_addresses -sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as); -static struct sorted_addresses -sorted_addresses_from_svec(struct svec *addresses); -static struct sorted_addresses -sorted_addresses_from_sset(struct sset *addresses); void * en_sync_to_sb_init(struct engine_node *node OVS_UNUSED, @@ -145,9 +132,10 @@ sync_to_sb_addr_set_nb_address_set_handler(struct engine_node *node, if (!sb_addr_set) { return false; } - struct sorted_addresses addrs = - sorted_addresses_from_nbrec(nb_addr_set); + struct sorted_array addrs = + sorted_array_from_dbrec(nb_addr_set, addresses); update_sb_addr_set(&addrs, sb_addr_set); + sorted_array_destroy(&addrs); } return true; @@ -194,18 +182,20 @@ sync_to_sb_addr_set_nb_port_group_handler(struct engine_node *node, struct svec ipv6_addrs = SVEC_EMPTY_INITIALIZER; build_port_group_address_set(nb_pg, &ipv4_addrs, &ipv6_addrs); - struct sorted_addresses ipv4_addrs_sorted = - sorted_addresses_from_svec(&ipv4_addrs); - struct sorted_addresses ipv6_addrs_sorted = - sorted_addresses_from_svec(&ipv6_addrs); + struct sorted_array ipv4_addrs_sorted = + sorted_array_from_svec(&ipv4_addrs); + struct sorted_array ipv6_addrs_sorted = + sorted_array_from_svec(&ipv6_addrs); update_sb_addr_set(&ipv4_addrs_sorted, sb_addr_set_v4); update_sb_addr_set(&ipv6_addrs_sorted, sb_addr_set_v6); - free(ipv4_addrs_name); - free(ipv6_addrs_name); + sorted_array_destroy(&ipv4_addrs_sorted); + sorted_array_destroy(&ipv6_addrs_sorted); svec_destroy(&ipv4_addrs); svec_destroy(&ipv6_addrs); + free(ipv4_addrs_name); + free(ipv6_addrs_name); } return true; @@ -214,7 +204,7 @@ sync_to_sb_addr_set_nb_port_group_handler(struct engine_node *node, /* static functions. */ static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name, - struct sorted_addresses *addresses, + struct sorted_array *addresses, struct shash *sb_address_sets) { const struct sbrec_address_set *sb_address_set; @@ -261,11 +251,9 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn, /* Service monitor MAC. */ const char *svc_monitor_macp = northd_get_svc_monitor_mac(); - struct sorted_addresses svc = { - .arr = &svc_monitor_macp, - .n = 1, - }; + struct sorted_array svc = sorted_array_create(&svc_monitor_macp, 1, false); sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc, &sb_address_sets); + sorted_array_destroy(&svc); /* sync port group generated address sets first */ const struct nbrec_port_group *nb_port_group; @@ -277,19 +265,21 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn, char *ipv4_addrs_name = xasprintf("%s_ip4", nb_port_group->name); char *ipv6_addrs_name = xasprintf("%s_ip6", nb_port_group->name); - struct sorted_addresses ipv4_addrs_sorted = - sorted_addresses_from_svec(&ipv4_addrs); - struct sorted_addresses ipv6_addrs_sorted = - sorted_addresses_from_svec(&ipv6_addrs); + struct sorted_array ipv4_addrs_sorted = + sorted_array_from_svec(&ipv4_addrs); + struct sorted_array ipv6_addrs_sorted = + sorted_array_from_svec(&ipv6_addrs); sync_addr_set(ovnsb_txn, ipv4_addrs_name, &ipv4_addrs_sorted, &sb_address_sets); sync_addr_set(ovnsb_txn, ipv6_addrs_name, &ipv6_addrs_sorted, &sb_address_sets); - free(ipv4_addrs_name); - free(ipv6_addrs_name); + sorted_array_destroy(&ipv4_addrs_sorted); + sorted_array_destroy(&ipv6_addrs_sorted); svec_destroy(&ipv4_addrs); svec_destroy(&ipv6_addrs); + free(ipv4_addrs_name); + free(ipv6_addrs_name); } /* Sync router load balancer VIP generated address sets. */ @@ -301,24 +291,24 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn, char *ipv4_addrs_name = lr_lb_address_set_name(od->tunnel_key, AF_INET); - struct sorted_addresses ipv4_addrs_sorted = - sorted_addresses_from_sset(&od->lb_ips->ips_v4_reachable); + struct sorted_array ipv4_addrs_sorted = + sorted_array_from_sset(&od->lb_ips->ips_v4_reachable); sync_addr_set(ovnsb_txn, ipv4_addrs_name, &ipv4_addrs_sorted, &sb_address_sets); - free(ipv4_addrs_sorted.arr); + sorted_array_destroy(&ipv4_addrs_sorted); free(ipv4_addrs_name); } if (sset_count(&od->lb_ips->ips_v6_reachable)) { char *ipv6_addrs_name = lr_lb_address_set_name(od->tunnel_key, AF_INET6); - struct sorted_addresses ipv6_addrs_sorted = - sorted_addresses_from_sset(&od->lb_ips->ips_v6_reachable); + struct sorted_array ipv6_addrs_sorted = + sorted_array_from_sset(&od->lb_ips->ips_v6_reachable); sync_addr_set(ovnsb_txn, ipv6_addrs_name, &ipv6_addrs_sorted, &sb_address_sets); - free(ipv6_addrs_sorted.arr); + sorted_array_destroy(&ipv6_addrs_sorted); free(ipv6_addrs_name); } } @@ -328,10 +318,11 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn, const struct nbrec_address_set *nb_address_set; NBREC_ADDRESS_SET_TABLE_FOR_EACH (nb_address_set, nb_address_set_table) { - struct sorted_addresses addrs = - sorted_addresses_from_nbrec(nb_address_set); + struct sorted_array addrs = + sorted_array_from_dbrec(nb_address_set, addresses); sync_addr_set(ovnsb_txn, nb_address_set->name, &addrs, &sb_address_sets); + sorted_array_destroy(&addrs); } struct shash_node *node; @@ -343,39 +334,25 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn, } static void -update_sb_addr_set(struct sorted_addresses *nb_addresses, - const struct sbrec_address_set *sb_as) +sb_addr_set_apply_diff(const void *arg, const char *item, bool add) { - size_t nb_index, sb_index; - - const char **nb_arr = nb_addresses->arr; - char **sb_arr = sb_as->addresses; - size_t nb_n = nb_addresses->n; - size_t sb_n = sb_as->n_addresses; - - for (nb_index = sb_index = 0; nb_index < nb_n && sb_index < sb_n;) { - int cmp = strcmp(nb_arr[nb_index], sb_arr[sb_index]); - if (cmp < 0) { - sbrec_address_set_update_addresses_addvalue(sb_as, - nb_arr[nb_index]); - nb_index++; - } else if (cmp > 0) { - sbrec_address_set_update_addresses_delvalue(sb_as, - sb_arr[sb_index]); - sb_index++; - } else { - nb_index++; - sb_index++; - } - } - - for (; nb_index < nb_n; nb_index++) { - sbrec_address_set_update_addresses_addvalue(sb_as, nb_arr[nb_index]); + const struct sbrec_address_set *as = arg; + if (add) { + sbrec_address_set_update_addresses_addvalue(as, item); + } else { + sbrec_address_set_update_addresses_delvalue(as, item); } +} - for (; sb_index < sb_n; sb_index++) { - sbrec_address_set_update_addresses_delvalue(sb_as, sb_arr[sb_index]); - } +static void +update_sb_addr_set(struct sorted_array *nb_addresses, + const struct sbrec_address_set *sb_as) +{ + struct sorted_array sb_addresses = + sorted_array_from_dbrec(sb_as, addresses); + sorted_array_apply_diff(nb_addresses, &sb_addresses, + sb_addr_set_apply_diff, sb_as); + sorted_array_destroy(&sb_addresses); } static void @@ -414,32 +391,3 @@ sb_address_set_lookup_by_name(struct ovsdb_idl_index *sbrec_addr_set_by_name, return retval; } - -static struct sorted_addresses -sorted_addresses_from_nbrec(const struct nbrec_address_set *nb_as) -{ - /* The DB is already sorted. */ - return (struct sorted_addresses) { - .arr = (const char **) nb_as->addresses, - .n = nb_as->n_addresses, - }; -} - -static struct sorted_addresses -sorted_addresses_from_svec(struct svec *addresses) -{ - svec_sort(addresses); - return (struct sorted_addresses) { - .arr = (const char **) addresses->names, - .n = addresses->n, - }; -} - -static struct sorted_addresses -sorted_addresses_from_sset(struct sset *addresses) -{ - return (struct sorted_addresses) { - .arr = sset_sort(addresses), - .n = sset_count(addresses), - }; -} From patchwork Thu Aug 10 12:44:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1819842 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.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=NeVZxRX+; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RM68Q4mt1z1yYC for ; Thu, 10 Aug 2023 22:45:10 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id BB98383F9F; Thu, 10 Aug 2023 12:45:08 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org BB98383F9F 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=NeVZxRX+ 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 FHKN1z1lJM4b; Thu, 10 Aug 2023 12:45:06 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTPS id 0327F83F77; Thu, 10 Aug 2023 12:45:04 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 0327F83F77 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B3131C0072; Thu, 10 Aug 2023 12:45:04 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1C168C007F for ; Thu, 10 Aug 2023 12:45:03 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 9A89F41742 for ; Thu, 10 Aug 2023 12:44:55 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 9A89F41742 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=NeVZxRX+ 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 vYA4EZZPcnRb for ; Thu, 10 Aug 2023 12:44:54 +0000 (UTC) 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 1679C4174D for ; Thu, 10 Aug 2023 12:44:53 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1679C4174D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691671493; 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=152wmJgXXJj4OB7YGmO/revgHz9I1fqfp6q6RVhxXls=; b=NeVZxRX+Xovivvxh2DXHCfI5+hZ2CPeqnlxjeMqeCIFzUkxe3nD+DZWqMGtiVRjcpX/i61 K5q8jKnrpZFl43iCSnu9T9GgncgE2nKCM0+dUB15lZ0WJHfaIwOe8/Zdg+Jjd393bqnCJ1 QW+LqiUBzYOhLwzI+HBDu9fCEA3k5q0= Received: from mimecast-mx02.redhat.com (66.187.233.73 [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-654-WsVnc7c0OUq2NRP8p-Hnmg-1; Thu, 10 Aug 2023 08:44:51 -0400 X-MC-Unique: WsVnc7c0OUq2NRP8p-Hnmg-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 F2BFF28EA6F5; Thu, 10 Aug 2023 12:44:50 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.194.96]) by smtp.corp.redhat.com (Postfix) with ESMTP id 39EDB2166B25; Thu, 10 Aug 2023 12:44:49 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Thu, 10 Aug 2023 14:44:47 +0200 Message-Id: <169167148471.2447623.13612015239977748432.stgit@dceara.remote.csb> In-Reply-To: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> References: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn 2/5] northd: Merge port group related structures. 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" There's currently no need to store both 'ovn_ls_port_group' and 'ovn_port_group_ls' so just use the first type. Signed-off-by: Dumitru Ceara Acked-by: Ales Musil Acked-by: Han Zhou --- northd/en-lflow.c | 2 northd/northd.c | 286 +++++++++++++++++++++++++---------------------------- northd/northd.h | 25 ++++- 3 files changed, 158 insertions(+), 155 deletions(-) diff --git a/northd/en-lflow.c b/northd/en-lflow.c index 28ab1c67fb..7187cf959f 100644 --- a/northd/en-lflow.c +++ b/northd/en-lflow.c @@ -55,7 +55,7 @@ lflow_get_input_data(struct engine_node *node, lflow_input->lr_datapaths = &northd_data->lr_datapaths; lflow_input->ls_ports = &northd_data->ls_ports; lflow_input->lr_ports = &northd_data->lr_ports; - lflow_input->port_groups = &northd_data->port_groups; + lflow_input->ls_port_groups = &northd_data->ls_port_groups; lflow_input->meter_groups = &northd_data->meter_groups; lflow_input->lbs = &northd_data->lbs; lflow_input->features = &northd_data->features; diff --git a/northd/northd.c b/northd/northd.c index 9a12a94ae2..73fab3af7e 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -813,7 +813,6 @@ ovn_datapath_create(struct hmap *datapaths, const struct uuid *key, od->nbs = nbs; od->nbr = nbr; hmap_init(&od->port_tnlids); - hmap_init(&od->nb_pgs); od->port_key_hint = 0; hmap_insert(datapaths, &od->key_node, uuid_hash(&od->key)); od->lr_group = NULL; @@ -821,7 +820,6 @@ ovn_datapath_create(struct hmap *datapaths, const struct uuid *key, return od; } -static void ovn_ls_port_group_destroy(struct hmap *nb_pgs); static void destroy_mcast_info_for_datapath(struct ovn_datapath *od); static void @@ -849,7 +847,6 @@ ovn_datapath_destroy(struct hmap *datapaths, struct ovn_datapath *od) free(od->nat_entries); free(od->localnet_ports); free(od->l3dgw_ports); - ovn_ls_port_group_destroy(&od->nb_pgs); destroy_mcast_info_for_datapath(od); destroy_ports_for_datapath(od); @@ -6240,83 +6237,87 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip, return true; } -struct ovn_port_group_ls { - struct hmap_node key_node; /* Index on 'key'. */ - struct uuid key; /* nb_ls->header_.uuid. */ - struct ovn_datapath *od; - - struct ovn_port **ports; /* Ports in 'od' referrenced by the PG. */ - size_t n_ports; - size_t n_allocated_ports; -}; - -struct ovn_port_group { - struct hmap_node key_node; /* Index on 'key'. */ - struct uuid key; /* nb_pg->header_.uuid. */ - const struct nbrec_port_group *nb_pg; - struct hmap nb_lswitches; /* NB lswitches related to the port group */ -}; - -static struct ovn_port_group_ls * -ovn_port_group_ls_add(struct ovn_port_group *pg, struct ovn_datapath *od) +static struct ls_port_group_record * +ls_port_group_record_add(struct hmap *nb_pgs, + const struct nbrec_port_group *nb_pg, + const char *port_name) { - struct ovn_port_group_ls *pg_ls = xzalloc(sizeof *pg_ls); - pg_ls->key = od->nbs->header_.uuid; - pg_ls->od = od; - hmap_insert(&pg->nb_lswitches, &pg_ls->key_node, uuid_hash(&pg_ls->key)); - return pg_ls; -} + struct ls_port_group_record *ls_pg_rec = NULL; + size_t hash = uuid_hash(&nb_pg->header_.uuid); -static struct ovn_port_group_ls * -ovn_port_group_ls_find(struct ovn_port_group *pg, const struct uuid *ls_uuid) -{ - struct ovn_port_group_ls *pg_ls; - - HMAP_FOR_EACH_WITH_HASH (pg_ls, key_node, uuid_hash(ls_uuid), - &pg->nb_lswitches) { - if (uuid_equals(ls_uuid, &pg_ls->key)) { - return pg_ls; + HMAP_FOR_EACH_WITH_HASH (ls_pg_rec, key_node, hash, nb_pgs) { + if (ls_pg_rec->nb_pg == nb_pg) { + goto done; } } - return NULL; + + ls_pg_rec = xzalloc(sizeof *ls_pg_rec); + *ls_pg_rec = (struct ls_port_group_record) { + .nb_pg = nb_pg, + .ports = SSET_INITIALIZER(&ls_pg_rec->ports), + }; + hmap_insert(nb_pgs, &ls_pg_rec->key_node, hash); +done: + sset_add(&ls_pg_rec->ports, port_name); + return ls_pg_rec; } static void -ovn_port_group_ls_add_port(struct ovn_port_group_ls *pg_ls, - struct ovn_port *op) +ls_port_group_record_destroy(struct hmap *nb_pgs, + struct ls_port_group_record *ls_pg_rec) { - if (pg_ls->n_ports == pg_ls->n_allocated_ports) { - pg_ls->ports = x2nrealloc(pg_ls->ports, - &pg_ls->n_allocated_ports, - sizeof *pg_ls->ports); + if (ls_pg_rec) { + hmap_remove(nb_pgs, &ls_pg_rec->key_node); + sset_destroy(&ls_pg_rec->ports); + free(ls_pg_rec); } - pg_ls->ports[pg_ls->n_ports++] = op; } -struct ovn_ls_port_group { - struct hmap_node key_node; /* Index on 'key'. */ - struct uuid key; /* nb_pg->header_.uuid. */ - const struct nbrec_port_group *nb_pg; -}; -static void -ovn_ls_port_group_add(struct hmap *nb_pgs, - const struct nbrec_port_group *nb_pg) +static struct ls_port_group * +ls_port_group_create(struct hmap *ls_port_groups, + const struct nbrec_logical_switch *nbs, + const struct sbrec_datapath_binding *dp) { - struct ovn_ls_port_group *ls_pg = xzalloc(sizeof *ls_pg); - ls_pg->key = nb_pg->header_.uuid; - ls_pg->nb_pg = nb_pg; - hmap_insert(nb_pgs, &ls_pg->key_node, uuid_hash(&ls_pg->key)); + struct ls_port_group *ls_pg = xmalloc(sizeof *ls_pg); + + *ls_pg = (struct ls_port_group) { + .nbs = nbs, + .sb_datapath_key = dp->tunnel_key, + .nb_pgs = HMAP_INITIALIZER(&ls_pg->nb_pgs), + }; + hmap_insert(ls_port_groups, &ls_pg->key_node, + uuid_hash(&nbs->header_.uuid)); + return ls_pg; } static void -ovn_ls_port_group_destroy(struct hmap *nb_pgs) +ls_port_group_destroy(struct hmap *ls_port_groups, struct ls_port_group *ls_pg) { - struct ovn_ls_port_group *ls_pg; - HMAP_FOR_EACH_POP (ls_pg, key_node, nb_pgs) { + if (ls_pg) { + struct ls_port_group_record *ls_pg_rec; + HMAP_FOR_EACH_SAFE (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + ls_port_group_record_destroy(&ls_pg->nb_pgs, ls_pg_rec); + } + hmap_destroy(&ls_pg->nb_pgs); + hmap_remove(ls_port_groups, &ls_pg->key_node); free(ls_pg); } - hmap_destroy(nb_pgs); +} + +static struct ls_port_group * +ls_port_group_find(const struct hmap *ls_port_groups, + const struct nbrec_logical_switch *nbs) +{ + struct ls_port_group *ls_pg; + + HMAP_FOR_EACH_WITH_HASH (ls_pg, key_node, uuid_hash(&nbs->header_.uuid), + ls_port_groups) { + if (nbs == ls_pg->nbs) { + return ls_pg; + } + } + return NULL; } static bool @@ -6350,7 +6351,7 @@ od_set_acl_flags(struct ovn_datapath *od, struct nbrec_acl **acls, } static void -ls_get_acl_flags(struct ovn_datapath *od) +ls_get_acl_flags(struct ovn_datapath *od, const struct hmap *ls_port_groups) { od->has_acls = false; od->has_stateful_acl = false; @@ -6360,9 +6361,18 @@ ls_get_acl_flags(struct ovn_datapath *od) return; } - struct ovn_ls_port_group *ls_pg; - HMAP_FOR_EACH (ls_pg, key_node, &od->nb_pgs) { - if (od_set_acl_flags(od, ls_pg->nb_pg->acls, ls_pg->nb_pg->n_acls)) { + const struct ls_port_group *ls_pg; + + ls_pg = ls_port_group_find(ls_port_groups, od->nbs); + if (!ls_pg) { + return; + } + + + struct ls_port_group_record *ls_pg_rec; + HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + if (od_set_acl_flags(od, ls_pg_rec->nb_pg->acls, + ls_pg_rec->nb_pg->n_acls)) { return; } } @@ -6568,7 +6578,7 @@ build_stateless_filter(struct ovn_datapath *od, static void build_stateless_filters(struct ovn_datapath *od, - const struct hmap *port_groups, + const struct hmap *ls_port_groups, struct hmap *lflows) { for (size_t i = 0; i < od->nbs->n_acls; i++) { @@ -6578,21 +6588,26 @@ build_stateless_filters(struct ovn_datapath *od, } } - struct ovn_port_group *pg; - HMAP_FOR_EACH (pg, key_node, port_groups) { - if (ovn_port_group_ls_find(pg, &od->nbs->header_.uuid)) { - for (size_t i = 0; i < pg->nb_pg->n_acls; i++) { - const struct nbrec_acl *acl = pg->nb_pg->acls[i]; - if (!strcmp(acl->action, "allow-stateless")) { - build_stateless_filter(od, acl, lflows); - } + const struct ls_port_group *ls_pg = ls_port_group_find(ls_port_groups, + od->nbs); + if (!ls_pg) { + return; + } + + const struct ls_port_group_record *ls_pg_rec; + HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + for (size_t i = 0; i < ls_pg_rec->nb_pg->n_acls; i++) { + const struct nbrec_acl *acl = ls_pg_rec->nb_pg->acls[i]; + + if (!strcmp(acl->action, "allow-stateless")) { + build_stateless_filter(od, acl, lflows); } } } } static void -build_pre_acls(struct ovn_datapath *od, const struct hmap *port_groups, +build_pre_acls(struct ovn_datapath *od, const struct hmap *ls_port_groups, struct hmap *lflows) { /* Ingress and Egress Pre-ACL Table (Priority 0): Packets are @@ -6623,7 +6638,7 @@ build_pre_acls(struct ovn_datapath *od, const struct hmap *port_groups, } /* stateless filters always take precedence over stateful ACLs. */ - build_stateless_filters(od, port_groups, lflows); + build_stateless_filters(od, ls_port_groups, lflows); /* Ingress and Egress Pre-ACL Table (Priority 110). * @@ -6657,7 +6672,7 @@ build_pre_acls(struct ovn_datapath *od, const struct hmap *port_groups, } else if (od->has_lb_vip) { /* We'll build stateless filters if there are LB rules so that * the stateless flows are not tracked in pre-lb. */ - build_stateless_filters(od, port_groups, lflows); + build_stateless_filters(od, ls_port_groups, lflows); } } @@ -7218,33 +7233,6 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od, } } -static struct ovn_port_group * -ovn_port_group_create(struct hmap *pgs, - const struct nbrec_port_group *nb_pg) -{ - struct ovn_port_group *pg = xzalloc(sizeof *pg); - pg->key = nb_pg->header_.uuid; - pg->nb_pg = nb_pg; - hmap_init(&pg->nb_lswitches); - hmap_insert(pgs, &pg->key_node, uuid_hash(&pg->key)); - return pg; -} - -static void -ovn_port_group_destroy(struct hmap *pgs, struct ovn_port_group *pg) -{ - if (pg) { - hmap_remove(pgs, &pg->key_node); - struct ovn_port_group_ls *ls; - HMAP_FOR_EACH_POP (ls, key_node, &pg->nb_lswitches) { - free(ls->ports); - free(ls); - } - hmap_destroy(&pg->nb_lswitches); - free(pg); - } -} - static void copy_ra_to_sb(struct ovn_port *op, const char *address_mode); @@ -7316,13 +7304,12 @@ ovn_update_ipv6_options(struct hmap *lr_ports) static void build_port_group_lswitches( const struct nbrec_port_group_table *nbrec_port_group_table, - struct hmap *pgs, struct hmap *ls_ports) + struct hmap *ls_pgs, struct hmap *ls_ports) { - hmap_init(pgs); + hmap_init(ls_pgs); const struct nbrec_port_group *nb_pg; NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_pg, nbrec_port_group_table) { - struct ovn_port_group *pg = ovn_port_group_create(pgs, nb_pg); for (size_t i = 0; i < nb_pg->n_ports; i++) { struct ovn_port *op = ovn_port_find(ls_ports, nb_pg->ports[i]->name); @@ -7342,13 +7329,12 @@ build_port_group_lswitches( continue; } - struct ovn_port_group_ls *pg_ls = - ovn_port_group_ls_find(pg, &op->od->nbs->header_.uuid); - if (!pg_ls) { - pg_ls = ovn_port_group_ls_add(pg, op->od); - ovn_ls_port_group_add(&op->od->nb_pgs, nb_pg); + struct ls_port_group *ls_pg = + ls_port_group_find(ls_pgs, op->od->nbs); + if (!ls_pg) { + ls_pg = ls_port_group_create(ls_pgs, op->od->nbs, op->od->sb); } - ovn_port_group_ls_add_port(pg_ls, op); + ls_port_group_record_add(&ls_pg->nb_pgs, nb_pg, op->key); } } } @@ -7505,7 +7491,7 @@ build_acl_log_related_flows(struct ovn_datapath *od, struct hmap *lflows, static void build_acls(struct ovn_datapath *od, const struct chassis_features *features, - struct hmap *lflows, const struct hmap *port_groups, + struct hmap *lflows, const struct hmap *ls_port_groups, const struct shash *meter_groups) { const char *default_acl_action = default_acl_drop @@ -7691,11 +7677,15 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, features->ct_no_masked_label, meter_groups, &match, &actions); } - struct ovn_port_group *pg; - HMAP_FOR_EACH (pg, key_node, port_groups) { - if (ovn_port_group_ls_find(pg, &od->nbs->header_.uuid)) { - for (size_t i = 0; i < pg->nb_pg->n_acls; i++) { - const struct nbrec_acl *acl = pg->nb_pg->acls[i]; + + const struct ls_port_group *ls_pg = ls_port_group_find(ls_port_groups, + od->nbs); + if (ls_pg) { + const struct ls_port_group_record *ls_pg_rec; + HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + for (size_t i = 0; i < ls_pg_rec->nb_pg->n_acls; i++) { + const struct nbrec_acl *acl = ls_pg_rec->nb_pg->acls[i]; + build_acl_log_related_flows(od, lflows, acl, has_stateful, features->ct_no_masked_label, meter_groups, &match, &actions); @@ -9199,19 +9189,19 @@ build_lswitch_lflows_l2_unknown(struct ovn_datapath *od, * Ingress tables 3 through 10. Egress tables 0 through 7. */ static void build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od, - const struct hmap *port_groups, + const struct hmap *ls_port_groups, const struct chassis_features *features, struct hmap *lflows, const struct shash *meter_groups) { ovs_assert(od->nbs); - ls_get_acl_flags(od); + ls_get_acl_flags(od, ls_port_groups); - build_pre_acls(od, port_groups, lflows); + build_pre_acls(od, ls_port_groups, lflows); build_pre_lb(od, meter_groups, lflows); build_pre_stateful(od, features, lflows); build_acl_hints(od, features, lflows); - build_acls(od, features, lflows, port_groups, meter_groups); + build_acls(od, features, lflows, ls_port_groups, meter_groups); build_qos(od, lflows); build_stateful(od, features, lflows); build_lb_hairpin(od, lflows); @@ -15512,7 +15502,7 @@ struct lswitch_flow_build_info { const struct ovn_datapaths *lr_datapaths; const struct hmap *ls_ports; const struct hmap *lr_ports; - const struct hmap *port_groups; + const struct hmap *ls_port_groups; struct hmap *lflows; struct hmap *igmp_groups; const struct shash *meter_groups; @@ -15536,7 +15526,7 @@ build_lswitch_and_lrouter_iterate_by_ls(struct ovn_datapath *od, struct lswitch_flow_build_info *lsi) { ovs_assert(od->nbs); - build_lswitch_lflows_pre_acl_and_acl(od, lsi->port_groups, + build_lswitch_lflows_pre_acl_and_acl(od, lsi->ls_port_groups, lsi->features, lsi->lflows, lsi->meter_groups); @@ -15810,7 +15800,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths, const struct ovn_datapaths *lr_datapaths, const struct hmap *ls_ports, const struct hmap *lr_ports, - const struct hmap *port_groups, + const struct hmap *ls_port_groups, struct hmap *lflows, struct hmap *igmp_groups, const struct shash *meter_groups, @@ -15838,7 +15828,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths, lsiv[index].lr_datapaths = lr_datapaths; lsiv[index].ls_ports = ls_ports; lsiv[index].lr_ports = lr_ports; - lsiv[index].port_groups = port_groups; + lsiv[index].ls_port_groups = ls_port_groups; lsiv[index].igmp_groups = igmp_groups; lsiv[index].meter_groups = meter_groups; lsiv[index].lbs = lbs; @@ -15871,7 +15861,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths, .lr_datapaths = lr_datapaths, .ls_ports = ls_ports, .lr_ports = lr_ports, - .port_groups = port_groups, + .ls_port_groups = ls_port_groups, .lflows = lflows, .igmp_groups = igmp_groups, .meter_groups = meter_groups, @@ -16015,7 +16005,8 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn, input_data->lr_datapaths, input_data->ls_ports, input_data->lr_ports, - input_data->port_groups, lflows, + input_data->ls_port_groups, + lflows, &igmp_groups, input_data->meter_groups, input_data->lbs, input_data->bfd_connections, @@ -16562,7 +16553,7 @@ bool lflow_handle_northd_ls_changes(struct ovsdb_idl_txn *ovnsb_txn, static void sync_port_groups(struct ovsdb_idl_txn *ovnsb_txn, const struct sbrec_port_group_table *sbrec_port_group_table, - struct hmap *pgs) + struct hmap *ls_pgs) { struct shash sb_port_groups = SHASH_INITIALIZER(&sb_port_groups); @@ -16573,12 +16564,13 @@ sync_port_groups(struct ovsdb_idl_txn *ovnsb_txn, struct ds sb_name = DS_EMPTY_INITIALIZER; - struct ovn_port_group *pg; - HMAP_FOR_EACH (pg, key_node, pgs) { + struct ls_port_group *ls_pg; + HMAP_FOR_EACH (ls_pg, key_node, ls_pgs) { + struct ls_port_group_record *ls_pg_rec; - struct ovn_port_group_ls *pg_ls; - HMAP_FOR_EACH (pg_ls, key_node, &pg->nb_lswitches) { - get_sb_port_group_name(pg->nb_pg->name, pg_ls->od->sb->tunnel_key, + HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + get_sb_port_group_name(ls_pg_rec->nb_pg->name, + ls_pg->sb_datapath_key, &sb_name); sb_port_group = shash_find_and_delete(&sb_port_groups, ds_cstr(&sb_name)); @@ -16587,14 +16579,10 @@ sync_port_groups(struct ovsdb_idl_txn *ovnsb_txn, sbrec_port_group_set_name(sb_port_group, ds_cstr(&sb_name)); } - const char **nb_port_names = xcalloc(pg_ls->n_ports, - sizeof *nb_port_names); - for (size_t i = 0; i < pg_ls->n_ports; i++) { - nb_port_names[i] = pg_ls->ports[i]->nbsp->name; - } + const char **nb_port_names = sset_array(&ls_pg_rec->ports); sbrec_port_group_set_ports(sb_port_group, nb_port_names, - pg_ls->n_ports); + sset_count(&ls_pg_rec->ports)); free(nb_port_names); } } @@ -17418,7 +17406,7 @@ northd_init(struct northd_data *data) ovn_datapaths_init(&data->lr_datapaths); hmap_init(&data->ls_ports); hmap_init(&data->lr_ports); - hmap_init(&data->port_groups); + hmap_init(&data->ls_port_groups); shash_init(&data->meter_groups); hmap_init(&data->lbs); hmap_init(&data->lb_groups); @@ -17450,12 +17438,11 @@ northd_destroy(struct northd_data *data) } hmap_destroy(&data->lb_groups); - struct ovn_port_group *pg; - HMAP_FOR_EACH_SAFE (pg, key_node, &data->port_groups) { - ovn_port_group_destroy(&data->port_groups, pg); + struct ls_port_group *ls_pg; + HMAP_FOR_EACH_SAFE (ls_pg, key_node, &data->ls_port_groups) { + ls_port_group_destroy(&data->ls_port_groups, ls_pg); } - - hmap_destroy(&data->port_groups); + hmap_destroy(&data->ls_port_groups); struct shash_node *node; SHASH_FOR_EACH_SAFE (node, &data->meter_groups) { @@ -17596,7 +17583,8 @@ ovnnb_db_run(struct northd_input *input_data, ods_size(&data->lr_datapaths)); build_ipam(&data->ls_datapaths.datapaths, &data->ls_ports); build_port_group_lswitches(input_data->nbrec_port_group_table, - &data->port_groups, &data->ls_ports); + &data->ls_port_groups, + &data->ls_ports); build_lrouter_groups(&data->lr_ports, &data->lr_list); build_ip_mcast(ovnsb_txn, input_data->sbrec_ip_multicast_table, input_data->sbrec_ip_mcast_by_dp, @@ -17615,7 +17603,7 @@ ovnnb_db_run(struct northd_input *input_data, sync_lbs(ovnsb_txn, input_data->sbrec_load_balancer_table, &data->ls_datapaths, &data->lbs); sync_port_groups(ovnsb_txn, input_data->sbrec_port_group_table, - &data->port_groups); + &data->ls_port_groups); sync_meters(ovnsb_txn, input_data->nbrec_meter_table, input_data->nbrec_acl_table, input_data->sbrec_meter_table, &data->meter_groups); diff --git a/northd/northd.h b/northd/northd.h index f3e63b1e1a..38bc7f50f1 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -108,7 +108,7 @@ struct northd_data { struct ovn_datapaths lr_datapaths; struct hmap ls_ports; struct hmap lr_ports; - struct hmap port_groups; + struct hmap ls_port_groups; /* Stores struct ls_port_group. */ struct shash meter_groups; struct hmap lbs; struct hmap lb_groups; @@ -144,7 +144,7 @@ struct lflow_input { const struct ovn_datapaths *lr_datapaths; const struct hmap *ls_ports; const struct hmap *lr_ports; - const struct hmap *port_groups; + const struct hmap *ls_port_groups; const struct shash *meter_groups; const struct hmap *lbs; const struct hmap *bfd_connections; @@ -309,14 +309,29 @@ struct ovn_datapath { * Valid only if it is logical router datapath. NULL otherwise. */ struct lrouter_group *lr_group; - /* Port groups related to the datapath, used only when nbs is NOT NULL. */ - struct hmap nb_pgs; - /* Map of ovn_port objects belonging to this datapath. * This map doesn't include derived ports. */ struct hmap ports; }; +/* Per logical switch port group information. */ +struct ls_port_group { + struct hmap_node key_node; /* Index on 'nbs->header_.uuid'. */ + + const struct nbrec_logical_switch *nbs; + int64_t sb_datapath_key; /* SB.Datapath_Binding.tunnel_key. */ + + /* Port groups with ports attached to 'nbs'. */ + struct hmap nb_pgs; /* Stores struct ls_port_group_record. */ +}; + +struct ls_port_group_record { + struct hmap_node key_node; /* Index on 'nb_pg->header_.uuid'. */ + + const struct nbrec_port_group *nb_pg; + struct sset ports; /* Subset of 'nb_pg' ports in this record. */ +}; + void ovnnb_db_run(struct northd_input *input_data, struct northd_data *data, struct ovsdb_idl_txn *ovnnb_txn, From patchwork Thu Aug 10 12:44:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1819843 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.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=) Authentication-Results: legolas.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=ePQ+Q+7y; dkim-atps=neutral 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 ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RM68q2hf3z1yYC for ; Thu, 10 Aug 2023 22:45:31 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id CE40441B95; Thu, 10 Aug 2023 12:45:28 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org CE40441B95 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=ePQ+Q+7y 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 eHAWjGu4tpsE; Thu, 10 Aug 2023 12:45:26 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 11C1A41BBB; Thu, 10 Aug 2023 12:45:25 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 11C1A41BBB Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BF514C008D; Thu, 10 Aug 2023 12:45:24 +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 347E6C0072 for ; Thu, 10 Aug 2023 12:45:23 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 5898A83C12 for ; Thu, 10 Aug 2023 12:45:14 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 5898A83C12 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ePQ+Q+7y 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 ew9WxfzpaILP for ; Thu, 10 Aug 2023 12:45:12 +0000 (UTC) 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 4A24283FA9 for ; Thu, 10 Aug 2023 12:45:09 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 4A24283FA9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691671508; 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=QME81khy9HctfoLpX+OuU1z8QjOiy6swX7De0xRK7DY=; b=ePQ+Q+7yrfMJMFuFGcYkXFOoSubu+BcA8ScfzU0MaBZ7F/Qwh65M8Zv8ITeSUXvROtYc4k uz1aTLJokewpcUU+Z6WtWd1cJLoEsME6HXmOwotEi1SoweqRUxeuMounbiuzroXPfmbxxq bU9mdzrRh0NETXRgQpLMwOLFIxCNni4= Received: from mimecast-mx02.redhat.com (66.187.233.73 [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-537-93RzBaZSNSCnD6d2QzDYZQ-1; Thu, 10 Aug 2023 08:45:01 -0400 X-MC-Unique: 93RzBaZSNSCnD6d2QzDYZQ-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5E3091C068DC; Thu, 10 Aug 2023 12:45:01 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.194.96]) by smtp.corp.redhat.com (Postfix) with ESMTP id 17E8F40C2076; Thu, 10 Aug 2023 12:44:59 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Thu, 10 Aug 2023 14:44:58 +0200 Message-Id: <169167149634.2447623.7362496199433519342.stgit@dceara.remote.csb> In-Reply-To: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> References: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn 3/5] northd: Move port group processing to its separate module. 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" No functional differences in this commit, just abstract out the processing a bit. Signed-off-by: Dumitru Ceara Acked-by: Ales Musil Acked-by: Han Zhou --- northd/automake.mk | 2 northd/en-port-group.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++ northd/en-port-group.h | 63 ++++++++++++ northd/northd.c | 246 ++++++++---------------------------------------- northd/northd.h | 26 +---- 5 files changed, 350 insertions(+), 224 deletions(-) create mode 100644 northd/en-port-group.c create mode 100644 northd/en-port-group.h diff --git a/northd/automake.mk b/northd/automake.mk index b17f1fdb54..0fc634b4b4 100644 --- a/northd/automake.mk +++ b/northd/automake.mk @@ -14,6 +14,8 @@ northd_ovn_northd_SOURCES = \ northd/en-lflow.h \ northd/en-northd-output.c \ northd/en-northd-output.h \ + northd/en-port-group.c \ + northd/en-port-group.h \ northd/en-sync-sb.c \ northd/en-sync-sb.h \ northd/en-sync-from-sb.c \ diff --git a/northd/en-port-group.c b/northd/en-port-group.c new file mode 100644 index 0000000000..b83926c351 --- /dev/null +++ b/northd/en-port-group.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2023, 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 "openvswitch/vlog.h" + +#include "en-port-group.h" +#include "northd.h" + +VLOG_DEFINE_THIS_MODULE(en_port_group); + +static struct ls_port_group *ls_port_group_create( + struct ls_port_group_table *, + const struct nbrec_logical_switch *, + const struct sbrec_datapath_binding *); + +static void ls_port_group_destroy(struct ls_port_group_table *, + struct ls_port_group *); + +static struct ls_port_group_record *ls_port_group_record_add( + struct ls_port_group *, + const struct nbrec_port_group *, + const char *port_name); + +static void ls_port_group_record_destroy( + struct ls_port_group *, + struct ls_port_group_record *); + +void +ls_port_group_table_init(struct ls_port_group_table *table) +{ + *table = (struct ls_port_group_table) { + .entries = HMAP_INITIALIZER(&table->entries), + }; +} + +void +ls_port_group_table_clear(struct ls_port_group_table *table) +{ + struct ls_port_group *ls_pg; + HMAP_FOR_EACH_SAFE (ls_pg, key_node, &table->entries) { + ls_port_group_destroy(table, ls_pg); + } +} + +void +ls_port_group_table_destroy(struct ls_port_group_table *table) +{ + ls_port_group_table_clear(table); + hmap_destroy(&table->entries); +} + +struct ls_port_group * +ls_port_group_table_find(const struct ls_port_group_table *table, + const struct nbrec_logical_switch *nbs) +{ + struct ls_port_group *ls_pg; + + HMAP_FOR_EACH_WITH_HASH (ls_pg, key_node, uuid_hash(&nbs->header_.uuid), + &table->entries) { + if (nbs == ls_pg->nbs) { + return ls_pg; + } + } + return NULL; +} + +void +ls_port_group_table_build(struct ls_port_group_table *ls_port_groups, + const struct nbrec_port_group_table *pg_table, + const struct hmap *ls_ports) +{ + const struct nbrec_port_group *nb_pg; + NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_pg, pg_table) { + for (size_t i = 0; i < nb_pg->n_ports; i++) { + const char *port_name = nb_pg->ports[i]->name; + const struct ovn_datapath *od = + northd_get_datapath_for_port(ls_ports, port_name); + + if (!od) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_ERR_RL(&rl, "lport %s in port group %s not found.", + port_name, nb_pg->name); + continue; + } + + if (!od->nbs) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "lport %s in port group %s has no lswitch.", + nb_pg->ports[i]->name, + nb_pg->name); + continue; + } + + struct ls_port_group *ls_pg = + ls_port_group_table_find(ls_port_groups, od->nbs); + if (!ls_pg) { + ls_pg = ls_port_group_create(ls_port_groups, od->nbs, od->sb); + } + ls_port_group_record_add(ls_pg, nb_pg, port_name); + } + } +} + +/* Each port group in Port_Group table in OVN_Northbound has a corresponding + * entry in Port_Group table in OVN_Southbound. In OVN_Northbound the entries + * contains lport uuids, while in OVN_Southbound we store the lport names. + */ +void +ls_port_group_table_sync( + const struct ls_port_group_table *ls_port_groups, + const struct sbrec_port_group_table *sbrec_port_group_table, + struct ovsdb_idl_txn *ovnsb_txn) +{ + struct shash sb_port_groups = SHASH_INITIALIZER(&sb_port_groups); + + const struct sbrec_port_group *sb_port_group; + SBREC_PORT_GROUP_TABLE_FOR_EACH (sb_port_group, sbrec_port_group_table) { + shash_add(&sb_port_groups, sb_port_group->name, sb_port_group); + } + + struct ds sb_name = DS_EMPTY_INITIALIZER; + + struct ls_port_group *ls_pg; + HMAP_FOR_EACH (ls_pg, key_node, &ls_port_groups->entries) { + struct ls_port_group_record *ls_pg_rec; + + HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + get_sb_port_group_name(ls_pg_rec->nb_pg->name, + ls_pg->sb_datapath_key, + &sb_name); + sb_port_group = shash_find_and_delete(&sb_port_groups, + ds_cstr(&sb_name)); + if (!sb_port_group) { + sb_port_group = sbrec_port_group_insert(ovnsb_txn); + sbrec_port_group_set_name(sb_port_group, ds_cstr(&sb_name)); + } + + const char **nb_port_names = sset_array(&ls_pg_rec->ports); + sbrec_port_group_set_ports(sb_port_group, + nb_port_names, + sset_count(&ls_pg_rec->ports)); + free(nb_port_names); + } + } + ds_destroy(&sb_name); + + struct shash_node *node; + SHASH_FOR_EACH_SAFE (node, &sb_port_groups) { + sbrec_port_group_delete(node->data); + shash_delete(&sb_port_groups, node); + } + shash_destroy(&sb_port_groups); +} + +static struct ls_port_group * +ls_port_group_create(struct ls_port_group_table *ls_port_groups, + const struct nbrec_logical_switch *nbs, + const struct sbrec_datapath_binding *dp) +{ + struct ls_port_group *ls_pg = xmalloc(sizeof *ls_pg); + + *ls_pg = (struct ls_port_group) { + .nbs = nbs, + .sb_datapath_key = dp->tunnel_key, + .nb_pgs = HMAP_INITIALIZER(&ls_pg->nb_pgs), + }; + hmap_insert(&ls_port_groups->entries, &ls_pg->key_node, + uuid_hash(&nbs->header_.uuid)); + return ls_pg; +} + +static void +ls_port_group_destroy(struct ls_port_group_table *ls_port_groups, + struct ls_port_group *ls_pg) +{ + if (ls_pg) { + struct ls_port_group_record *ls_pg_rec; + HMAP_FOR_EACH_SAFE (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + ls_port_group_record_destroy(ls_pg, ls_pg_rec); + } + hmap_destroy(&ls_pg->nb_pgs); + hmap_remove(&ls_port_groups->entries, &ls_pg->key_node); + free(ls_pg); + } +} + +static struct ls_port_group_record * +ls_port_group_record_add(struct ls_port_group *ls_pg, + const struct nbrec_port_group *nb_pg, + const char *port_name) +{ + struct ls_port_group_record *ls_pg_rec = NULL; + size_t hash = uuid_hash(&nb_pg->header_.uuid); + + HMAP_FOR_EACH_WITH_HASH (ls_pg_rec, key_node, hash, &ls_pg->nb_pgs) { + if (ls_pg_rec->nb_pg == nb_pg) { + goto done; + } + } + + ls_pg_rec = xzalloc(sizeof *ls_pg_rec); + *ls_pg_rec = (struct ls_port_group_record) { + .nb_pg = nb_pg, + .ports = SSET_INITIALIZER(&ls_pg_rec->ports), + }; + hmap_insert(&ls_pg->nb_pgs, &ls_pg_rec->key_node, hash); +done: + sset_add(&ls_pg_rec->ports, port_name); + return ls_pg_rec; +} + +static void +ls_port_group_record_destroy(struct ls_port_group *ls_pg, + struct ls_port_group_record *ls_pg_rec) +{ + if (ls_pg_rec) { + hmap_remove(&ls_pg->nb_pgs, &ls_pg_rec->key_node); + sset_destroy(&ls_pg_rec->ports); + free(ls_pg_rec); + } +} + diff --git a/northd/en-port-group.h b/northd/en-port-group.h new file mode 100644 index 0000000000..2c8e01f51f --- /dev/null +++ b/northd/en-port-group.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023, 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 EN_PORT_GROUP_H +#define EN_PORT_GROUP_H 1 + +#include + +#include "lib/inc-proc-eng.h" +#include "lib/ovn-nb-idl.h" +#include "lib/ovn-sb-idl.h" +#include "openvswitch/hmap.h" + +#include "sset.h" + +/* Per logical switch port group information. */ +struct ls_port_group_table { + struct hmap entries; /* Stores struct ls_port_group. */ +}; + +struct ls_port_group { + struct hmap_node key_node; /* Index on 'nbs->header_.uuid'. */ + + const struct nbrec_logical_switch *nbs; + int64_t sb_datapath_key; /* SB.Datapath_Binding.tunnel_key. */ + + /* Port groups with ports attached to 'nbs'. */ + struct hmap nb_pgs; /* Stores struct ls_port_group_record. */ +}; + +struct ls_port_group_record { + struct hmap_node key_node; /* Index on 'nb_pg->header_.uuid'. */ + + const struct nbrec_port_group *nb_pg; + struct sset ports; /* Subset of 'nb_pg' ports in this record. */ +}; + +void ls_port_group_table_init(struct ls_port_group_table *); +void ls_port_group_table_clear(struct ls_port_group_table *); +void ls_port_group_table_destroy(struct ls_port_group_table *); +struct ls_port_group *ls_port_group_table_find( + const struct ls_port_group_table *, + const struct nbrec_logical_switch *); + +void ls_port_group_table_build(struct ls_port_group_table *ls_port_groups, + const struct nbrec_port_group_table *, + const struct hmap *ls_ports); +void ls_port_group_table_sync(const struct ls_port_group_table *ls_port_groups, + const struct sbrec_port_group_table *, + struct ovsdb_idl_txn *ovnsb_txn); +#endif /* EN_PORT_GROUP_H */ diff --git a/northd/northd.c b/northd/northd.c index 73fab3af7e..04da75fa96 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -21,6 +21,7 @@ #include "bitmap.h" #include "coverage.h" #include "dirs.h" +#include "en-port-group.h" #include "ipam.h" #include "openvswitch/dynamic-string.h" #include "hash.h" @@ -6237,89 +6238,6 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip, return true; } -static struct ls_port_group_record * -ls_port_group_record_add(struct hmap *nb_pgs, - const struct nbrec_port_group *nb_pg, - const char *port_name) -{ - struct ls_port_group_record *ls_pg_rec = NULL; - size_t hash = uuid_hash(&nb_pg->header_.uuid); - - HMAP_FOR_EACH_WITH_HASH (ls_pg_rec, key_node, hash, nb_pgs) { - if (ls_pg_rec->nb_pg == nb_pg) { - goto done; - } - } - - ls_pg_rec = xzalloc(sizeof *ls_pg_rec); - *ls_pg_rec = (struct ls_port_group_record) { - .nb_pg = nb_pg, - .ports = SSET_INITIALIZER(&ls_pg_rec->ports), - }; - hmap_insert(nb_pgs, &ls_pg_rec->key_node, hash); -done: - sset_add(&ls_pg_rec->ports, port_name); - return ls_pg_rec; -} - -static void -ls_port_group_record_destroy(struct hmap *nb_pgs, - struct ls_port_group_record *ls_pg_rec) -{ - if (ls_pg_rec) { - hmap_remove(nb_pgs, &ls_pg_rec->key_node); - sset_destroy(&ls_pg_rec->ports); - free(ls_pg_rec); - } -} - - -static struct ls_port_group * -ls_port_group_create(struct hmap *ls_port_groups, - const struct nbrec_logical_switch *nbs, - const struct sbrec_datapath_binding *dp) -{ - struct ls_port_group *ls_pg = xmalloc(sizeof *ls_pg); - - *ls_pg = (struct ls_port_group) { - .nbs = nbs, - .sb_datapath_key = dp->tunnel_key, - .nb_pgs = HMAP_INITIALIZER(&ls_pg->nb_pgs), - }; - hmap_insert(ls_port_groups, &ls_pg->key_node, - uuid_hash(&nbs->header_.uuid)); - return ls_pg; -} - -static void -ls_port_group_destroy(struct hmap *ls_port_groups, struct ls_port_group *ls_pg) -{ - if (ls_pg) { - struct ls_port_group_record *ls_pg_rec; - HMAP_FOR_EACH_SAFE (ls_pg_rec, key_node, &ls_pg->nb_pgs) { - ls_port_group_record_destroy(&ls_pg->nb_pgs, ls_pg_rec); - } - hmap_destroy(&ls_pg->nb_pgs); - hmap_remove(ls_port_groups, &ls_pg->key_node); - free(ls_pg); - } -} - -static struct ls_port_group * -ls_port_group_find(const struct hmap *ls_port_groups, - const struct nbrec_logical_switch *nbs) -{ - struct ls_port_group *ls_pg; - - HMAP_FOR_EACH_WITH_HASH (ls_pg, key_node, uuid_hash(&nbs->header_.uuid), - ls_port_groups) { - if (nbs == ls_pg->nbs) { - return ls_pg; - } - } - return NULL; -} - static bool od_set_acl_flags(struct ovn_datapath *od, struct nbrec_acl **acls, size_t n_acls) @@ -6351,7 +6269,8 @@ od_set_acl_flags(struct ovn_datapath *od, struct nbrec_acl **acls, } static void -ls_get_acl_flags(struct ovn_datapath *od, const struct hmap *ls_port_groups) +ls_get_acl_flags(struct ovn_datapath *od, + const struct ls_port_group_table *ls_port_groups) { od->has_acls = false; od->has_stateful_acl = false; @@ -6361,15 +6280,13 @@ ls_get_acl_flags(struct ovn_datapath *od, const struct hmap *ls_port_groups) return; } - const struct ls_port_group *ls_pg; - - ls_pg = ls_port_group_find(ls_port_groups, od->nbs); + const struct ls_port_group *ls_pg = + ls_port_group_table_find(ls_port_groups, od->nbs); if (!ls_pg) { return; } - - struct ls_port_group_record *ls_pg_rec; + const struct ls_port_group_record *ls_pg_rec; HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { if (od_set_acl_flags(od, ls_pg_rec->nb_pg->acls, ls_pg_rec->nb_pg->n_acls)) { @@ -6578,7 +6495,7 @@ build_stateless_filter(struct ovn_datapath *od, static void build_stateless_filters(struct ovn_datapath *od, - const struct hmap *ls_port_groups, + const struct ls_port_group_table *ls_port_groups, struct hmap *lflows) { for (size_t i = 0; i < od->nbs->n_acls; i++) { @@ -6588,8 +6505,8 @@ build_stateless_filters(struct ovn_datapath *od, } } - const struct ls_port_group *ls_pg = ls_port_group_find(ls_port_groups, - od->nbs); + const struct ls_port_group *ls_pg = + ls_port_group_table_find(ls_port_groups, od->nbs); if (!ls_pg) { return; } @@ -6607,7 +6524,8 @@ build_stateless_filters(struct ovn_datapath *od, } static void -build_pre_acls(struct ovn_datapath *od, const struct hmap *ls_port_groups, +build_pre_acls(struct ovn_datapath *od, + const struct ls_port_group_table *ls_port_groups, struct hmap *lflows) { /* Ingress and Egress Pre-ACL Table (Priority 0): Packets are @@ -7301,44 +7219,6 @@ ovn_update_ipv6_options(struct hmap *lr_ports) } } -static void -build_port_group_lswitches( - const struct nbrec_port_group_table *nbrec_port_group_table, - struct hmap *ls_pgs, struct hmap *ls_ports) -{ - hmap_init(ls_pgs); - - const struct nbrec_port_group *nb_pg; - NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_pg, nbrec_port_group_table) { - for (size_t i = 0; i < nb_pg->n_ports; i++) { - struct ovn_port *op = ovn_port_find(ls_ports, - nb_pg->ports[i]->name); - if (!op) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_ERR_RL(&rl, "lport %s in port group %s not found.", - nb_pg->ports[i]->name, - nb_pg->name); - continue; - } - - if (!op->od->nbs) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "lport %s in port group %s has no lswitch.", - nb_pg->ports[i]->name, - nb_pg->name); - continue; - } - - struct ls_port_group *ls_pg = - ls_port_group_find(ls_pgs, op->od->nbs); - if (!ls_pg) { - ls_pg = ls_port_group_create(ls_pgs, op->od->nbs, op->od->sb); - } - ls_port_group_record_add(&ls_pg->nb_pgs, nb_pg, op->key); - } - } -} - #define IPV6_CT_OMIT_MATCH "nd || nd_ra || nd_rs || mldv1 || mldv2" static void @@ -7491,7 +7371,8 @@ build_acl_log_related_flows(struct ovn_datapath *od, struct hmap *lflows, static void build_acls(struct ovn_datapath *od, const struct chassis_features *features, - struct hmap *lflows, const struct hmap *ls_port_groups, + struct hmap *lflows, + const struct ls_port_group_table *ls_port_groups, const struct shash *meter_groups) { const char *default_acl_action = default_acl_drop @@ -7678,8 +7559,8 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features, meter_groups, &match, &actions); } - const struct ls_port_group *ls_pg = ls_port_group_find(ls_port_groups, - od->nbs); + const struct ls_port_group *ls_pg = + ls_port_group_table_find(ls_port_groups, od->nbs); if (ls_pg) { const struct ls_port_group_record *ls_pg_rec; HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { @@ -9188,11 +9069,12 @@ build_lswitch_lflows_l2_unknown(struct ovn_datapath *od, /* Build pre-ACL and ACL tables for both ingress and egress. * Ingress tables 3 through 10. Egress tables 0 through 7. */ static void -build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od, - const struct hmap *ls_port_groups, - const struct chassis_features *features, - struct hmap *lflows, - const struct shash *meter_groups) +build_lswitch_lflows_pre_acl_and_acl( + struct ovn_datapath *od, + const struct ls_port_group_table *ls_port_groups, + const struct chassis_features *features, + struct hmap *lflows, + const struct shash *meter_groups) { ovs_assert(od->nbs); ls_get_acl_flags(od, ls_port_groups); @@ -15502,7 +15384,7 @@ struct lswitch_flow_build_info { const struct ovn_datapaths *lr_datapaths; const struct hmap *ls_ports; const struct hmap *lr_ports; - const struct hmap *ls_port_groups; + const struct ls_port_group_table *ls_port_groups; struct hmap *lflows; struct hmap *igmp_groups; const struct shash *meter_groups; @@ -15800,7 +15682,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths, const struct ovn_datapaths *lr_datapaths, const struct hmap *ls_ports, const struct hmap *lr_ports, - const struct hmap *ls_port_groups, + const struct ls_port_group_table *ls_pgs, struct hmap *lflows, struct hmap *igmp_groups, const struct shash *meter_groups, @@ -15828,7 +15710,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths, lsiv[index].lr_datapaths = lr_datapaths; lsiv[index].ls_ports = ls_ports; lsiv[index].lr_ports = lr_ports; - lsiv[index].ls_port_groups = ls_port_groups; + lsiv[index].ls_port_groups = ls_pgs; lsiv[index].igmp_groups = igmp_groups; lsiv[index].meter_groups = meter_groups; lsiv[index].lbs = lbs; @@ -15861,7 +15743,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths, .lr_datapaths = lr_datapaths, .ls_ports = ls_ports, .lr_ports = lr_ports, - .ls_port_groups = ls_port_groups, + .ls_port_groups = ls_pgs, .lflows = lflows, .igmp_groups = igmp_groups, .meter_groups = meter_groups, @@ -16546,56 +16428,6 @@ bool lflow_handle_northd_ls_changes(struct ovsdb_idl_txn *ovnsb_txn, } -/* Each port group in Port_Group table in OVN_Northbound has a corresponding - * entry in Port_Group table in OVN_Southbound. In OVN_Northbound the entries - * contains lport uuids, while in OVN_Southbound we store the lport names. - */ -static void -sync_port_groups(struct ovsdb_idl_txn *ovnsb_txn, - const struct sbrec_port_group_table *sbrec_port_group_table, - struct hmap *ls_pgs) -{ - struct shash sb_port_groups = SHASH_INITIALIZER(&sb_port_groups); - - const struct sbrec_port_group *sb_port_group; - SBREC_PORT_GROUP_TABLE_FOR_EACH (sb_port_group, sbrec_port_group_table) { - shash_add(&sb_port_groups, sb_port_group->name, sb_port_group); - } - - struct ds sb_name = DS_EMPTY_INITIALIZER; - - struct ls_port_group *ls_pg; - HMAP_FOR_EACH (ls_pg, key_node, ls_pgs) { - struct ls_port_group_record *ls_pg_rec; - - HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { - get_sb_port_group_name(ls_pg_rec->nb_pg->name, - ls_pg->sb_datapath_key, - &sb_name); - sb_port_group = shash_find_and_delete(&sb_port_groups, - ds_cstr(&sb_name)); - if (!sb_port_group) { - sb_port_group = sbrec_port_group_insert(ovnsb_txn); - sbrec_port_group_set_name(sb_port_group, ds_cstr(&sb_name)); - } - - const char **nb_port_names = sset_array(&ls_pg_rec->ports); - sbrec_port_group_set_ports(sb_port_group, - nb_port_names, - sset_count(&ls_pg_rec->ports)); - free(nb_port_names); - } - } - ds_destroy(&sb_name); - - struct shash_node *node; - SHASH_FOR_EACH_SAFE (node, &sb_port_groups) { - sbrec_port_group_delete(node->data); - shash_delete(&sb_port_groups, node); - } - shash_destroy(&sb_port_groups); -} - struct band_entry { int64_t rate; int64_t burst_size; @@ -17406,7 +17238,7 @@ northd_init(struct northd_data *data) ovn_datapaths_init(&data->lr_datapaths); hmap_init(&data->ls_ports); hmap_init(&data->lr_ports); - hmap_init(&data->ls_port_groups); + ls_port_group_table_init(&data->ls_port_groups); shash_init(&data->meter_groups); hmap_init(&data->lbs); hmap_init(&data->lb_groups); @@ -17438,11 +17270,7 @@ northd_destroy(struct northd_data *data) } hmap_destroy(&data->lb_groups); - struct ls_port_group *ls_pg; - HMAP_FOR_EACH_SAFE (ls_pg, key_node, &data->ls_port_groups) { - ls_port_group_destroy(&data->ls_port_groups, ls_pg); - } - hmap_destroy(&data->ls_port_groups); + ls_port_group_table_destroy(&data->ls_port_groups); struct shash_node *node; SHASH_FOR_EACH_SAFE (node, &data->meter_groups) { @@ -17582,9 +17410,9 @@ ovnnb_db_run(struct northd_input *input_data, ods_size(&data->ls_datapaths), ods_size(&data->lr_datapaths)); build_ipam(&data->ls_datapaths.datapaths, &data->ls_ports); - build_port_group_lswitches(input_data->nbrec_port_group_table, - &data->ls_port_groups, - &data->ls_ports); + ls_port_group_table_build(&data->ls_port_groups, + input_data->nbrec_port_group_table, + &data->ls_ports); build_lrouter_groups(&data->lr_ports, &data->lr_list); build_ip_mcast(ovnsb_txn, input_data->sbrec_ip_multicast_table, input_data->sbrec_ip_mcast_by_dp, @@ -17602,8 +17430,9 @@ ovnnb_db_run(struct northd_input *input_data, sync_lbs(ovnsb_txn, input_data->sbrec_load_balancer_table, &data->ls_datapaths, &data->lbs); - sync_port_groups(ovnsb_txn, input_data->sbrec_port_group_table, - &data->ls_port_groups); + ls_port_group_table_sync(&data->ls_port_groups, + input_data->sbrec_port_group_table, + ovnsb_txn); sync_meters(ovnsb_txn, input_data->nbrec_meter_table, input_data->nbrec_acl_table, input_data->sbrec_meter_table, &data->meter_groups); @@ -17898,3 +17727,12 @@ northd_get_svc_monitor_mac(void) { return svc_monitor_mac; } + +const struct ovn_datapath * +northd_get_datapath_for_port(const struct hmap *ls_ports, + const char *port_name) +{ + const struct ovn_port *op = ovn_port_find(ls_ports, port_name); + + return op ? op->od : NULL; +} diff --git a/northd/northd.h b/northd/northd.h index 38bc7f50f1..da93a7c6a5 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -19,6 +19,7 @@ #include "lib/ovn-util.h" #include "lib/ovs-atomic.h" #include "lib/sset.h" +#include "northd/en-port-group.h" #include "northd/ipam.h" #include "openvswitch/hmap.h" @@ -108,7 +109,7 @@ struct northd_data { struct ovn_datapaths lr_datapaths; struct hmap ls_ports; struct hmap lr_ports; - struct hmap ls_port_groups; /* Stores struct ls_port_group. */ + struct ls_port_group_table ls_port_groups; struct shash meter_groups; struct hmap lbs; struct hmap lb_groups; @@ -144,7 +145,7 @@ struct lflow_input { const struct ovn_datapaths *lr_datapaths; const struct hmap *ls_ports; const struct hmap *lr_ports; - const struct hmap *ls_port_groups; + const struct ls_port_group_table *ls_port_groups; const struct shash *meter_groups; const struct hmap *lbs; const struct hmap *bfd_connections; @@ -314,24 +315,6 @@ struct ovn_datapath { struct hmap ports; }; -/* Per logical switch port group information. */ -struct ls_port_group { - struct hmap_node key_node; /* Index on 'nbs->header_.uuid'. */ - - const struct nbrec_logical_switch *nbs; - int64_t sb_datapath_key; /* SB.Datapath_Binding.tunnel_key. */ - - /* Port groups with ports attached to 'nbs'. */ - struct hmap nb_pgs; /* Stores struct ls_port_group_record. */ -}; - -struct ls_port_group_record { - struct hmap_node key_node; /* Index on 'nb_pg->header_.uuid'. */ - - const struct nbrec_port_group *nb_pg; - struct sset ports; /* Subset of 'nb_pg' ports in this record. */ -}; - void ovnnb_db_run(struct northd_input *input_data, struct northd_data *data, struct ovsdb_idl_txn *ovnnb_txn, @@ -369,4 +352,7 @@ void bfd_cleanup_connections(const struct nbrec_bfd_table *, void run_update_worker_pool(int n_threads); const char *northd_get_svc_monitor_mac(void); + +const struct ovn_datapath *northd_get_datapath_for_port( + const struct hmap *ls_ports, const char *port_name); #endif /* NORTHD_H */ From patchwork Thu Aug 10 12:45:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1819844 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.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=DeM/1ZQ/; dkim-atps=neutral Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RM68t1N14z1yYC for ; Thu, 10 Aug 2023 22:45:34 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 67FF141BBE; Thu, 10 Aug 2023 12:45:32 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 67FF141BBE 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=DeM/1ZQ/ 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 ZkIrfbrA0eIm; Thu, 10 Aug 2023 12:45:29 +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 2A1C041BAF; Thu, 10 Aug 2023 12:45:28 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 2A1C041BAF Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D37FDC008D; Thu, 10 Aug 2023 12:45:27 +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 3890BC008D for ; Thu, 10 Aug 2023 12:45:26 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 18CA76124B for ; Thu, 10 Aug 2023 12:45:18 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 18CA76124B 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=DeM/1ZQ/ 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 Ow916WS3HqBD for ; Thu, 10 Aug 2023 12:45:17 +0000 (UTC) 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 C8792611DD for ; Thu, 10 Aug 2023 12:45:16 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org C8792611DD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691671515; 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=ApmKY0xxTvAOSH2635bLakEXScDsiNWfVPIfxpa1Oes=; b=DeM/1ZQ/UbNqvVFkC3fZgV2+04fOVkqEZOcAAK2e2FJ4G5mYFD4CZRU0VEzar4RyqUEwvb ZoN3CA+ET2VBW9KmeRqTPT6aWy7EyLgnVjnXkJ/Wpg055l2naXIM2qVXTImePJSYvbemHA LpMEtSLMk9uz8QVeKfR85CmNn+Lpet4= 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-642-dKwuccfEMMWd_6QGSH8CFA-1; Thu, 10 Aug 2023 08:45:12 -0400 X-MC-Unique: dKwuccfEMMWd_6QGSH8CFA-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3059E185A792; Thu, 10 Aug 2023 12:45:12 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.194.96]) by smtp.corp.redhat.com (Postfix) with ESMTP id D6F8D568F7; Thu, 10 Aug 2023 12:45:10 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Thu, 10 Aug 2023 14:45:08 +0200 Message-Id: <169167150658.2447623.16064515466507285336.stgit@dceara.remote.csb> In-Reply-To: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> References: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.5 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn 4/5] northd: Move port group processing to its own I-P node. 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" For now it's still a node recompute for every port group change. It doesn't trigger northd recompute anymore though. A follow up commit will add incremental processing of NB.Port_Group changes. Signed-off-by: Dumitru Ceara Acked-by: Ales Musil Acked-by: Han Zhou --- lib/stopwatch-names.h | 1 + northd/en-lflow.c | 4 ++- northd/en-northd.c | 4 --- northd/en-port-group.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ northd/en-port-group.h | 21 +++++++++++++++++ northd/inc-proc-northd.c | 15 ++++++++++-- northd/northd.c | 9 ------- northd/northd.h | 3 -- tests/ovn-northd.at | 8 ++----- 9 files changed, 96 insertions(+), 25 deletions(-) diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index de6fca4ccc..08cb0159a7 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -30,5 +30,6 @@ #define LFLOWS_IGMP_STOPWATCH_NAME "lflows_igmp" #define LFLOWS_DP_GROUPS_STOPWATCH_NAME "lflows_dp_groups" #define LFLOWS_TO_SB_STOPWATCH_NAME "lflows_to_sb" +#define PORT_GROUP_RUN_STOPWATCH_NAME "port_group_run" #endif diff --git a/northd/en-lflow.c b/northd/en-lflow.c index 7187cf959f..7f6a7872b2 100644 --- a/northd/en-lflow.c +++ b/northd/en-lflow.c @@ -35,6 +35,8 @@ lflow_get_input_data(struct engine_node *node, struct lflow_input *lflow_input) { struct northd_data *northd_data = engine_get_input_data("northd", node); + struct port_group_data *pg_data = + engine_get_input_data("port_group", node); lflow_input->nbrec_bfd_table = EN_OVSDB_GET(engine_get_input("NB_bfd", node)); lflow_input->sbrec_bfd_table = @@ -55,7 +57,7 @@ lflow_get_input_data(struct engine_node *node, lflow_input->lr_datapaths = &northd_data->lr_datapaths; lflow_input->ls_ports = &northd_data->ls_ports; lflow_input->lr_ports = &northd_data->lr_ports; - lflow_input->ls_port_groups = &northd_data->ls_port_groups; + lflow_input->ls_port_groups = &pg_data->ls_port_groups; lflow_input->meter_groups = &northd_data->meter_groups; lflow_input->lbs = &northd_data->lbs; lflow_input->features = &northd_data->features; diff --git a/northd/en-northd.c b/northd/en-northd.c index 044fa70190..6fb0597144 100644 --- a/northd/en-northd.c +++ b/northd/en-northd.c @@ -74,8 +74,6 @@ northd_get_input_data(struct engine_node *node, EN_OVSDB_GET(engine_get_input("NB_load_balancer", node)); input_data->nbrec_load_balancer_group_table = EN_OVSDB_GET(engine_get_input("NB_load_balancer_group", node)); - input_data->nbrec_port_group_table = - EN_OVSDB_GET(engine_get_input("NB_port_group", node)); input_data->nbrec_meter_table = EN_OVSDB_GET(engine_get_input("NB_meter", node)); input_data->nbrec_acl_table = @@ -105,8 +103,6 @@ northd_get_input_data(struct engine_node *node, EN_OVSDB_GET(engine_get_input("SB_load_balancer", node)); input_data->sbrec_service_monitor_table = EN_OVSDB_GET(engine_get_input("SB_service_monitor", node)); - input_data->sbrec_port_group_table = - EN_OVSDB_GET(engine_get_input("SB_port_group", node)); input_data->sbrec_meter_table = EN_OVSDB_GET(engine_get_input("SB_meter", node)); input_data->sbrec_dns_table = diff --git a/northd/en-port-group.c b/northd/en-port-group.c index b83926c351..2c36410246 100644 --- a/northd/en-port-group.c +++ b/northd/en-port-group.c @@ -17,8 +17,10 @@ #include #include "openvswitch/vlog.h" +#include "stopwatch.h" #include "en-port-group.h" +#include "lib/stopwatch-names.h" #include "northd.h" VLOG_DEFINE_THIS_MODULE(en_port_group); @@ -235,3 +237,57 @@ ls_port_group_record_destroy(struct ls_port_group *ls_pg, } } +/* Incremental processing implementation. */ +static struct port_group_input +port_group_get_input_data(struct engine_node *node) +{ + struct northd_data *northd_data = engine_get_input_data("northd", node); + + return (struct port_group_input) { + .nbrec_port_group_table = + EN_OVSDB_GET(engine_get_input("NB_port_group", node)), + .sbrec_port_group_table = + EN_OVSDB_GET(engine_get_input("SB_port_group", node)), + .ls_ports = &northd_data->ls_ports, + }; +} + +void * +en_port_group_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct port_group_data *pg_data = xmalloc(sizeof *pg_data); + + ls_port_group_table_init(&pg_data->ls_port_groups); + return pg_data; +} + +void +en_port_group_cleanup(void *data_) +{ + struct port_group_data *data = data_; + + ls_port_group_table_destroy(&data->ls_port_groups); +} + +void +en_port_group_run(struct engine_node *node, void *data_) +{ + const struct engine_context *eng_ctx = engine_get_context(); + struct port_group_input input_data = port_group_get_input_data(node); + struct port_group_data *data = data_; + + stopwatch_start(PORT_GROUP_RUN_STOPWATCH_NAME, time_msec()); + + ls_port_group_table_clear(&data->ls_port_groups); + ls_port_group_table_build(&data->ls_port_groups, + input_data.nbrec_port_group_table, + input_data.ls_ports); + + ls_port_group_table_sync(&data->ls_port_groups, + input_data.sbrec_port_group_table, + eng_ctx->ovnsb_idl_txn); + + stopwatch_stop(PORT_GROUP_RUN_STOPWATCH_NAME, time_msec()); + engine_set_node_state(node, EN_UPDATED); +} diff --git a/northd/en-port-group.h b/northd/en-port-group.h index 2c8e01f51f..5cbf6c6c4a 100644 --- a/northd/en-port-group.h +++ b/northd/en-port-group.h @@ -60,4 +60,25 @@ void ls_port_group_table_build(struct ls_port_group_table *ls_port_groups, void ls_port_group_table_sync(const struct ls_port_group_table *ls_port_groups, const struct sbrec_port_group_table *, struct ovsdb_idl_txn *ovnsb_txn); + +/* Incremental processing implementation. */ +struct port_group_input { + /* Northbound table references. */ + const struct nbrec_port_group_table *nbrec_port_group_table; + + /* Southbound table references. */ + const struct sbrec_port_group_table *sbrec_port_group_table; + + /* northd node references. */ + const struct hmap *ls_ports; +}; + +struct port_group_data { + struct ls_port_group_table ls_port_groups; +}; + +void *en_port_group_init(struct engine_node *, struct engine_arg *); +void en_port_group_cleanup(void *data); +void en_port_group_run(struct engine_node *, void *data); + #endif /* EN_PORT_GROUP_H */ diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index d328deb222..6d5f9e8d16 100644 --- a/northd/inc-proc-northd.c +++ b/northd/inc-proc-northd.c @@ -137,6 +137,7 @@ static ENGINE_NODE(mac_binding_aging_waker, "mac_binding_aging_waker"); static ENGINE_NODE(northd_output, "northd_output"); static ENGINE_NODE(sync_to_sb, "sync_to_sb"); static ENGINE_NODE(sync_to_sb_addr_set, "sync_to_sb_addr_set"); +static ENGINE_NODE(port_group, "port_group"); static ENGINE_NODE(fdb_aging, "fdb_aging"); static ENGINE_NODE(fdb_aging_waker, "fdb_aging_waker"); @@ -145,7 +146,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, { /* Define relationships between nodes where first argument is dependent * on the second argument */ - engine_add_input(&en_northd, &en_nb_port_group, NULL); engine_add_input(&en_northd, &en_nb_load_balancer, NULL); engine_add_input(&en_northd, &en_nb_load_balancer_group, NULL); engine_add_input(&en_northd, &en_nb_acl, NULL); @@ -157,7 +157,6 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_northd, &en_sb_sb_global, NULL); engine_add_input(&en_northd, &en_sb_chassis, NULL); - engine_add_input(&en_northd, &en_sb_port_group, NULL); engine_add_input(&en_northd, &en_sb_mirror, NULL); engine_add_input(&en_northd, &en_sb_meter, NULL); engine_add_input(&en_northd, &en_sb_datapath_binding, NULL); @@ -194,6 +193,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_lflow, &en_sb_multicast_group, NULL); engine_add_input(&en_lflow, &en_sb_igmp_group, NULL); engine_add_input(&en_lflow, &en_northd, lflow_northd_handler); + engine_add_input(&en_lflow, &en_port_group, NULL); engine_add_input(&en_sync_to_sb_addr_set, &en_nb_address_set, sync_to_sb_addr_set_nb_address_set_handler); @@ -202,11 +202,20 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL); engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL); + engine_add_input(&en_port_group, &en_nb_port_group, NULL); + engine_add_input(&en_port_group, &en_sb_port_group, NULL); + /* No need for an explicit handler for northd changes. Port changes + * that affect port_groups trigger updates to the NB.Port_Group + * table too (because of the explicit dependency in the schema). */ + engine_add_input(&en_port_group, &en_northd, engine_noop_handler); + /* en_sync_to_sb engine node syncs the SB database tables from * the NB database tables. - * Right now this engine only syncs the SB Address_Set table. + * Right now this engine syncs the SB Address_Set and Port_Group + * tables. */ engine_add_input(&en_sync_to_sb, &en_sync_to_sb_addr_set, NULL); + engine_add_input(&en_sync_to_sb, &en_port_group, NULL); engine_add_input(&en_sync_from_sb, &en_northd, sync_from_sb_northd_handler); diff --git a/northd/northd.c b/northd/northd.c index 04da75fa96..b695153805 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -17238,7 +17238,6 @@ northd_init(struct northd_data *data) ovn_datapaths_init(&data->lr_datapaths); hmap_init(&data->ls_ports); hmap_init(&data->lr_ports); - ls_port_group_table_init(&data->ls_port_groups); shash_init(&data->meter_groups); hmap_init(&data->lbs); hmap_init(&data->lb_groups); @@ -17270,8 +17269,6 @@ northd_destroy(struct northd_data *data) } hmap_destroy(&data->lb_groups); - ls_port_group_table_destroy(&data->ls_port_groups); - struct shash_node *node; SHASH_FOR_EACH_SAFE (node, &data->meter_groups) { shash_delete(&data->meter_groups, node); @@ -17410,9 +17407,6 @@ ovnnb_db_run(struct northd_input *input_data, ods_size(&data->ls_datapaths), ods_size(&data->lr_datapaths)); build_ipam(&data->ls_datapaths.datapaths, &data->ls_ports); - ls_port_group_table_build(&data->ls_port_groups, - input_data->nbrec_port_group_table, - &data->ls_ports); build_lrouter_groups(&data->lr_ports, &data->lr_list); build_ip_mcast(ovnsb_txn, input_data->sbrec_ip_multicast_table, input_data->sbrec_ip_mcast_by_dp, @@ -17430,9 +17424,6 @@ ovnnb_db_run(struct northd_input *input_data, sync_lbs(ovnsb_txn, input_data->sbrec_load_balancer_table, &data->ls_datapaths, &data->lbs); - ls_port_group_table_sync(&data->ls_port_groups, - input_data->sbrec_port_group_table, - ovnsb_txn); sync_meters(ovnsb_txn, input_data->nbrec_meter_table, input_data->nbrec_acl_table, input_data->sbrec_meter_table, &data->meter_groups); diff --git a/northd/northd.h b/northd/northd.h index da93a7c6a5..ba28ec63af 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -31,7 +31,6 @@ struct northd_input { const struct nbrec_load_balancer_table *nbrec_load_balancer_table; const struct nbrec_load_balancer_group_table *nbrec_load_balancer_group_table; - const struct nbrec_port_group_table *nbrec_port_group_table; const struct nbrec_meter_table *nbrec_meter_table; const struct nbrec_acl_table *nbrec_acl_table; const struct nbrec_static_mac_binding_table @@ -50,7 +49,6 @@ struct northd_input { const struct sbrec_fdb_table *sbrec_fdb_table; const struct sbrec_load_balancer_table *sbrec_load_balancer_table; const struct sbrec_service_monitor_table *sbrec_service_monitor_table; - const struct sbrec_port_group_table *sbrec_port_group_table; const struct sbrec_meter_table *sbrec_meter_table; const struct sbrec_dns_table *sbrec_dns_table; const struct sbrec_ip_multicast_table *sbrec_ip_multicast_table; @@ -109,7 +107,6 @@ struct northd_data { struct ovn_datapaths lr_datapaths; struct hmap ls_ports; struct hmap lr_ports; - struct ls_port_group_table ls_port_groups; struct shash meter_groups; struct hmap lbs; struct hmap lb_groups; diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index d5be3be75b..1a12513d7a 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -8923,11 +8923,9 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats check ovn-nbctl add port_group pg1 ports ${p1_uuid} wait_column '20.0.0.4' Address_Set addresses name=pg1_ip4 -# There should be recompute of the sync_to_sb_addr_set engine node since northd engine changes. -# There will be another recompute when the update message is received from the sb ovsdb-server. -# Once we add I-P for Port_Groups, there should be no recompute here. -recompute_stat=$(as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats sync_to_sb_addr_set recompute) -AT_CHECK([test $recompute_stat -ge 1]) +# There should be no recompute of the sync_to_sb_addr_set engine node. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats sync_to_sb_addr_set recompute], [0], [0 +]) # No change, no recompute check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats From patchwork Thu Aug 10 12:45:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dumitru Ceara X-Patchwork-Id: 1819845 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: legolas.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=DrXufli/; dkim-atps=neutral Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RM69K5fv4z1yYC for ; Thu, 10 Aug 2023 22:45:57 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id CD2CF61302; Thu, 10 Aug 2023 12:45:55 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org CD2CF61302 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=DrXufli/ 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 uOUZEYTaubaM; Thu, 10 Aug 2023 12:45:53 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id D4DA2612F0; Thu, 10 Aug 2023 12:45:52 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org D4DA2612F0 Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id B9D14C0072; Thu, 10 Aug 2023 12:45:52 +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 5D75BC0032 for ; Thu, 10 Aug 2023 12:45:51 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 5EBBA83F91 for ; Thu, 10 Aug 2023 12:45:33 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 5EBBA83F91 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=DrXufli/ 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 VujaOaz74QH1 for ; Thu, 10 Aug 2023 12:45:29 +0000 (UTC) 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 BC3E883F97 for ; Thu, 10 Aug 2023 12:45:28 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org BC3E883F97 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691671527; 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=O56TB7ou3q8C1X9CSGI99yKwbxkFO/MmEGPcS9AmAqg=; b=DrXufli/4b/fiRQ9vwV1bds2A4kyIjeo+Q2HIRBQP4xFu6ve1h4v6HA7XmxDKRhgbUMiHt J8OxPKAWMIWGKxvwrKjfNRH8j6pZIm3OKOykd35rhycwsO6738EkgpOpAu3p5ox0wbjK/B rkBlSjGXW4/KXh6KJsBSVpEzWuljBYM= 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-643-Y9gw5QPiMlG4hwwajsfvLw-1; Thu, 10 Aug 2023 08:45:24 -0400 X-MC-Unique: Y9gw5QPiMlG4hwwajsfvLw-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DCB73856DED; Thu, 10 Aug 2023 12:45:23 +0000 (UTC) Received: from dceara.remote.csb (unknown [10.39.194.96]) by smtp.corp.redhat.com (Postfix) with ESMTP id 64983C15BAE; Thu, 10 Aug 2023 12:45:22 +0000 (UTC) From: Dumitru Ceara To: ovs-dev@openvswitch.org Date: Thu, 10 Aug 2023 14:45:19 +0200 Message-Id: <169167151736.2447623.4735504724454800717.stgit@dceara.remote.csb> In-Reply-To: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> References: <169167146062.2447623.4263905982665736274.stgit@dceara.remote.csb> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn 5/5] northd: Add incremental processing for NB port groups. 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" It's similar to the processing we do for address sets. There's a bit more mechanics involved due to the fact that we need to split NB port groups per datapath. We currently only partially implement incremental processing of port_group changes in the lflow node. That is, we deal with the case when the sets of "switches per port group" doesn't change. In that specific case ACL lflows don't need to be reprocessed. In a synthetic benchmark that created (in this order): - 500 switches - 2000 port groups - 4 ACLs per port group - 10000 ports distributed equally between the switches and port groups we measured the following ovn-northd CPU usage: +-------------------------+------------+--------------------+ | Incremental processing? | --wait=sb? | northd avg cpu (%) | +-------------------------+------------+--------------------+ | N | Y | 84.2 | +-------------------------+------------+--------------------+ | Y | Y | 41.5 | +-------------------------+------------+--------------------+ | N | N | 93.2 | +-------------------------+------------+--------------------+ | Y | N | 53.6 | +-------------------------+------------+--------------------+ where '--wait=sb' set to 'Y' means the benchmark was waiting for the port and port group operations to be propagated to the Southbound DB before continuing to the next operation. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2228162 Signed-off-by: Dumitru Ceara Acked-by: Ales Musil --- northd/en-lflow.c | 17 ++ northd/en-lflow.h | 1 northd/en-port-group.c | 451 ++++++++++++++++++++++++++++++++++++++++------ northd/en-port-group.h | 36 +++- northd/inc-proc-northd.c | 13 + northd/ovn-northd.c | 4 tests/ovn-northd.at | 246 +++++++++++++++++++++++++ 7 files changed, 708 insertions(+), 60 deletions(-) diff --git a/northd/en-lflow.c b/northd/en-lflow.c index 7f6a7872b2..1321f79036 100644 --- a/northd/en-lflow.c +++ b/northd/en-lflow.c @@ -119,6 +119,23 @@ lflow_northd_handler(struct engine_node *node, return true; } +bool +lflow_port_group_handler(struct engine_node *node, void *data OVS_UNUSED) +{ + struct port_group_data *pg_data = + engine_get_input_data("port_group", node); + + /* If the set of switches per port group didn't change then there's no + * need to reprocess lflows. Otherwise, there might be a need to add + * port-group ACLs to new switches. */ + if (!pg_data->ls_port_groups_sets_unchanged) { + return false; + } + + engine_set_node_state(node, EN_UPDATED); + return true; +} + void *en_lflow_init(struct engine_node *node OVS_UNUSED, struct engine_arg *arg OVS_UNUSED) { diff --git a/northd/en-lflow.h b/northd/en-lflow.h index 5e3fbc25e3..5417b2faff 100644 --- a/northd/en-lflow.h +++ b/northd/en-lflow.h @@ -13,5 +13,6 @@ void en_lflow_run(struct engine_node *node, void *data); void *en_lflow_init(struct engine_node *node, struct engine_arg *arg); void en_lflow_cleanup(void *data); bool lflow_northd_handler(struct engine_node *, void *data); +bool lflow_port_group_handler(struct engine_node *, void *data); #endif /* EN_LFLOW_H */ diff --git a/northd/en-port-group.c b/northd/en-port-group.c index 2c36410246..6902695a01 100644 --- a/northd/en-port-group.c +++ b/northd/en-port-group.c @@ -33,15 +33,46 @@ static struct ls_port_group *ls_port_group_create( static void ls_port_group_destroy(struct ls_port_group_table *, struct ls_port_group *); +static bool ls_port_group_process( + struct ls_port_group_table *, + struct port_group_to_ls_table *, + const struct hmap *ls_ports, + const struct nbrec_port_group *, + struct hmapx *updated_ls_port_groups +); + +static void ls_port_group_record_clear( + struct ls_port_group_table *, + struct port_group_to_ls *, + struct hmapx *updated_ls_port_groups); +static void ls_port_group_record_prune(struct ls_port_group *); + static struct ls_port_group_record *ls_port_group_record_add( struct ls_port_group *, const struct nbrec_port_group *, const char *port_name); +static struct ls_port_group_record *ls_port_group_record_find( + struct ls_port_group *, const struct nbrec_port_group *nb_pg); + static void ls_port_group_record_destroy( struct ls_port_group *, struct ls_port_group_record *); +static struct port_group_to_ls *port_group_to_ls_create( + struct port_group_to_ls_table *, + const struct nbrec_port_group *); +static void port_group_to_ls_destroy(struct port_group_to_ls_table *, + struct port_group_to_ls *); + +static void update_sb_port_group(struct sorted_array *nb_ports, + const struct sbrec_port_group *sb_pg); +static void sync_port_group(struct ovsdb_idl_txn *, const char *sb_pg_name, + struct sorted_array *ports, + struct shash *sb_port_groups); +static const struct sbrec_port_group *sb_port_group_lookup_by_name( + struct ovsdb_idl_index *sbrec_port_group_by_name, const char *name); + void ls_port_group_table_init(struct ls_port_group_table *table) { @@ -82,39 +113,16 @@ ls_port_group_table_find(const struct ls_port_group_table *table, } void -ls_port_group_table_build(struct ls_port_group_table *ls_port_groups, - const struct nbrec_port_group_table *pg_table, - const struct hmap *ls_ports) +ls_port_group_table_build( + struct ls_port_group_table *ls_port_groups, + struct port_group_to_ls_table *port_group_to_switches, + const struct nbrec_port_group_table *pg_table, + const struct hmap *ls_ports) { const struct nbrec_port_group *nb_pg; NBREC_PORT_GROUP_TABLE_FOR_EACH (nb_pg, pg_table) { - for (size_t i = 0; i < nb_pg->n_ports; i++) { - const char *port_name = nb_pg->ports[i]->name; - const struct ovn_datapath *od = - northd_get_datapath_for_port(ls_ports, port_name); - - if (!od) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_ERR_RL(&rl, "lport %s in port group %s not found.", - port_name, nb_pg->name); - continue; - } - - if (!od->nbs) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "lport %s in port group %s has no lswitch.", - nb_pg->ports[i]->name, - nb_pg->name); - continue; - } - - struct ls_port_group *ls_pg = - ls_port_group_table_find(ls_port_groups, od->nbs); - if (!ls_pg) { - ls_pg = ls_port_group_create(ls_port_groups, od->nbs, od->sb); - } - ls_port_group_record_add(ls_pg, nb_pg, port_name); - } + ls_port_group_process(ls_port_groups, port_group_to_switches, + ls_ports, nb_pg, NULL); } } @@ -145,18 +153,11 @@ ls_port_group_table_sync( get_sb_port_group_name(ls_pg_rec->nb_pg->name, ls_pg->sb_datapath_key, &sb_name); - sb_port_group = shash_find_and_delete(&sb_port_groups, - ds_cstr(&sb_name)); - if (!sb_port_group) { - sb_port_group = sbrec_port_group_insert(ovnsb_txn); - sbrec_port_group_set_name(sb_port_group, ds_cstr(&sb_name)); - } - - const char **nb_port_names = sset_array(&ls_pg_rec->ports); - sbrec_port_group_set_ports(sb_port_group, - nb_port_names, - sset_count(&ls_pg_rec->ports)); - free(nb_port_names); + struct sorted_array ports = + sorted_array_from_sset(&ls_pg_rec->ports); + sync_port_group(ovnsb_txn, ds_cstr(&sb_name), + &ports, &sb_port_groups); + sorted_array_destroy(&ports); } } ds_destroy(&sb_name); @@ -201,31 +202,165 @@ ls_port_group_destroy(struct ls_port_group_table *ls_port_groups, } } +/* Process a NB.Port_Group record and stores any updated ls_port_groups + * in updated_ls_port_groups. Returns true if a new ls_port_group had + * to be created or destroyed. + */ +static bool +ls_port_group_process(struct ls_port_group_table *ls_port_groups, + struct port_group_to_ls_table *port_group_to_switches, + const struct hmap *ls_ports, + const struct nbrec_port_group *nb_pg, + struct hmapx *updated_ls_port_groups) +{ + struct hmapx cleared_ls_port_groups = + HMAPX_INITIALIZER(&cleared_ls_port_groups); + bool ls_port_group_created = false; + + struct port_group_to_ls *pg_ls = + port_group_to_ls_table_find(port_group_to_switches, nb_pg); + if (!pg_ls) { + pg_ls = port_group_to_ls_create(port_group_to_switches, nb_pg); + } else { + /* Clear all old records corresponding to this port group; we'll + * reprocess it below. */ + ls_port_group_record_clear(ls_port_groups, pg_ls, + &cleared_ls_port_groups); + } + + for (size_t i = 0; i < nb_pg->n_ports; i++) { + const char *port_name = nb_pg->ports[i]->name; + const struct ovn_datapath *od = + northd_get_datapath_for_port(ls_ports, port_name); + + if (!od) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_ERR_RL(&rl, "lport %s in port group %s not found.", + port_name, nb_pg->name); + continue; + } + + if (!od->nbs) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "lport %s in port group %s has no lswitch.", + nb_pg->ports[i]->name, + nb_pg->name); + continue; + } + + struct ls_port_group *ls_pg = + ls_port_group_table_find(ls_port_groups, od->nbs); + if (!ls_pg) { + ls_pg = ls_port_group_create(ls_port_groups, od->nbs, od->sb); + ls_port_group_created = true; + } + ls_port_group_record_add(ls_pg, nb_pg, port_name); + hmapx_add(&pg_ls->switches, + CONST_CAST(struct nbrec_logical_switch *, od->nbs)); + if (updated_ls_port_groups) { + hmapx_add(updated_ls_port_groups, ls_pg); + } + } + + bool ls_port_group_destroyed = false; + struct hmapx_node *node; + HMAPX_FOR_EACH (node, &cleared_ls_port_groups) { + struct ls_port_group *ls_pg = node->data; + + ls_port_group_record_prune(ls_pg); + + if (hmap_is_empty(&ls_pg->nb_pgs)) { + ls_port_group_destroy(ls_port_groups, ls_pg); + ls_port_group_destroyed = true; + } + } + hmapx_destroy(&cleared_ls_port_groups); + + return ls_port_group_created || ls_port_group_destroyed; +} + +/* Destroys all the struct ls_port_group_record that might be associated to + * northbound database logical switches. Stores ls_port_groups that became + * were updated in the 'updated_ls_port_groups' map. + */ +static void +ls_port_group_record_clear(struct ls_port_group_table *ls_port_groups, + struct port_group_to_ls *pg_ls, + struct hmapx *cleared_ls_port_groups) +{ + struct hmapx_node *node; + + HMAPX_FOR_EACH (node, &pg_ls->switches) { + const struct nbrec_logical_switch *nbs = node->data; + + struct ls_port_group *ls_pg = + ls_port_group_table_find(ls_port_groups, nbs); + if (!ls_pg) { + continue; + } + + /* Clear ports in the port group record. */ + struct ls_port_group_record *ls_pg_rec = + ls_port_group_record_find(ls_pg, pg_ls->nb_pg); + if (!ls_pg_rec) { + continue; + } + + sset_clear(&ls_pg_rec->ports); + hmapx_add(cleared_ls_port_groups, ls_pg); + } +} + +static void +ls_port_group_record_prune(struct ls_port_group *ls_pg) +{ + struct ls_port_group_record *ls_pg_rec; + + HMAP_FOR_EACH_SAFE (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + if (sset_is_empty(&ls_pg_rec->ports)) { + ls_port_group_record_destroy(ls_pg, ls_pg_rec); + } + } +} + static struct ls_port_group_record * ls_port_group_record_add(struct ls_port_group *ls_pg, const struct nbrec_port_group *nb_pg, const char *port_name) { - struct ls_port_group_record *ls_pg_rec = NULL; + struct ls_port_group_record *ls_pg_rec = + ls_port_group_record_find(ls_pg, nb_pg); size_t hash = uuid_hash(&nb_pg->header_.uuid); - HMAP_FOR_EACH_WITH_HASH (ls_pg_rec, key_node, hash, &ls_pg->nb_pgs) { - if (ls_pg_rec->nb_pg == nb_pg) { - goto done; - } + if (!ls_pg_rec) { + ls_pg_rec = xzalloc(sizeof *ls_pg_rec); + *ls_pg_rec = (struct ls_port_group_record) { + .nb_pg = nb_pg, + .ports = SSET_INITIALIZER(&ls_pg_rec->ports), + }; + hmap_insert(&ls_pg->nb_pgs, &ls_pg_rec->key_node, hash); } - ls_pg_rec = xzalloc(sizeof *ls_pg_rec); - *ls_pg_rec = (struct ls_port_group_record) { - .nb_pg = nb_pg, - .ports = SSET_INITIALIZER(&ls_pg_rec->ports), - }; - hmap_insert(&ls_pg->nb_pgs, &ls_pg_rec->key_node, hash); -done: sset_add(&ls_pg_rec->ports, port_name); return ls_pg_rec; } +static struct ls_port_group_record * +ls_port_group_record_find(struct ls_port_group *ls_pg, + const struct nbrec_port_group *nb_pg) +{ + size_t hash = uuid_hash(&nb_pg->header_.uuid); + struct ls_port_group_record *ls_pg_rec; + + HMAP_FOR_EACH_WITH_HASH (ls_pg_rec, key_node, hash, &ls_pg->nb_pgs) { + if (ls_pg_rec->nb_pg == nb_pg) { + return ls_pg_rec; + } + } + return NULL; +} + + static void ls_port_group_record_destroy(struct ls_port_group *ls_pg, struct ls_port_group_record *ls_pg_rec) @@ -237,6 +372,71 @@ ls_port_group_record_destroy(struct ls_port_group *ls_pg, } } +void +port_group_to_ls_table_init(struct port_group_to_ls_table *table) +{ + *table = (struct port_group_to_ls_table) { + .entries = HMAP_INITIALIZER(&table->entries), + }; +} + +void +port_group_to_ls_table_clear(struct port_group_to_ls_table *table) +{ + struct port_group_to_ls *pg_ls; + HMAP_FOR_EACH_SAFE (pg_ls, key_node, &table->entries) { + port_group_to_ls_destroy(table, pg_ls); + } +} + +void +port_group_to_ls_table_destroy(struct port_group_to_ls_table *table) +{ + port_group_to_ls_table_clear(table); + hmap_destroy(&table->entries); +} + +struct port_group_to_ls * +port_group_to_ls_table_find(const struct port_group_to_ls_table *table, + const struct nbrec_port_group *nb_pg) +{ + struct port_group_to_ls *pg_ls; + + HMAP_FOR_EACH_WITH_HASH (pg_ls, key_node, uuid_hash(&nb_pg->header_.uuid), + &table->entries) { + if (nb_pg == pg_ls->nb_pg) { + return pg_ls; + } + } + return NULL; +} + +static struct port_group_to_ls * +port_group_to_ls_create(struct port_group_to_ls_table *table, + const struct nbrec_port_group *nb_pg) +{ + struct port_group_to_ls *pg_ls = xmalloc(sizeof *pg_ls); + + *pg_ls = (struct port_group_to_ls) { + .nb_pg = nb_pg, + .switches = HMAPX_INITIALIZER(&pg_ls->switches), + }; + hmap_insert(&table->entries, &pg_ls->key_node, + uuid_hash(&nb_pg->header_.uuid)); + return pg_ls; +} + +static void +port_group_to_ls_destroy(struct port_group_to_ls_table *table, + struct port_group_to_ls *pg_ls) +{ + if (pg_ls) { + hmapx_destroy(&pg_ls->switches); + hmap_remove(&table->entries, &pg_ls->key_node); + free(pg_ls); + } +} + /* Incremental processing implementation. */ static struct port_group_input port_group_get_input_data(struct engine_node *node) @@ -259,6 +459,7 @@ en_port_group_init(struct engine_node *node OVS_UNUSED, struct port_group_data *pg_data = xmalloc(sizeof *pg_data); ls_port_group_table_init(&pg_data->ls_port_groups); + port_group_to_ls_table_init(&pg_data->port_groups_to_ls); return pg_data; } @@ -268,6 +469,15 @@ en_port_group_cleanup(void *data_) struct port_group_data *data = data_; ls_port_group_table_destroy(&data->ls_port_groups); + port_group_to_ls_table_destroy(&data->port_groups_to_ls); +} + +void +en_port_group_clear_tracked_data(void *data_) +{ + struct port_group_data *data = data_; + + data->ls_port_groups_sets_unchanged = false; } void @@ -280,7 +490,10 @@ en_port_group_run(struct engine_node *node, void *data_) stopwatch_start(PORT_GROUP_RUN_STOPWATCH_NAME, time_msec()); ls_port_group_table_clear(&data->ls_port_groups); + port_group_to_ls_table_clear(&data->port_groups_to_ls); + ls_port_group_table_build(&data->ls_port_groups, + &data->port_groups_to_ls, input_data.nbrec_port_group_table, input_data.ls_ports); @@ -291,3 +504,133 @@ en_port_group_run(struct engine_node *node, void *data_) stopwatch_stop(PORT_GROUP_RUN_STOPWATCH_NAME, time_msec()); engine_set_node_state(node, EN_UPDATED); } + +bool +port_group_nb_port_group_handler(struct engine_node *node, void *data_) +{ + struct port_group_input input_data = port_group_get_input_data(node); + struct port_group_data *data = data_; + bool success = true; + + const struct nbrec_port_group_table *nb_pg_table = + EN_OVSDB_GET(engine_get_input("NB_port_group", node)); + const struct nbrec_port_group *nb_pg; + + /* Return false if a port group is created or deleted. + * Handle I-P for only updated port groups. */ + NBREC_PORT_GROUP_TABLE_FOR_EACH_TRACKED (nb_pg, nb_pg_table) { + if (nbrec_port_group_is_new(nb_pg) || + nbrec_port_group_is_deleted(nb_pg)) { + return false; + } + } + + struct hmapx updated_ls_port_groups = + HMAPX_INITIALIZER(&updated_ls_port_groups); + + NBREC_PORT_GROUP_TABLE_FOR_EACH_TRACKED (nb_pg, nb_pg_table) { + /* Newly created port groups can't be incrementally processed; + * the rest yes. */ + if (ls_port_group_process(&data->ls_port_groups, + &data->port_groups_to_ls, + input_data.ls_ports, + nb_pg, &updated_ls_port_groups)) { + success = false; + break; + } + } + + /* If changes have been successfully processed incrementally then update + * the SB too. */ + if (success) { + struct ovsdb_idl_index *sbrec_port_group_by_name = + engine_ovsdb_node_get_index( + engine_get_input("SB_port_group", node), + "sbrec_port_group_by_name"); + struct ds sb_pg_name = DS_EMPTY_INITIALIZER; + + struct hmapx_node *updated_node; + HMAPX_FOR_EACH (updated_node, &updated_ls_port_groups) { + const struct ls_port_group *ls_pg = updated_node->data; + struct ls_port_group_record *ls_pg_rec; + + HMAP_FOR_EACH (ls_pg_rec, key_node, &ls_pg->nb_pgs) { + get_sb_port_group_name(ls_pg_rec->nb_pg->name, + ls_pg->sb_datapath_key, + &sb_pg_name); + + const struct sbrec_port_group *sb_pg = + sb_port_group_lookup_by_name(sbrec_port_group_by_name, + ds_cstr(&sb_pg_name)); + if (!sb_pg) { + success = false; + break; + } + struct sorted_array nb_ports = + sorted_array_from_sset(&ls_pg_rec->ports); + update_sb_port_group(&nb_ports, sb_pg); + sorted_array_destroy(&nb_ports); + } + } + ds_destroy(&sb_pg_name); + } + + data->ls_port_groups_sets_unchanged = success; + engine_set_node_state(node, EN_UPDATED); + hmapx_destroy(&updated_ls_port_groups); + return success; +} + +static void +sb_port_group_apply_diff(const void *arg, const char *item, bool add) +{ + const struct sbrec_port_group *pg = arg; + if (add) { + sbrec_port_group_update_ports_addvalue(pg, item); + } else { + sbrec_port_group_update_ports_delvalue(pg, item); + } +} + +static void +update_sb_port_group(struct sorted_array *nb_ports, + const struct sbrec_port_group *sb_pg) +{ + struct sorted_array sb_ports = sorted_array_from_dbrec(sb_pg, ports); + sorted_array_apply_diff(nb_ports, &sb_ports, + sb_port_group_apply_diff, sb_pg); + sorted_array_destroy(&sb_ports); +} + +static void +sync_port_group(struct ovsdb_idl_txn *ovnsb_txn, const char *sb_pg_name, + struct sorted_array *ports, + struct shash *sb_port_groups) +{ + const struct sbrec_port_group *sb_port_group = + shash_find_and_delete(sb_port_groups, sb_pg_name); + if (!sb_port_group) { + sb_port_group = sbrec_port_group_insert(ovnsb_txn); + sbrec_port_group_set_name(sb_port_group, sb_pg_name); + sbrec_port_group_set_ports(sb_port_group, ports->arr, ports->n); + } else { + update_sb_port_group(ports, sb_port_group); + } +} + +/* Finds and returns the port group set with the given 'name', or NULL + * if no such port group exists. */ +static const struct sbrec_port_group * +sb_port_group_lookup_by_name(struct ovsdb_idl_index *sbrec_port_group_by_name, + const char *name) +{ + struct sbrec_port_group *target = sbrec_port_group_index_init_row( + sbrec_port_group_by_name); + sbrec_port_group_index_set_name(target, name); + + struct sbrec_port_group *retval = sbrec_port_group_index_find( + sbrec_port_group_by_name, target); + + sbrec_port_group_index_destroy_row(target); + return retval; +} diff --git a/northd/en-port-group.h b/northd/en-port-group.h index 5cbf6c6c4a..c3975f64ee 100644 --- a/northd/en-port-group.h +++ b/northd/en-port-group.h @@ -18,6 +18,7 @@ #include +#include "lib/hmapx.h" #include "lib/inc-proc-eng.h" #include "lib/ovn-nb-idl.h" #include "lib/ovn-sb-idl.h" @@ -54,9 +55,33 @@ struct ls_port_group *ls_port_group_table_find( const struct ls_port_group_table *, const struct nbrec_logical_switch *); -void ls_port_group_table_build(struct ls_port_group_table *ls_port_groups, - const struct nbrec_port_group_table *, - const struct hmap *ls_ports); +/* Per port group map of datapaths with ports in the group. */ +struct port_group_to_ls_table { + struct hmap entries; /* Stores struct port_group_to_ls. */ +}; + +struct port_group_to_ls { + struct hmap_node key_node; /* Index on 'pg->header_.uuid'. */ + + const struct nbrec_port_group *nb_pg; + + /* Map of 'struct nbrec_logical_switch *' with ports in the group. */ + struct hmapx switches; +}; + +void port_group_to_ls_table_init(struct port_group_to_ls_table *); +void port_group_to_ls_table_clear(struct port_group_to_ls_table *); +void port_group_to_ls_table_destroy(struct port_group_to_ls_table *); + +struct port_group_to_ls *port_group_to_ls_table_find( + const struct port_group_to_ls_table *, + const struct nbrec_port_group *); + +void ls_port_group_table_build( + struct ls_port_group_table *ls_port_groups, + struct port_group_to_ls_table *port_group_to_switches, + const struct nbrec_port_group_table *, + const struct hmap *ls_ports); void ls_port_group_table_sync(const struct ls_port_group_table *ls_port_groups, const struct sbrec_port_group_table *, struct ovsdb_idl_txn *ovnsb_txn); @@ -75,10 +100,15 @@ struct port_group_input { struct port_group_data { struct ls_port_group_table ls_port_groups; + struct port_group_to_ls_table port_groups_to_ls; + bool ls_port_groups_sets_unchanged; }; void *en_port_group_init(struct engine_node *, struct engine_arg *); void en_port_group_cleanup(void *data); +void en_port_group_clear_tracked_data(void *data); void en_port_group_run(struct engine_node *, void *data); +bool port_group_nb_port_group_handler(struct engine_node *, void *data); + #endif /* EN_PORT_GROUP_H */ diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index 6d5f9e8d16..bd598ba5e2 100644 --- a/northd/inc-proc-northd.c +++ b/northd/inc-proc-northd.c @@ -137,7 +137,7 @@ static ENGINE_NODE(mac_binding_aging_waker, "mac_binding_aging_waker"); static ENGINE_NODE(northd_output, "northd_output"); static ENGINE_NODE(sync_to_sb, "sync_to_sb"); static ENGINE_NODE(sync_to_sb_addr_set, "sync_to_sb_addr_set"); -static ENGINE_NODE(port_group, "port_group"); +static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(port_group, "port_group"); static ENGINE_NODE(fdb_aging, "fdb_aging"); static ENGINE_NODE(fdb_aging_waker, "fdb_aging_waker"); @@ -193,7 +193,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_lflow, &en_sb_multicast_group, NULL); engine_add_input(&en_lflow, &en_sb_igmp_group, NULL); engine_add_input(&en_lflow, &en_northd, lflow_northd_handler); - engine_add_input(&en_lflow, &en_port_group, NULL); + engine_add_input(&en_lflow, &en_port_group, lflow_port_group_handler); engine_add_input(&en_sync_to_sb_addr_set, &en_nb_address_set, sync_to_sb_addr_set_nb_address_set_handler); @@ -202,7 +202,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL); engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL); - engine_add_input(&en_port_group, &en_nb_port_group, NULL); + engine_add_input(&en_port_group, &en_nb_port_group, + port_group_nb_port_group_handler); engine_add_input(&en_port_group, &en_sb_port_group, NULL); /* No need for an explicit handler for northd changes. Port changes * that affect port_groups trigger updates to the NB.Port_Group @@ -287,6 +288,12 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, "sbrec_address_set_by_name", sbrec_address_set_by_name); + struct ovsdb_idl_index *sbrec_port_group_by_name + = ovsdb_idl_index_create1(sb->idl, &sbrec_port_group_col_name); + engine_ovsdb_node_add_index(&en_sb_port_group, + "sbrec_port_group_by_name", + sbrec_port_group_by_name); + struct ovsdb_idl_index *sbrec_fdb_by_dp_and_port = ovsdb_idl_index_create2(sb->idl, &sbrec_fdb_col_dp_key, &sbrec_fdb_col_port_key); diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 4fa1b039ea..44385d604c 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -836,6 +836,10 @@ main(int argc, char *argv[]) ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &sbrec_multicast_group_columns[i]); } + for (size_t i = 0; i < SBREC_PORT_GROUP_N_COLUMNS; i++) { + ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, + &sbrec_port_group_columns[i]); + } unixctl_command_register("sb-connection-status", "", 0, 0, ovn_conn_show, ovnsb_idl_loop.idl); diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 1a12513d7a..a04ba2b23f 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -8936,6 +8936,252 @@ AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats sync_to_sb_a AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD_NO_HV([ +AT_SETUP([Port group incremental processing]) +ovn_start + +check ovn-nbctl ls-add sw1 \ + -- lsp-add sw1 sw1.1 \ + -- lsp-add sw1 sw1.2 \ + -- lsp-add sw1 sw1.3 \ + -- ls-add sw2 \ + -- lsp-add sw2 sw2.1 \ + -- lsp-add sw2 sw2.2 \ + -- lsp-add sw2 sw2.3 + +check ovn-nbctl --wait=sb sync +sw1_key=$(fetch_column Datapath_Binding tunnel_key external_ids:name=sw1) +sw2_key=$(fetch_column Datapath_Binding tunnel_key external_ids:name=sw2) + +check_acl_lflows() { +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw1 | grep ls_in_acl_eval | grep eth.src==41:41:41:41:41:41 -c], [ignore], [dnl +$1 +]) +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw1 | grep ls_in_acl_eval | grep eth.src==42:42:42:42:42:42 -c], [ignore], [dnl +$2 +]) +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw2 | grep ls_in_acl_eval | grep eth.src==41:41:41:41:41:41 -c], [ignore], [dnl +$3 +]) +AT_CHECK_UNQUOTED([ovn-sbctl lflow-list sw2 | grep ls_in_acl_eval | grep eth.src==42:42:42:42:42:42 -c], [ignore], [dnl +$4 +]) +} + +AS_BOX([Create new PG1 and PG2]) +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats +check ovn-nbctl --wait=sb -- pg-add pg1 -- pg-add pg2 +dnl The northd node should not recompute, it should handle nb_global update +dnl though, therefore "compute: 1". +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd], [0], [dnl +Node: northd +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl The port_group node recomputes every time a NB port group is added/deleted. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats port_group], [0], [dnl +Node: port_group +- recompute: 1 +- compute: 0 +- abort: 0 +]) +dnl The port_group node is an input for the lflow node. Port_group +dnl recompute/compute triggers lflow recompute. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow], [0], [dnl +Node: lflow +- recompute: 1 +- compute: 0 +- abort: 0 +]) + +AS_BOX([Add ACLs on PG1 and PG2]) +check ovn-nbctl --wait=sb \ + -- acl-add pg1 from-lport 1 eth.src==41:41:41:41:41:41 allow \ + -- acl-add pg2 from-lport 1 eth.src==42:42:42:42:42:42 allow + +AS_BOX([Add one port from the two switches to PG1]) +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats +check ovn-nbctl --wait=sb \ + -- pg-set-ports pg1 sw1.1 sw2.1 +check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1" +check_column "sw2.1" sb:Port_Group ports name="${sw2_key}_pg1" + +dnl The northd node should not recompute, it should handle nb_global update +dnl though, therefore "compute: 1". +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd], [0], [dnl +Node: northd +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl The port_group node recomputes also every time a port from a new switch +dnl is added to the group. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats port_group], [0], [dnl +Node: port_group +- recompute: 1 +- compute: 0 +- abort: 0 +]) +dnl The port_group node is an input for the lflow node. Port_group +dnl recompute/compute triggers lflow recompute. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow], [0], [dnl +Node: lflow +- recompute: 1 +- compute: 0 +- abort: 0 +]) +dnl Expect ACL1 on sw1 and sw2 +check_acl_lflows 1 0 1 0 + +AS_BOX([Add one port from the two switches to PG2]) +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats +check ovn-nbctl --wait=sb \ + -- pg-set-ports pg2 sw1.2 sw2.2 +check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1" +check_column "sw2.1" sb:Port_Group ports name="${sw2_key}_pg1" +check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2" +check_column "sw2.2" sb:Port_Group ports name="${sw2_key}_pg2" + +dnl The northd node should not recompute, it should handle nb_global update +dnl though, therefore "compute: 1". +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd], [0], [dnl +Node: northd +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl The port_group node recomputes also every time a port from a new switch +dnl is added to the group. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats port_group], [0], [dnl +Node: port_group +- recompute: 1 +- compute: 0 +- abort: 0 +]) +dnl The port_group node is an input for the lflow node. Port_group +dnl recompute/compute triggers lflow recompute (for ACLs). +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow], [0], [dnl +Node: lflow +- recompute: 1 +- compute: 0 +- abort: 0 +]) +dnl Expect both ACLs on sw1 and sw2 +check_acl_lflows 1 1 1 1 + +AS_BOX([Add one more port from the two switches to PG1 and PG2]) +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats +check ovn-nbctl --wait=sb \ + -- pg-set-ports pg1 sw1.1 sw2.1 sw1.3 sw2.3 \ + -- pg-set-ports pg2 sw1.2 sw2.2 sw1.3 sw2.3 +check_column "sw1.1 sw1.3" sb:Port_Group ports name="${sw1_key}_pg1" +check_column "sw2.1 sw2.3" sb:Port_Group ports name="${sw2_key}_pg1" +check_column "sw1.2 sw1.3" sb:Port_Group ports name="${sw1_key}_pg2" +check_column "sw2.2 sw2.3" sb:Port_Group ports name="${sw2_key}_pg2" + +dnl The northd node should not recompute, it should handle nb_global update +dnl though, therefore "compute: 1". +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd], [0], [dnl +Node: northd +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl We did not change the set of switches a pg is applied to, there should be +dnl no recompute. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats port_group], [0], [dnl +Node: port_group +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl We did not change the set of switches a pg is applied to, there should be +dnl no recompute. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow], [0], [dnl +Node: lflow +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl Expect both ACLs on sw1 and sw2 +check_acl_lflows 1 1 1 1 + +AS_BOX([Remove the last port from PG1 and PG2]) +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats +check ovn-nbctl --wait=sb \ + -- pg-set-ports pg1 sw1.1 sw2.1 \ + -- pg-set-ports pg2 sw1.2 sw2.2 +check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1" +check_column "sw2.1" sb:Port_Group ports name="${sw2_key}_pg1" +check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2" +check_column "sw2.2" sb:Port_Group ports name="${sw2_key}_pg2" + +dnl The northd node should not recompute, it should handle nb_global update +dnl though, therefore "compute: 1". +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd], [0], [dnl +Node: northd +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl We did not change the set of switches a pg is applied to, there should be +dnl no recompute. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats port_group], [0], [dnl +Node: port_group +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl We did not change the set of switches a pg is applied to, there should be +dnl no recompute. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow], [0], [dnl +Node: lflow +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl Expect both ACLs on sw1 and sw2 +check_acl_lflows 1 1 1 1 + +AS_BOX([Remove the second port from PG1 and PG2]) +check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats +check ovn-nbctl --wait=sb \ + -- pg-set-ports pg1 sw1.1 \ + -- pg-set-ports pg2 sw1.2 +check_column "sw1.1" sb:Port_Group ports name="${sw1_key}_pg1" +check_column "sw1.2" sb:Port_Group ports name="${sw1_key}_pg2" + +dnl The northd node should not recompute, it should handle nb_global update +dnl though, therefore "compute: 1". +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats northd], [0], [dnl +Node: northd +- recompute: 0 +- compute: 1 +- abort: 0 +]) +dnl We did changed the set of switches a pg is applied to, there should be +dnl a recompute. +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats port_group], [0], [dnl +Node: port_group +- recompute: 1 +- compute: 0 +- abort: 0 +]) +dnl We did changed the set of switches a pg is applied to, there should be +dnl a recompute (for ACLs). +AT_CHECK([as northd ovn-appctl -t NORTHD_TYPE inc-engine/show-stats lflow], [0], [dnl +Node: lflow +- recompute: 1 +- compute: 0 +- abort: 0 +]) +dnl Expect both ACLs on sw1 and not on sw2. +check_acl_lflows 1 1 0 0 + +AT_CLEANUP +]) + OVN_FOR_EACH_NORTHD([ AT_SETUP([Check default drop]) AT_KEYWORDS([drop])