From patchwork Tue May 7 06:25:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1932227 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=MLlFjRBE; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VYSvH3FtMz1xnS for ; Tue, 7 May 2024 16:25:31 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 7E99C40156; Tue, 7 May 2024 06:25:29 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id D0B-MWOKA9SI; Tue, 7 May 2024 06:25:28 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 13D1741522 Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=MLlFjRBE Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTPS id 13D1741522; Tue, 7 May 2024 06:25:28 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id DE831C0077; Tue, 7 May 2024 06:25:27 +0000 (UTC) X-Original-To: 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 CC860C0077 for ; Tue, 7 May 2024 06:25:25 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id A93B140156 for ; Tue, 7 May 2024 06:25:25 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id BNvVm_X1wMkv for ; Tue, 7 May 2024 06:25:24 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amusil@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org 6A3E140158 Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 6A3E140158 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 6A3E140158 for ; Tue, 7 May 2024 06:25:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1715063123; 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=Xe1n09EwOuQxbbXiH8QyDwfeIgAH3RAVZeRdSd1Sb2Y=; b=MLlFjRBEBotJpkiveB4csdrJ5r7FTP0xuLQmA9fT4GgWzSxR2bY62fER29p9UZEtt2W5SL f1MWOfsRA0g/PzVf3rW4jtug9T8L05rIioz4V41n0eDkQNJx/GZ63NhUNZEyJDXOHTGk+z eHGsFcH9EHAYhclv71ykAebENI8yzCY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-194-JaZmepAnMcWa1JL3_PDgWg-1; Tue, 07 May 2024 02:25:19 -0400 X-MC-Unique: JaZmepAnMcWa1JL3_PDgWg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A32B6834FBC; Tue, 7 May 2024 06:25:19 +0000 (UTC) Received: from amusil.brq.redhat.com (unknown [10.43.17.32]) by smtp.corp.redhat.com (Postfix) with ESMTP id D2DBAC271B1; Tue, 7 May 2024 06:25:18 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Tue, 7 May 2024 08:25:14 +0200 Message-ID: <20240507062517.387329-2-amusil@redhat.com> In-Reply-To: <20240507062517.387329-1-amusil@redhat.com> References: <20240507062517.387329-1-amusil@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn v2 1/4] northd, controller: Handle tunnel_key change consistently. 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" Currently the tunnel_key change for either LS/LR/LSP/LRP wasn't consistent. That would lead to a situations when some old would still be present, breaking the connection especially for already existing FDBs and MAC bindings. Make sure the FDB entries are up to date by removing them from DB when there is a tunnel_key change as those entries have only tunnel_key refrences (dp_key, port_key). MAC bindings have references to the datapath and port name, instead of removing those entries do recompute in the controller when we detect tunnel_key change. This can be costly at scale, however the tunnel_key is not expected to change constantly, in most cases it shouldn't change at all. Fixes: b337750e45be ("northd: Incremental processing of VIF changes in 'northd' node.") Fixes: 425f699e2b20 ("controller: fixed potential segfault when changing tunnel_key and deleting ls.") Reported-at: https://issues.redhat.com/browse/FDP-393 Acked-by: Mark Michelson Signed-off-by: Ales Musil --- v2: Rebase on top of main. --- controller/binding.c | 13 ++++++++-- controller/ovn-controller.c | 27 +++++++------------ northd/northd.c | 7 +++++ tests/ovn.at | 52 +++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 20 deletions(-) diff --git a/controller/binding.c b/controller/binding.c index 8ac2ce3e2..0712d7030 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -3126,8 +3126,17 @@ delete_done: update_ld_peers(pb, b_ctx_out->local_datapaths); } - handled = handle_updated_port(b_ctx_in, b_ctx_out, pb); - if (!handled) { + if (!handle_updated_port(b_ctx_in, b_ctx_out, pb)) { + handled = false; + break; + } + + if (!sbrec_port_binding_is_new(pb) && + sbrec_port_binding_is_updated(pb, + SBREC_PORT_BINDING_COL_TUNNEL_KEY) && + get_local_datapath(b_ctx_out->local_datapaths, + pb->datapath->tunnel_key)) { + handled = false; break; } } diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 23269af83..356ce881a 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -1894,7 +1894,6 @@ runtime_data_sb_datapath_binding_handler(struct engine_node *node OVS_UNUSED, engine_get_input("SB_datapath_binding", node)); const struct sbrec_datapath_binding *dp; struct ed_type_runtime_data *rt_data = data; - struct local_datapath *ld; SBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (dp, dp_table) { if (sbrec_datapath_binding_is_deleted(dp)) { @@ -1902,27 +1901,19 @@ runtime_data_sb_datapath_binding_handler(struct engine_node *node OVS_UNUSED, dp->tunnel_key)) { return false; } + + } + + if (sbrec_datapath_binding_is_updated( + dp, SBREC_DATAPATH_BINDING_COL_TUNNEL_KEY) && + !sbrec_datapath_binding_is_new(dp)) { /* If the tunnel key got updated, get_local_datapath will not find * the ld. Use get_local_datapath_no_hash which does not * rely on the hash. */ - if (sbrec_datapath_binding_is_updated( - dp, SBREC_DATAPATH_BINDING_COL_TUNNEL_KEY)) { - if (get_local_datapath_no_hash(&rt_data->local_datapaths, - dp->tunnel_key)) { - return false; - } - } - } else if (sbrec_datapath_binding_is_updated( - dp, SBREC_DATAPATH_BINDING_COL_TUNNEL_KEY) - && !sbrec_datapath_binding_is_new(dp)) { - /* If the tunnel key is updated, remove the entry (with a wrong - * hash) from the map. It will be (properly) added back later. - */ - if ((ld = get_local_datapath_no_hash(&rt_data->local_datapaths, - dp->tunnel_key))) { - hmap_remove(&rt_data->local_datapaths, &ld->hmap_node); - local_datapath_destroy(ld); + if (get_local_datapath_no_hash(&rt_data->local_datapaths, + dp->tunnel_key)) { + return false; } } } diff --git a/northd/northd.c b/northd/northd.c index 133cddb69..0cabda7ea 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -4550,6 +4550,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, op->visited = true; continue; } + + uint32_t old_tunnel_key = op->tunnel_key; if (!ls_port_reinit(op, ovnsb_idl_txn, new_nbsp, od, sb, ni->sbrec_mirror_table, @@ -4563,6 +4565,11 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn, goto fail; } add_op_to_northd_tracked_ports(&trk_lsps->updated, op); + + if (old_tunnel_key != op->tunnel_key) { + delete_fdb_entry(ni->sbrec_fdb_by_dp_and_port, od->tunnel_key, + old_tunnel_key); + } } op->visited = true; } diff --git a/tests/ovn.at b/tests/ovn.at index 79c9524c6..784b3dd1f 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -37472,6 +37472,8 @@ sim_add hv1 as hv1 check ovs-vsctl add-br br-phys ovn_attach n1 br-phys 192.168.0.11 +ovs-vsctl -- add-port br-int vif1 -- \ + set interface vif1 external-ids:iface-id=lsp1 check ovn-nbctl --wait=hv ls-add ls \ -- lsp-add ls lsp1 \ @@ -37484,6 +37486,56 @@ check ovn-nbctl --wait=hv ls-add ls \ addresses=router \ -- lrp-set-gateway-chassis lr-ls hv1 +dp_uuid=$(fetch_column datapath _uuid external_ids:name=lr) +ovn-sbctl create MAC_Binding ip=192.168.1.10 datapath=$dp_uuid logical_port=lr-ls mac='"00:00:00:00:00:01"' + +OVN_POPULATE_ARP +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +create_fdb() { + ls_key=$(fetch_column datapath tunnel_key external_ids:name=ls) + lsp_key=$(fetch_column port_binding tunnel_key logical_port=lsp1) + + ovn-sbctl create FDB mac='"00:00:00:00:00:01"' dp_key=$ls_key port_key=$lsp_key +} + +AS_BOX([Logical switch tunnel_key change]) +create_fdb + +check ovn-nbctl --wait=hv set Logical_Switch ls other_config:requested-tnl-key=10 +ovn-sbctl list datapath +CHECK_FLOWS_AFTER_RECOMPUTE([hv1], [hv1]) + +check_row_count FDB 0 mac='"00:00:00:00:00:01"' + +AS_BOX([Logical switch port tunnel_key change]) +create_fdb + +check ovn-nbctl --wait=hv set Logical_Switch_Port lsp1 options:requested-tnl-key=10 +CHECK_FLOWS_AFTER_RECOMPUTE([hv1], [hv1]) + +check_row_count FDB 0 mac='"00:00:00:00:00:01"' + +AS_BOX([Logical router tunnel_key change]) +check ovn-nbctl --wait=hv set Logical_Router lr options:requested-tnl-key=20 +CHECK_FLOWS_AFTER_RECOMPUTE([hv1], [hv1]) + +check_row_count Mac_Binding 1 ip=192.168.1.10 +AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep -c metadata=0x14], [0], [dnl +1 +]) + +AS_BOX([Logical router port tunnel_key change]) +check ovn-nbctl --wait=hv set Logical_Router_Port lr-ls options:requested-tnl-key=20 +CHECK_FLOWS_AFTER_RECOMPUTE([hv1], [hv1]) + +check_row_count Mac_Binding 1 ip=192.168.1.10 +AT_CHECK([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep -c reg14=0x14], [0], [dnl +1 +]) + +AS_BOX([Logical switch tunnel_key change, potential segfault]) sleep_controller hv1 check ovn-nbctl --wait=sb set Logical_Switch ls other_config:requested-tnl-key=1000 From patchwork Tue May 7 06:25:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1932228 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=MJ9iAO1t; dkim-atps=neutral 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=patchwork.ozlabs.org) 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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VYSvJ3HwJz20fX for ; Tue, 7 May 2024 16:25:32 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id A2FD882640; Tue, 7 May 2024 06:25:30 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id fR9Gxfxgig7m; Tue, 7 May 2024 06:25:29 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 38D1382433 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=MJ9iAO1t Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 38D1382433; Tue, 7 May 2024 06:25:29 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id DF5D9C0DD5; Tue, 7 May 2024 06:25:28 +0000 (UTC) X-Original-To: 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 2FA22C0037 for ; Tue, 7 May 2024 06:25:26 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 1F73460ABA for ; Tue, 7 May 2024 06:25:26 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id vPN2TwFqYBVp for ; Tue, 7 May 2024 06:25:25 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amusil@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp3.osuosl.org 4692260AB1 Authentication-Results: smtp3.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 4692260AB1 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=MJ9iAO1t 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 4692260AB1 for ; Tue, 7 May 2024 06:25:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1715063124; 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=wQObpHoDDrd2cPFA2QgEC3gj0lsw6Yj5Rs8pBvglcYc=; b=MJ9iAO1t/z2lEKCG6C7RGZCeNIei2m+9NdgiNxOtPyugOemwnVyWy8em+eYl8sRu7+N3fg TqAZSFDFFFXJ89Km4aD6IkHSPLVU4kpRCmcDlxErBYIXlzoLGyDi3veUpJqMNDltInS58B 7tkGKD7kGwi46D+XqRLySU1dHoyiYao= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-118-146Phs8JN4W9bxO9hukOHg-1; Tue, 07 May 2024 02:25:20 -0400 X-MC-Unique: 146Phs8JN4W9bxO9hukOHg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8C7851C03144; Tue, 7 May 2024 06:25:20 +0000 (UTC) Received: from amusil.brq.redhat.com (unknown [10.43.17.32]) by smtp.corp.redhat.com (Postfix) with ESMTP id D6C88C271B1; Tue, 7 May 2024 06:25:19 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Tue, 7 May 2024 08:25:15 +0200 Message-ID: <20240507062517.387329-3-amusil@redhat.com> In-Reply-To: <20240507062517.387329-1-amusil@redhat.com> References: <20240507062517.387329-1-amusil@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn v2 2/4] controller: Rename mac_cache to to mac-cache. 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 consistency rename the mac_cache.c/.h to mac-cache.c/.h. Acked-by: Mark Michelson Signed-off-by: Ales Musil --- v2: Rebase on top of main. --- controller/automake.mk | 4 ++-- controller/{mac_cache.c => mac-cache.c} | 2 +- controller/{mac_cache.h => mac-cache.h} | 2 +- controller/ovn-controller.c | 2 +- controller/statctrl.c | 2 +- controller/statctrl.h | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) rename controller/{mac_cache.c => mac-cache.c} (99%) rename controller/{mac_cache.h => mac-cache.h} (99%) diff --git a/controller/automake.mk b/controller/automake.mk index a17ff0d60..2eeca718a 100644 --- a/controller/automake.mk +++ b/controller/automake.mk @@ -46,8 +46,8 @@ controller_ovn_controller_SOURCES = \ controller/vif-plug.c \ controller/mirror.h \ controller/mirror.c \ - controller/mac_cache.h \ - controller/mac_cache.c \ + controller/mac-cache.h \ + controller/mac-cache.c \ controller/statctrl.h \ controller/statctrl.c diff --git a/controller/mac_cache.c b/controller/mac-cache.c similarity index 99% rename from controller/mac_cache.c rename to controller/mac-cache.c index 7e4feeed7..1515e0ec2 100644 --- a/controller/mac_cache.c +++ b/controller/mac-cache.c @@ -17,7 +17,7 @@ #include #include "lport.h" -#include "mac_cache.h" +#include "mac-cache.h" #include "openvswitch/hmap.h" #include "openvswitch/vlog.h" #include "ovn/logical-fields.h" diff --git a/controller/mac_cache.h b/controller/mac-cache.h similarity index 99% rename from controller/mac_cache.h rename to controller/mac-cache.h index ea8aa7c1b..644ac8be2 100644 --- a/controller/mac_cache.h +++ b/controller/mac-cache.h @@ -121,4 +121,4 @@ void mac_cache_fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, void mac_cache_stats_destroy(struct ovs_list *stats_list); -#endif /* controller/mac_cache.h */ +#endif /* controller/mac-cache.h */ diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 356ce881a..cde45e35e 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -83,7 +83,7 @@ #include "lib/ovn-l7.h" #include "hmapx.h" #include "mirror.h" -#include "mac_cache.h" +#include "mac-cache.h" #include "statctrl.h" #include "lib/dns-resolve.h" diff --git a/controller/statctrl.c b/controller/statctrl.c index 8cce97df8..cce31cce6 100644 --- a/controller/statctrl.c +++ b/controller/statctrl.c @@ -19,7 +19,7 @@ #include "dirs.h" #include "latch.h" #include "lflow.h" -#include "mac_cache.h" +#include "mac-cache.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-flow.h" #include "openvswitch/ofp-msgs.h" diff --git a/controller/statctrl.h b/controller/statctrl.h index c5cede353..f34da6bde 100644 --- a/controller/statctrl.h +++ b/controller/statctrl.h @@ -16,7 +16,7 @@ #ifndef STATCTRL_H #define STATCTRL_H -#include "mac_cache.h" +#include "mac-cache.h" void statctrl_init(void); void statctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, From patchwork Tue May 7 06:25:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1932230 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=LWUN3ysg; dkim-atps=neutral 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=patchwork.ozlabs.org) 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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VYSvd6q2Gz1xnS for ; Tue, 7 May 2024 16:25:49 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 1E1DE8301F; Tue, 7 May 2024 06:25:48 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 25IjMEtbEGuz; Tue, 7 May 2024 06:25:39 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org B24C482AED 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=LWUN3ysg Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id B24C482AED; Tue, 7 May 2024 06:25:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 66F8FC0DD6; Tue, 7 May 2024 06:25:39 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 284C5C008E for ; Tue, 7 May 2024 06:25:37 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id AA97E4080B for ; Tue, 7 May 2024 06:25:35 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 13aXppkK2zIr for ; Tue, 7 May 2024 06:25:28 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amusil@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp4.osuosl.org BD59E407B1 Authentication-Results: smtp4.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org BD59E407B1 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=LWUN3ysg 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 BD59E407B1 for ; Tue, 7 May 2024 06:25:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1715063125; 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=S5Fzad+FKpHyjJX13Z0hGdinCuoEHuHuo2+l0erKxNc=; b=LWUN3ysghjQLLcYQxZLnrQQyalMAs9Ok4BhWqqEQELQ3ed6EsqavQVcHeRoYH7PzGXcbIb ca1+ZIrb1TK5ufi8KoLyX45th0hs7DxVCj+82syXWC7E+o1zBEHnOgXUTZ7DWvCNkJjS0K qqPk4DU/e5CDt976eFft2NdimchYZfg= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-21-Ll_TIqgjO1W_vBbfOkrANQ-1; Tue, 07 May 2024 02:25:22 -0400 X-MC-Unique: Ll_TIqgjO1W_vBbfOkrANQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id ABA181005055; Tue, 7 May 2024 06:25:21 +0000 (UTC) Received: from amusil.brq.redhat.com (unknown [10.43.17.32]) by smtp.corp.redhat.com (Postfix) with ESMTP id BFF0AC271B4; Tue, 7 May 2024 06:25:20 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Tue, 7 May 2024 08:25:16 +0200 Message-ID: <20240507062517.387329-4-amusil@redhat.com> In-Reply-To: <20240507062517.387329-1-amusil@redhat.com> References: <20240507062517.387329-1-amusil@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn v2 3/4] controller: Merge the mac-cache and mac-learn. 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" Merge mac-cache and mac-learn into single module. Both of those modules contained very similar functionality with some small differences. By merging those we have unified interface to deal with FDB and MAC binding. Acked-by: Mark Michelson Signed-off-by: Ales Musil --- v2: Rebase on top of main. --- controller/automake.mk | 2 - controller/mac-cache.c | 588 ++++++++++++++++++++++++------------ controller/mac-cache.h | 165 +++++++--- controller/mac-learn.c | 482 ----------------------------- controller/mac-learn.h | 145 --------- controller/ovn-controller.c | 104 +++++-- controller/pinctrl.c | 165 +++++----- controller/statctrl.c | 5 +- 8 files changed, 697 insertions(+), 959 deletions(-) delete mode 100644 controller/mac-learn.c delete mode 100644 controller/mac-learn.h diff --git a/controller/automake.mk b/controller/automake.mk index 2eeca718a..1b1b3aeb1 100644 --- a/controller/automake.mk +++ b/controller/automake.mk @@ -36,8 +36,6 @@ controller_ovn_controller_SOURCES = \ controller/ovn-controller.h \ controller/physical.c \ controller/physical.h \ - controller/mac-learn.c \ - controller/mac-learn.h \ controller/local_data.c \ controller/local_data.h \ controller/ovsport.h \ diff --git a/controller/mac-cache.c b/controller/mac-cache.c index 1515e0ec2..c52f913ce 100644 --- a/controller/mac-cache.c +++ b/controller/mac-cache.c @@ -25,29 +25,20 @@ VLOG_DEFINE_THIS_MODULE(mac_cache); +#define MAX_BUFFERED_PACKETS 1000 +#define BUFFER_QUEUE_DEPTH 4 +#define BUFFERED_PACKETS_TIMEOUT_MS 10000 +#define BUFFERED_PACKETS_LOOKUP_MS 100 + static uint32_t -mac_cache_mb_data_hash(const struct mac_cache_mb_data *mb_data); +mac_binding_data_hash(const struct mac_binding_data *mb_data); static inline bool -mac_cache_mb_data_equals(const struct mac_cache_mb_data *a, - const struct mac_cache_mb_data *b); -static struct mac_cache_mac_binding * -mac_cache_mac_binding_find(struct mac_cache_data *data, - const struct mac_cache_mb_data *mb_data); -static bool -mac_cache_mb_data_from_sbrec(struct mac_cache_mb_data *data, - const struct sbrec_mac_binding *mb, - struct ovsdb_idl_index *sbrec_pb_by_name); +mac_binding_data_equals(const struct mac_binding_data *a, + const struct mac_binding_data *b); static uint32_t -mac_cache_fdb_data_hash(const struct mac_cache_fdb_data *fdb_data); +fdb_data_hash(const struct fdb_data *fdb_data); static inline bool -mac_cache_fdb_data_equals(const struct mac_cache_fdb_data *a, - const struct mac_cache_fdb_data *b); -static bool -mac_cache_fdb_data_from_sbrec(struct mac_cache_fdb_data *data, - const struct sbrec_fdb *fdb); -static struct mac_cache_fdb * -mac_cache_fdb_find(struct mac_cache_data *data, - const struct mac_cache_fdb_data *fdb_data); +fdb_data_equals(const struct fdb_data *a, const struct fdb_data *b); static struct mac_cache_threshold * mac_cache_threshold_find(struct hmap *thresholds, const struct uuid *uuid); static uint64_t @@ -59,6 +50,23 @@ mac_cache_threshold_remove(struct hmap *thresholds, static void mac_cache_update_req_delay(struct hmap *thresholds, uint64_t *req_delay); +static struct buffered_packets * +buffered_packets_find(struct buffered_packets_ctx *ctx, + const struct mac_binding_data *mb_data); + +static void +buffered_packets_remove(struct buffered_packets_ctx *ctx, + struct buffered_packets *bp); + +static void +buffered_packets_db_lookup(struct buffered_packets *bp, + struct ds *ip, struct eth_addr *mac, + struct ovsdb_idl_index *sbrec_pb_by_key, + struct ovsdb_idl_index *sbrec_dp_by_key, + struct ovsdb_idl_index *sbrec_pb_by_name, + struct ovsdb_idl_index *sbrec_mb_by_lport_ip); + +/* Thresholds. */ bool mac_cache_threshold_add(struct mac_cache_data *data, const struct sbrec_datapath_binding *dp, @@ -113,50 +121,78 @@ mac_cache_thresholds_clear(struct mac_cache_data *data) } } -void -mac_cache_mac_binding_add(struct mac_cache_data *data, - const struct sbrec_mac_binding *mb, - struct ovsdb_idl_index *sbrec_pb_by_name) -{ - struct mac_cache_mb_data mb_data; - if (!mac_cache_mb_data_from_sbrec(&mb_data, mb, sbrec_pb_by_name)) { - return; - } +/* MAC binding. */ +struct mac_binding * +mac_binding_add(struct hmap *map, struct mac_binding_data mb_data, + long long timestamp) { - struct mac_cache_mac_binding *mc_mb = mac_cache_mac_binding_find(data, - &mb_data); - if (!mc_mb) { - mc_mb = xmalloc(sizeof *mc_mb); - hmap_insert(&data->mac_bindings, &mc_mb->hmap_node, - mac_cache_mb_data_hash(&mb_data)); + struct mac_binding *mb = mac_binding_find(map, &mb_data); + if (!mb) { + mb = xmalloc(sizeof *mb); + mb->sbrec_mb = NULL; + hmap_insert(map, &mb->hmap_node, mac_binding_data_hash(&mb_data)); } - mc_mb->sbrec_mb = mb; - mc_mb->data = mb_data; + mb->data = mb_data; + mb->timestamp = timestamp; + + return mb; } void -mac_cache_mac_binding_remove(struct mac_cache_data *data, - const struct sbrec_mac_binding *mb, - struct ovsdb_idl_index *sbrec_pb_by_name) -{ - struct mac_cache_mb_data mb_data; - if (!mac_cache_mb_data_from_sbrec(&mb_data, mb, sbrec_pb_by_name)) { - return; +mac_binding_remove(struct hmap *map, struct mac_binding *mb) { + hmap_remove(map, &mb->hmap_node); + free(mb); +} + +struct mac_binding * +mac_binding_find(const struct hmap *map, + const struct mac_binding_data *mb_data) { + uint32_t hash = mac_binding_data_hash(mb_data); + + struct mac_binding *mb; + HMAP_FOR_EACH_WITH_HASH (mb, hmap_node, hash, map) { + if (mac_binding_data_equals(&mb->data, mb_data)) { + return mb; + } } - struct mac_cache_mac_binding *mc_mb = mac_cache_mac_binding_find(data, - &mb_data); - if (!mc_mb) { - return; + return NULL; +} + +bool +mac_binding_data_from_sbrec(struct mac_binding_data *data, + const struct sbrec_mac_binding *mb, + struct ovsdb_idl_index *sbrec_pb_by_name) +{ + const struct sbrec_port_binding *pb = + lport_lookup_by_name(sbrec_pb_by_name, mb->logical_port); + + if (!pb || !pb->datapath || !ip46_parse(mb->ip, &data->ip) || + !eth_addr_from_string(mb->mac, &data->mac)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Couldn't parse MAC binding: ip=%s, mac=%s, " + "logical_port=%s", mb->ip, mb->mac, mb->logical_port); + return false; } - hmap_remove(&data->mac_bindings, &mc_mb->hmap_node); - free(mc_mb); + data->dp_key = mb->datapath->tunnel_key; + data->port_key = pb->tunnel_key; + + return true; +} + +void +mac_bindings_clear(struct hmap *map) +{ + struct mac_binding *mb; + HMAP_FOR_EACH_POP (mb, hmap_node, map) { + free(mb); + } } bool -mac_cache_sb_mac_binding_updated(const struct sbrec_mac_binding *mb) +sb_mac_binding_updated(const struct sbrec_mac_binding *mb) { bool updated = false; for (size_t i = 0; i < SBREC_MAC_BINDING_N_COLUMNS; i++) { @@ -171,56 +207,78 @@ mac_cache_sb_mac_binding_updated(const struct sbrec_mac_binding *mb) return updated || sbrec_mac_binding_is_deleted(mb); } -void -mac_cache_mac_bindings_clear(struct mac_cache_data *data) -{ - struct mac_cache_mac_binding *mc_mb; - HMAP_FOR_EACH_POP (mc_mb, hmap_node, &data->mac_bindings) { - free(mc_mb); +const struct sbrec_mac_binding * +mac_binding_lookup(struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, + const char *logical_port, const char *ip) { + struct sbrec_mac_binding *mb = + sbrec_mac_binding_index_init_row(sbrec_mac_binding_by_lport_ip); + sbrec_mac_binding_index_set_logical_port(mb, logical_port); + sbrec_mac_binding_index_set_ip(mb, ip); + + const struct sbrec_mac_binding *retval = + sbrec_mac_binding_index_find(sbrec_mac_binding_by_lport_ip, mb); + + sbrec_mac_binding_index_destroy_row(mb); + + return retval; +} + +/* FDB. */ +struct fdb * +fdb_add(struct hmap *map, struct fdb_data fdb_data) { + struct fdb *fdb = fdb_find(map, &fdb_data); + + if (!fdb) { + fdb = xmalloc(sizeof *fdb); + fdb->sbrec_fdb = NULL; + fdb->dp_uuid = UUID_ZERO; + hmap_insert(map, &fdb->hmap_node, fdb_data_hash(&fdb_data)); } + + fdb->data = fdb_data; + + return fdb; } void -mac_cache_fdb_add(struct mac_cache_data *data, const struct sbrec_fdb *fdb, - struct uuid dp_uuid) +fdb_remove(struct hmap *map, struct fdb *fdb) { - struct mac_cache_fdb_data fdb_data; - if (!mac_cache_fdb_data_from_sbrec(&fdb_data, fdb)) { - return; - } - - struct mac_cache_fdb *mc_fdb = mac_cache_fdb_find(data, &fdb_data); + hmap_remove(map, &fdb->hmap_node); + free(fdb); +} - if (!mc_fdb) { - mc_fdb = xmalloc(sizeof *mc_fdb); - hmap_insert(&data->fdbs, &mc_fdb->hmap_node, - mac_cache_fdb_data_hash(&fdb_data)); +bool +fdb_data_from_sbrec(struct fdb_data *data, const struct sbrec_fdb *fdb) +{ + if (!eth_addr_from_string(fdb->mac, &data->mac)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Couldn't parse FDB: mac=%s", fdb->mac); + return false; } - mc_fdb->sbrec_fdb = fdb; - mc_fdb->data = fdb_data; - mc_fdb->dp_uuid = dp_uuid; + data->dp_key = fdb->dp_key; + data->port_key = fdb->port_key; + + return true; } -void -mac_cache_fdb_remove(struct mac_cache_data *data, const struct sbrec_fdb *fdb) +struct fdb * +fdb_find(const struct hmap *map, const struct fdb_data *fdb_data) { - struct mac_cache_fdb_data fdb_data; - if (!mac_cache_fdb_data_from_sbrec(&fdb_data, fdb)) { - return; - } + uint32_t hash = fdb_data_hash(fdb_data); - struct mac_cache_fdb *mc_fdb = mac_cache_fdb_find(data, &fdb_data); - if (!mc_fdb) { - return; + struct fdb *fdb; + HMAP_FOR_EACH_WITH_HASH (fdb, hmap_node, hash, map) { + if (fdb_data_equals(&fdb->data, fdb_data)) { + return fdb; + } } - hmap_remove(&data->fdbs, &mc_fdb->hmap_node); - free(mc_fdb); + return NULL; } bool -mac_cache_sb_fdb_updated(const struct sbrec_fdb *fdb) +sb_fdb_updated(const struct sbrec_fdb *fdb) { bool updated = false; for (size_t i = 0; i < SBREC_FDB_N_COLUMNS; i++) { @@ -236,11 +294,11 @@ mac_cache_sb_fdb_updated(const struct sbrec_fdb *fdb) } void -mac_cache_fdbs_clear(struct mac_cache_data *data) +fdbs_clear(struct hmap *map) { - struct mac_cache_fdb *mc_fdb; - HMAP_FOR_EACH_POP (mc_fdb, hmap_node, &data->fdbs) { - free(mc_fdb); + struct fdb *fdb; + HMAP_FOR_EACH_POP (fdb, hmap_node, map) { + free(fdb); } } @@ -251,20 +309,21 @@ struct mac_cache_stats { union { /* Common data to identify MAC binding. */ - struct mac_cache_mb_data mb; + struct mac_binding_data mb; /* Common data to identify FDB. */ - struct mac_cache_fdb_data fdb; + struct fdb_data fdb; } data; }; +/* MAC binding stat processing. */ void -mac_cache_mb_stats_process_flow_stats(struct ovs_list *stats_list, - struct ofputil_flow_stats *ofp_stats) +mac_binding_stats_process_flow_stats(struct ovs_list *stats_list, + struct ofputil_flow_stats *ofp_stats) { struct mac_cache_stats *stats = xmalloc(sizeof *stats); stats->idle_age_ms = ofp_stats->idle_age * 1000; - stats->data.mb = (struct mac_cache_mb_data) { + stats->data.mb = (struct mac_binding_data) { .port_key = ofp_stats->match.flow.regs[MFF_LOG_INPORT - MFF_REG0], .dp_key = ntohll(ofp_stats->match.flow.metadata), .mac = ofp_stats->match.flow.dl_src @@ -280,8 +339,8 @@ mac_cache_mb_stats_process_flow_stats(struct ovs_list *stats_list, } void -mac_cache_mb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, - void *data) +mac_binding_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, + void *data) { struct mac_cache_data *cache_data = data; struct hmap *thresholds = &cache_data->thresholds[MAC_CACHE_MAC_BINDING]; @@ -289,14 +348,14 @@ mac_cache_mb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, struct mac_cache_stats *stats; LIST_FOR_EACH_POP (stats, list_node, stats_list) { - struct mac_cache_mac_binding *mc_mb = - mac_cache_mac_binding_find(cache_data, &stats->data.mb); - if (!mc_mb) { + struct mac_binding *mb = mac_binding_find(&cache_data->mac_bindings, + &stats->data.mb); + if (!mb) { free(stats); continue; } - struct uuid *dp_uuid = &mc_mb->sbrec_mb->datapath->header_.uuid; + struct uuid *dp_uuid = &mb->sbrec_mb->datapath->header_.uuid; struct mac_cache_threshold *threshold = mac_cache_threshold_find(thresholds, dp_uuid); @@ -304,9 +363,9 @@ mac_cache_mb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, * used on this chassis. Also make sure that we don't update the * timestamp more than once during the dump period. */ if (stats->idle_age_ms < threshold->value && - (timewall_now - mc_mb->sbrec_mb->timestamp) >= + (timewall_now - mb->sbrec_mb->timestamp) >= threshold->dump_period) { - sbrec_mac_binding_set_timestamp(mc_mb->sbrec_mb, timewall_now); + sbrec_mac_binding_set_timestamp(mb->sbrec_mb, timewall_now); } free(stats); @@ -315,14 +374,15 @@ mac_cache_mb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, mac_cache_update_req_delay(thresholds, req_delay); } +/* FDB stat processing. */ void -mac_cache_fdb_stats_process_flow_stats(struct ovs_list *stats_list, - struct ofputil_flow_stats *ofp_stats) +fdb_stats_process_flow_stats(struct ovs_list *stats_list, + struct ofputil_flow_stats *ofp_stats) { struct mac_cache_stats *stats = xmalloc(sizeof *stats); stats->idle_age_ms = ofp_stats->idle_age * 1000; - stats->data.fdb = (struct mac_cache_fdb_data) { + stats->data.fdb = (struct fdb_data) { .port_key = ofp_stats->match.flow.regs[MFF_LOG_INPORT - MFF_REG0], .dp_key = ntohll(ofp_stats->match.flow.metadata), .mac = ofp_stats->match.flow.dl_src @@ -332,8 +392,8 @@ mac_cache_fdb_stats_process_flow_stats(struct ovs_list *stats_list, } void -mac_cache_fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, - void *data) +fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, + void *data) { struct mac_cache_data *cache_data = data; struct hmap *thresholds = &cache_data->thresholds[MAC_CACHE_FDB]; @@ -341,22 +401,22 @@ mac_cache_fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, struct mac_cache_stats *stats; LIST_FOR_EACH_POP (stats, list_node, stats_list) { - struct mac_cache_fdb *mc_fdb = mac_cache_fdb_find(cache_data, - &stats->data.fdb); - if (!mc_fdb) { + struct fdb *fdb = fdb_find(&cache_data->fdbs, &stats->data.fdb); + + if (!fdb) { free(stats); continue; } struct mac_cache_threshold *threshold = - mac_cache_threshold_find(thresholds, &mc_fdb->dp_uuid); + mac_cache_threshold_find(thresholds, &fdb->dp_uuid); /* If "idle_age" is under threshold it means that the mac binding is * used on this chassis. Also make sure that we don't update the * timestamp more than once during the dump period. */ if (stats->idle_age_ms < threshold->value && - (timewall_now - mc_fdb->sbrec_fdb->timestamp) >= + (timewall_now - fdb->sbrec_fdb->timestamp) >= threshold->dump_period) { - sbrec_fdb_set_timestamp(mc_fdb->sbrec_fdb, timewall_now); + sbrec_fdb_set_timestamp(fdb->sbrec_fdb, timewall_now); } free(stats); @@ -365,130 +425,207 @@ mac_cache_fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, mac_cache_update_req_delay(thresholds, req_delay); } +/* Packet buffering. */ +struct bp_packet_data * +bp_packet_data_create(const struct ofputil_packet_in *pin, + const struct ofpbuf *continuation) { + struct bp_packet_data *pd = xmalloc(sizeof *pd); + + pd->pin = (struct ofputil_packet_in) { + .packet = xmemdup(pin->packet, pin->packet_len), + .packet_len = pin->packet_len, + .flow_metadata = pin->flow_metadata, + .reason = pin->reason, + .table_id = pin->table_id, + .cookie = pin->cookie, + /* Userdata are empty on purpose, + * it is not needed for the continuation. */ + .userdata = NULL, + .userdata_len = 0, + }; + pd->continuation = ofpbuf_clone(continuation); + + return pd; +} + + void -mac_cache_stats_destroy(struct ovs_list *stats_list) -{ - struct mac_cache_stats *stats; - LIST_FOR_EACH_POP (stats, list_node, stats_list) { - free(stats); - } +bp_packet_data_destroy(struct bp_packet_data *pd) { + free(pd->pin.packet); + ofpbuf_delete(pd->continuation); + free(pd); } -static uint32_t -mac_cache_mb_data_hash(const struct mac_cache_mb_data *mb_data) -{ - uint32_t hash = 0; +struct buffered_packets * +buffered_packets_add(struct buffered_packets_ctx *ctx, + struct mac_binding_data mb_data) { + uint32_t hash = mac_binding_data_hash(&mb_data); - hash = hash_add(hash, mb_data->port_key); - hash = hash_add(hash, mb_data->dp_key); - hash = hash_add_in6_addr(hash, &mb_data->ip); - hash = hash_add64(hash, eth_addr_to_uint64(mb_data->mac)); + struct buffered_packets *bp = buffered_packets_find(ctx, &mb_data); + if (!bp) { + if (hmap_count(&ctx->buffered_packets) >= MAX_BUFFERED_PACKETS) { + return NULL; + } + + bp = xmalloc(sizeof *bp); + hmap_insert(&ctx->buffered_packets, &bp->hmap_node, hash); + bp->mb_data = mb_data; + /* Schedule the freshly added buffered packet to do lookup + * immediately. */ + bp->lookup_at_ms = 0; + ovs_list_init(&bp->queue); + } - return hash_finish(hash, 32); + bp->expire_at_ms = time_msec() + BUFFERED_PACKETS_TIMEOUT_MS; + + return bp; } -static inline bool -mac_cache_mb_data_equals(const struct mac_cache_mb_data *a, - const struct mac_cache_mb_data *b) -{ - return a->port_key == b->port_key && - a->dp_key == b->dp_key && - ipv6_addr_equals(&a->ip, &b->ip) && - eth_addr_equals(a->mac, b->mac); +void +buffered_packets_packet_data_enqueue(struct buffered_packets *bp, + struct bp_packet_data *pd) { + if (ovs_list_size(&bp->queue) == BUFFER_QUEUE_DEPTH) { + struct bp_packet_data *p = CONTAINER_OF(ovs_list_pop_front(&bp->queue), + struct bp_packet_data, node); + + bp_packet_data_destroy(p); + } + ovs_list_push_back(&bp->queue, &pd->node); } -static bool -mac_cache_mb_data_from_sbrec(struct mac_cache_mb_data *data, - const struct sbrec_mac_binding *mb, - struct ovsdb_idl_index *sbrec_pb_by_name) -{ - const struct sbrec_port_binding *pb = - lport_lookup_by_name(sbrec_pb_by_name, mb->logical_port); +void +buffered_packets_ctx_run(struct buffered_packets_ctx *ctx, + const struct hmap *recent_mbs, + struct ovsdb_idl_index *sbrec_pb_by_key, + struct ovsdb_idl_index *sbrec_dp_by_key, + struct ovsdb_idl_index *sbrec_pb_by_name, + struct ovsdb_idl_index *sbrec_mb_by_lport_ip) { + struct ds ip = DS_EMPTY_INITIALIZER; + long long now = time_msec(); + + struct buffered_packets *bp; + HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) { + struct eth_addr mac = eth_addr_zero; + /* Remove expired buffered packets. */ + if (now > bp->expire_at_ms) { + buffered_packets_remove(ctx, bp); + continue; + } - if (!pb || !pb->datapath || !ip46_parse(mb->ip, &data->ip) || - !eth_addr_from_string(mb->mac, &data->mac)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Couldn't parse MAC binding: ip=%s, mac=%s, " - "logical_port=%s", mb->ip, mb->mac, mb->logical_port); - return false; + struct mac_binding *mb = mac_binding_find(recent_mbs, &bp->mb_data); + if (mb) { + mac = mb->data.mac; + } else if (now >= bp->lookup_at_ms) { + /* Check if we can do a full lookup. */ + buffered_packets_db_lookup(bp, &ip, &mac, sbrec_pb_by_key, + sbrec_dp_by_key, sbrec_pb_by_name, + sbrec_mb_by_lport_ip); + /* Schedule next lookup even if we found the MAC address, + * if the address was found this struct will be deleted anyway. */ + bp->lookup_at_ms = now + BUFFERED_PACKETS_LOOKUP_MS; + } + + if (eth_addr_is_zero(mac)) { + continue; + } + + struct bp_packet_data *pd; + LIST_FOR_EACH_POP (pd, node, &bp->queue) { + struct dp_packet packet; + dp_packet_use_const(&packet, pd->pin.packet, pd->pin.packet_len); + + struct eth_header *eth = dp_packet_data(&packet); + eth->eth_dst = mac; + + ovs_list_push_back(&ctx->ready_packets_data, &pd->node); + } + + buffered_packets_remove(ctx, bp); } - data->dp_key = mb->datapath->tunnel_key; - data->port_key = pb->tunnel_key; + ds_destroy(&ip); +} - return true; +bool +buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx) { + return !ovs_list_is_empty(&ctx->ready_packets_data); } -static struct mac_cache_mac_binding * -mac_cache_mac_binding_find(struct mac_cache_data *data, - const struct mac_cache_mb_data *mb_data) -{ - uint32_t hash = mac_cache_mb_data_hash(mb_data); +bool +buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx) { + return !hmap_is_empty(&ctx->buffered_packets); +} - struct mac_cache_mac_binding *mb; - HMAP_FOR_EACH_WITH_HASH (mb, hmap_node, hash, &data->mac_bindings) { - if (mac_cache_mb_data_equals(&mb->data, mb_data)) { - return mb; - } +void +buffered_packets_ctx_init(struct buffered_packets_ctx *ctx) { + hmap_init(&ctx->buffered_packets); + ovs_list_init(&ctx->ready_packets_data); +} + +void +buffered_packets_ctx_destroy(struct buffered_packets_ctx *ctx) { + struct bp_packet_data *pd; + LIST_FOR_EACH_POP (pd, node, &ctx->ready_packets_data) { + bp_packet_data_destroy(pd); } - return NULL; + struct buffered_packets *bp; + HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) { + buffered_packets_remove(ctx, bp); + } + hmap_destroy(&ctx->buffered_packets); +} + + +void +mac_cache_stats_destroy(struct ovs_list *stats_list) +{ + struct mac_cache_stats *stats; + LIST_FOR_EACH_POP (stats, list_node, stats_list) { + free(stats); + } } static uint32_t -mac_cache_fdb_data_hash(const struct mac_cache_fdb_data *fdb_data) +mac_binding_data_hash(const struct mac_binding_data *mb_data) { uint32_t hash = 0; - hash = hash_add(hash, fdb_data->port_key); - hash = hash_add(hash, fdb_data->dp_key); - hash = hash_add64(hash, eth_addr_to_uint64(fdb_data->mac)); + hash = hash_add(hash, mb_data->port_key); + hash = hash_add(hash, mb_data->dp_key); + hash = hash_add_in6_addr(hash, &mb_data->ip); - return hash_finish(hash, 16); + return hash_finish(hash, 24); } static inline bool -mac_cache_fdb_data_equals(const struct mac_cache_fdb_data *a, - const struct mac_cache_fdb_data *b) +mac_binding_data_equals(const struct mac_binding_data *a, + const struct mac_binding_data *b) { return a->port_key == b->port_key && a->dp_key == b->dp_key && - eth_addr_equals(a->mac, b->mac); + ipv6_addr_equals(&a->ip, &b->ip); } -static bool -mac_cache_fdb_data_from_sbrec(struct mac_cache_fdb_data *data, - const struct sbrec_fdb *fdb) +static uint32_t +fdb_data_hash(const struct fdb_data *fdb_data) { + uint32_t hash = 0; - if (!eth_addr_from_string(fdb->mac, &data->mac)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Couldn't parse FDB: mac=%s", fdb->mac); - return false; - } - - data->dp_key = fdb->dp_key; - data->port_key = fdb->port_key; + hash = hash_add(hash, fdb_data->dp_key); + hash = hash_add64(hash, eth_addr_to_uint64(fdb_data->mac)); - return true; + return hash_finish(hash, 12); } -static struct mac_cache_fdb * -mac_cache_fdb_find(struct mac_cache_data *data, - const struct mac_cache_fdb_data *fdb_data) +static inline bool +fdb_data_equals(const struct fdb_data *a, const struct fdb_data *b) { - uint32_t hash = mac_cache_fdb_data_hash(fdb_data); - - struct mac_cache_fdb *fdb; - HMAP_FOR_EACH_WITH_HASH (fdb, hmap_node, hash, &data->fdbs) { - if (mac_cache_fdb_data_equals(&fdb->data, fdb_data)) { - return fdb; - } - } - - return NULL; + return a->dp_key == b->dp_key && + eth_addr_equals(a->mac, b->mac); } + static struct mac_cache_threshold * mac_cache_threshold_find(struct hmap *thresholds, const struct uuid *uuid) { @@ -545,3 +682,66 @@ mac_cache_update_req_delay(struct hmap *thresholds, uint64_t *req_delay) *req_delay = dump_period < UINT64_MAX ? dump_period : 0; } + +static struct buffered_packets * +buffered_packets_find(struct buffered_packets_ctx *ctx, + const struct mac_binding_data *mb_data) { + uint32_t hash = mac_binding_data_hash(mb_data); + + struct buffered_packets *bp; + HMAP_FOR_EACH_WITH_HASH (bp, hmap_node, hash, &ctx->buffered_packets) { + if (mac_binding_data_equals(&bp->mb_data, mb_data)) { + return bp; + } + } + + return NULL; +} + +static void +buffered_packets_remove(struct buffered_packets_ctx *ctx, + struct buffered_packets *bp) { + struct bp_packet_data *pd; + LIST_FOR_EACH_POP (pd, node, &bp->queue) { + bp_packet_data_destroy(pd); + } + + hmap_remove(&ctx->buffered_packets, &bp->hmap_node); + free(bp); +} + +static void +buffered_packets_db_lookup(struct buffered_packets *bp, struct ds *ip, + struct eth_addr *mac, + struct ovsdb_idl_index *sbrec_pb_by_key, + struct ovsdb_idl_index *sbrec_dp_by_key, + struct ovsdb_idl_index *sbrec_pb_by_name, + struct ovsdb_idl_index *sbrec_mb_by_lport_ip) { + const struct sbrec_port_binding *pb = + lport_lookup_by_key(sbrec_dp_by_key, sbrec_pb_by_key, + bp->mb_data.dp_key, bp->mb_data.port_key); + if (!pb) { + return; + } + + if (!strcmp(pb->type, "chassisredirect")) { + const char *dgp_name = + smap_get_def(&pb->options, "distributed-port", ""); + pb = lport_lookup_by_name(sbrec_pb_by_name, dgp_name); + if (!pb) { + return; + } + } + + ipv6_format_mapped(&bp->mb_data.ip, ip); + const struct sbrec_mac_binding *smb = + mac_binding_lookup(sbrec_mb_by_lport_ip, pb->logical_port, + ds_cstr_ro(ip)); + ds_clear(ip); + + if (!smb) { + return; + } + + eth_addr_from_string(smb->mac, mac); +} diff --git a/controller/mac-cache.h b/controller/mac-cache.h index 644ac8be2..932f6cfd4 100644 --- a/controller/mac-cache.h +++ b/controller/mac-cache.h @@ -18,9 +18,16 @@ #include +#include "dp-packet.h" #include "openvswitch/hmap.h" -#include "ovn-sb-idl.h" +#include "openvswitch/hmap.h" +#include "openvswitch/list.h" +#include "openvswitch/ofpbuf.h" #include "openvswitch/ofp-flow.h" +#include "openvswitch/ofp-packet.h" +#include "ovn-sb-idl.h" + +struct ovsdb_idl_index; enum mac_cache_type { MAC_CACHE_MAC_BINDING, @@ -49,37 +56,73 @@ struct mac_cache_threshold { uint64_t dump_period; }; -struct mac_cache_mb_data { +struct mac_binding_data { + /* Keys. */ uint32_t port_key; uint32_t dp_key; struct in6_addr ip; + /* Value. */ struct eth_addr mac; }; -struct mac_cache_mac_binding { +struct mac_binding { struct hmap_node hmap_node; /* Common data to identify MAC binding. */ - struct mac_cache_mb_data data; - /* Reference to the SB MAC binding record. */ + struct mac_binding_data data; + /* Reference to the SB MAC binding record (Might be NULL). */ const struct sbrec_mac_binding *sbrec_mb; + /* User specified timestamp (in ms) */ + long long timestamp; }; -struct mac_cache_fdb_data { - uint32_t port_key; +struct fdb_data { + /* Keys. */ uint32_t dp_key; struct eth_addr mac; + /* Value. */ + uint32_t port_key; }; -struct mac_cache_fdb { +struct fdb { struct hmap_node hmap_node; /* Common data to identify FDB. */ - struct mac_cache_fdb_data data; + struct fdb_data data; /* Reference to the SB FDB record. */ const struct sbrec_fdb *sbrec_fdb; /* UUID of datapath for this FDB record. */ struct uuid dp_uuid; }; +struct bp_packet_data { + struct ovs_list node; + + struct ofpbuf *continuation; + struct ofputil_packet_in pin; +}; + +struct buffered_packets { + struct hmap_node hmap_node; + + struct mac_binding_data mb_data; + + /* Queue of packet_data associated with this struct. */ + struct ovs_list queue; + + /* Timestamp in ms when the buffered packet should expire. */ + long long int expire_at_ms; + + /* Timestamp in ms when the buffered packet should do full SB lookup.*/ + long long int lookup_at_ms; +}; + +struct buffered_packets_ctx { + /* Map of all buffered packets waiting for the MAC address. */ + struct hmap buffered_packets; + /* List of packet data that are ready to be sent. */ + struct ovs_list ready_packets_data; +}; + +/* Thresholds. */ bool mac_cache_threshold_add(struct mac_cache_data *data, const struct sbrec_datapath_binding *dp, enum mac_cache_type type); @@ -87,38 +130,86 @@ bool mac_cache_threshold_replace(struct mac_cache_data *data, const struct sbrec_datapath_binding *dp, enum mac_cache_type type); void mac_cache_thresholds_clear(struct mac_cache_data *data); -void mac_cache_mac_binding_add(struct mac_cache_data *data, - const struct sbrec_mac_binding *mb, - struct ovsdb_idl_index *sbrec_pb_by_name); -struct mac_cache_mac_binding * -mac_cachce_mac_binding_find(struct mac_cache_data *data, - const struct sbrec_mac_binding *mb, - struct ovsdb_idl_index *sbrec_pb_by_name); -void mac_cache_mac_binding_remove(struct mac_cache_data *data, - const struct sbrec_mac_binding *mb, - struct ovsdb_idl_index *sbrec_pb_by_name); -void mac_cache_mac_bindings_clear(struct mac_cache_data *data); -bool mac_cache_sb_mac_binding_updated(const struct sbrec_mac_binding *mb); - -void mac_cache_fdb_add(struct mac_cache_data *data, - const struct sbrec_fdb *fdb, struct uuid dp_uuid); -void mac_cache_fdb_remove(struct mac_cache_data *data, - const struct sbrec_fdb *fdb); -bool mac_cache_sb_fdb_updated(const struct sbrec_fdb *fdb); -void mac_cache_fdbs_clear(struct mac_cache_data *data); -void -mac_cache_mb_stats_process_flow_stats(struct ovs_list *stats_list, - struct ofputil_flow_stats *ofp_stats); -void mac_cache_mb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, - void *data); +/* MAC binding. */ +struct mac_binding *mac_binding_add(struct hmap *map, + struct mac_binding_data mb_data, + long long timestamp); + +void mac_binding_remove(struct hmap *map, struct mac_binding *mb); + +struct mac_binding *mac_binding_find(const struct hmap *map, + const struct mac_binding_data *mb_data); + +bool mac_binding_data_from_sbrec(struct mac_binding_data *data, + const struct sbrec_mac_binding *mb, + struct ovsdb_idl_index *sbrec_pb_by_name); +void mac_bindings_clear(struct hmap *map); + +bool sb_mac_binding_updated(const struct sbrec_mac_binding *mb); + +const struct sbrec_mac_binding * +mac_binding_lookup(struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, + const char *logical_port, const char *ip); + +/* FDB. */ +struct fdb *fdb_add(struct hmap *map, struct fdb_data fdb_data); + +void fdb_remove(struct hmap *map, struct fdb *fdb); + +bool fdb_data_from_sbrec(struct fdb_data *data, const struct sbrec_fdb *fdb); + +struct fdb *fdb_find(const struct hmap *map, const struct fdb_data *fdb_data); + +bool sb_fdb_updated(const struct sbrec_fdb *fdb); + +void fdbs_clear(struct hmap *map); + +/* MAC binding stat processing. */ void -mac_cache_fdb_stats_process_flow_stats(struct ovs_list *stats_list, - struct ofputil_flow_stats *ofp_stats); -void mac_cache_fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, - void *data); +mac_binding_stats_process_flow_stats(struct ovs_list *stats_list, + struct ofputil_flow_stats *ofp_stats); + +void mac_binding_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, + void *data); + +/* FDB stat processing. */ +void fdb_stats_process_flow_stats(struct ovs_list *stats_list, + struct ofputil_flow_stats *ofp_stats); + +void fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, + void *data); void mac_cache_stats_destroy(struct ovs_list *stats_list); +/* Packet buffering. */ +struct bp_packet_data * +bp_packet_data_create(const struct ofputil_packet_in *pin, + const struct ofpbuf *continuation); + +void bp_packet_data_destroy(struct bp_packet_data *pd); + +struct buffered_packets * +buffered_packets_add(struct buffered_packets_ctx *ctx, + struct mac_binding_data mb_data); + +void buffered_packets_packet_data_enqueue(struct buffered_packets *bp, + struct bp_packet_data *pd); + +void buffered_packets_ctx_run(struct buffered_packets_ctx *ctx, + const struct hmap *recent_mbs, + struct ovsdb_idl_index *sbrec_pb_by_key, + struct ovsdb_idl_index *sbrec_dp_by_key, + struct ovsdb_idl_index *sbrec_pb_by_name, + struct ovsdb_idl_index *sbrec_mb_by_lport_ip); + +void buffered_packets_ctx_init(struct buffered_packets_ctx *ctx); + +void buffered_packets_ctx_destroy(struct buffered_packets_ctx *ctx); + +bool buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx); + +bool buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx); + #endif /* controller/mac-cache.h */ diff --git a/controller/mac-learn.c b/controller/mac-learn.c deleted file mode 100644 index 0c3b60c23..000000000 --- a/controller/mac-learn.c +++ /dev/null @@ -1,482 +0,0 @@ -/* Copyright (c) 2020, 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 "mac-learn.h" - -/* OpenvSwitch lib includes. */ -#include "openvswitch/poll-loop.h" -#include "openvswitch/vlog.h" -#include "lib/packets.h" -#include "lib/smap.h" -#include "lib/timeval.h" -#include "lport.h" -#include "ovn-sb-idl.h" - -VLOG_DEFINE_THIS_MODULE(mac_learn); - -#define MAX_FDB_ENTRIES 1000 -#define MAX_BUFFERED_PACKETS 1000 -#define BUFFER_QUEUE_DEPTH 4 -#define BUFFERED_PACKETS_TIMEOUT_MS 10000 -#define BUFFERED_PACKETS_LOOKUP_MS 100 - -static size_t keys_ip_hash(uint32_t dp_key, uint32_t port_key, - struct in6_addr *ip); -static struct mac_binding *mac_binding_find(const struct mac_bindings_map - *mac_bindings, uint32_t dp_key, - uint32_t port_key, - struct in6_addr *ip, size_t hash); -static size_t fdb_entry_hash(uint32_t dp_key, struct eth_addr *); - -static struct fdb_entry *fdb_entry_find(struct hmap *fdbs, uint32_t dp_key, - struct eth_addr *mac, size_t hash); -static struct buffered_packets * -buffered_packets_find(struct buffered_packets_ctx *ctx, uint64_t dp_key, - uint64_t port_key, struct in6_addr *ip, uint32_t hash); -static void ovn_buffered_packets_remove(struct buffered_packets_ctx *ctx, - struct buffered_packets *bp); -static void -buffered_packets_db_lookup(struct buffered_packets *bp, - struct ds *ip, struct eth_addr *mac, - struct ovsdb_idl_index *sbrec_pb_by_key, - struct ovsdb_idl_index *sbrec_dp_by_key, - struct ovsdb_idl_index *sbrec_pb_by_name, - struct ovsdb_idl_index *sbrec_mb_by_lport_ip); - -/* mac_binding functions. */ -void -ovn_mac_bindings_map_init(struct mac_bindings_map *mac_bindings, - size_t max_size) -{ - mac_bindings->max_size = max_size; - hmap_init(&mac_bindings->map); -} - -void -ovn_mac_bindings_map_destroy(struct mac_bindings_map *mac_bindings) -{ - struct mac_binding *mb; - - HMAP_FOR_EACH_POP (mb, hmap_node, &mac_bindings->map) { - free(mb); - } - hmap_destroy(&mac_bindings->map); -} - -struct mac_binding * -ovn_mac_binding_add(struct mac_bindings_map *mac_bindings, uint32_t dp_key, - uint32_t port_key, struct in6_addr *ip, - struct eth_addr mac, uint32_t timeout_ms) -{ - uint32_t hash = keys_ip_hash(dp_key, port_key, ip); - - struct mac_binding *mb = - mac_binding_find(mac_bindings, dp_key, port_key, ip, hash); - size_t max_size = mac_bindings->max_size; - if (!mb) { - if (max_size && hmap_count(&mac_bindings->map) >= max_size) { - return NULL; - } - mb = xmalloc(sizeof *mb); - mb->dp_key = dp_key; - mb->port_key = port_key; - mb->ip = *ip; - mb->timeout_at_ms = time_msec() + timeout_ms; - hmap_insert(&mac_bindings->map, &mb->hmap_node, hash); - } - mb->mac = mac; - - return mb; -} - -/* This is called from ovn-controller main context */ -void -ovn_mac_bindings_map_wait(struct mac_bindings_map *mac_bindings) -{ - if (hmap_is_empty(&mac_bindings->map)) { - return; - } - - struct mac_binding *mb; - - HMAP_FOR_EACH (mb, hmap_node, &mac_bindings->map) { - poll_timer_wait_until(mb->timeout_at_ms); - } -} - -void -ovn_mac_binding_remove(struct mac_binding *mb, - struct mac_bindings_map *mac_bindings) -{ - hmap_remove(&mac_bindings->map, &mb->hmap_node); - free(mb); -} - -bool -ovn_mac_binding_timed_out(const struct mac_binding *mb, long long now) -{ - return now >= mb->timeout_at_ms; -} - -const struct sbrec_mac_binding * -ovn_mac_binding_lookup(struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, - const char *logical_port, const char *ip) -{ - struct sbrec_mac_binding *mb = - sbrec_mac_binding_index_init_row(sbrec_mac_binding_by_lport_ip); - sbrec_mac_binding_index_set_logical_port(mb, logical_port); - sbrec_mac_binding_index_set_ip(mb, ip); - - const struct sbrec_mac_binding *retval = - sbrec_mac_binding_index_find(sbrec_mac_binding_by_lport_ip, mb); - - sbrec_mac_binding_index_destroy_row(mb); - - return retval; -} - -/* fdb functions. */ -void -ovn_fdb_init(struct hmap *fdbs) -{ - hmap_init(fdbs); -} - -void -ovn_fdbs_flush(struct hmap *fdbs) -{ - struct fdb_entry *fdb_e; - HMAP_FOR_EACH_POP (fdb_e, hmap_node, fdbs) { - free(fdb_e); - } -} - -void -ovn_fdbs_destroy(struct hmap *fdbs) -{ - ovn_fdbs_flush(fdbs); - hmap_destroy(fdbs); -} - -struct fdb_entry * -ovn_fdb_add(struct hmap *fdbs, uint32_t dp_key, struct eth_addr mac, - uint32_t port_key) -{ - uint32_t hash = fdb_entry_hash(dp_key, &mac); - - struct fdb_entry *fdb_e = - fdb_entry_find(fdbs, dp_key, &mac, hash); - if (!fdb_e) { - if (hmap_count(fdbs) >= MAX_FDB_ENTRIES) { - return NULL; - } - - fdb_e = xzalloc(sizeof *fdb_e); - fdb_e->dp_key = dp_key; - fdb_e->mac = mac; - hmap_insert(fdbs, &fdb_e->hmap_node, hash); - } - fdb_e->port_key = port_key; - - return fdb_e; - -} - -/* packet buffering functions */ - -struct packet_data * -ovn_packet_data_create(const struct ofputil_packet_in *pin, - const struct ofpbuf *continuation) -{ - struct packet_data *pd = xmalloc(sizeof *pd); - - pd->pin = (struct ofputil_packet_in) { - .packet = xmemdup(pin->packet, pin->packet_len), - .packet_len = pin->packet_len, - .flow_metadata = pin->flow_metadata, - .reason = pin->reason, - .table_id = pin->table_id, - .cookie = pin->cookie, - /* Userdata are empty on purpose, - * it is not needed for the continuation. */ - .userdata = NULL, - .userdata_len = 0, - }; - pd->continuation = ofpbuf_clone(continuation); - - return pd; -} - - -void -ovn_packet_data_destroy(struct packet_data *pd) -{ - free(pd->pin.packet); - ofpbuf_delete(pd->continuation); - free(pd); -} - -struct buffered_packets * -ovn_buffered_packets_add(struct buffered_packets_ctx *ctx, uint64_t dp_key, - uint64_t port_key, struct in6_addr ip) -{ - struct buffered_packets *bp; - - uint32_t hash = keys_ip_hash(dp_key, port_key, &ip); - - bp = buffered_packets_find(ctx, dp_key, port_key, &ip, hash); - if (!bp) { - if (hmap_count(&ctx->buffered_packets) >= MAX_BUFFERED_PACKETS) { - return NULL; - } - - bp = xmalloc(sizeof *bp); - hmap_insert(&ctx->buffered_packets, &bp->hmap_node, hash); - bp->ip = ip; - bp->dp_key = dp_key; - bp->port_key = port_key; - /* Schedule the freshly added buffered packet to do lookup - * immediately. */ - bp->lookup_at_ms = 0; - ovs_list_init(&bp->queue); - } - - bp->expire_at_ms = time_msec() + BUFFERED_PACKETS_TIMEOUT_MS; - - return bp; -} - -void -ovn_buffered_packets_packet_data_enqueue(struct buffered_packets *bp, - struct packet_data *pd) -{ - if (ovs_list_size(&bp->queue) == BUFFER_QUEUE_DEPTH) { - struct packet_data *p = CONTAINER_OF(ovs_list_pop_front(&bp->queue), - struct packet_data, node); - - ovn_packet_data_destroy(p); - } - ovs_list_push_back(&bp->queue, &pd->node); -} - -void -ovn_buffered_packets_ctx_run(struct buffered_packets_ctx *ctx, - const struct mac_bindings_map *recent_mbs, - struct ovsdb_idl_index *sbrec_pb_by_key, - struct ovsdb_idl_index *sbrec_dp_by_key, - struct ovsdb_idl_index *sbrec_pb_by_name, - struct ovsdb_idl_index *sbrec_mb_by_lport_ip) -{ - struct ds ip = DS_EMPTY_INITIALIZER; - long long now = time_msec(); - - struct buffered_packets *bp; - - HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) { - struct eth_addr mac = eth_addr_zero; - /* Remove expired buffered packets. */ - if (now > bp->expire_at_ms) { - ovn_buffered_packets_remove(ctx, bp); - continue; - } - - uint32_t hash = keys_ip_hash(bp->dp_key, bp->port_key, &bp->ip); - struct mac_binding *mb = mac_binding_find(recent_mbs, bp->dp_key, - bp->port_key, &bp->ip, hash); - - if (mb) { - mac = mb->mac; - } else if (now >= bp->lookup_at_ms) { - /* Check if we can do a full lookup. */ - buffered_packets_db_lookup(bp, &ip, &mac, sbrec_pb_by_key, - sbrec_dp_by_key, sbrec_pb_by_name, - sbrec_mb_by_lport_ip); - /* Schedule next lookup even if we found the MAC address, - * if the address was found this struct will be deleted anyway. */ - bp->lookup_at_ms = now + BUFFERED_PACKETS_LOOKUP_MS; - } - - if (eth_addr_is_zero(mac)) { - continue; - } - - struct packet_data *pd; - LIST_FOR_EACH_POP (pd, node, &bp->queue) { - struct dp_packet packet; - dp_packet_use_const(&packet, pd->pin.packet, pd->pin.packet_len); - - struct eth_header *eth = dp_packet_data(&packet); - eth->eth_dst = mac; - - ovs_list_push_back(&ctx->ready_packets_data, &pd->node); - } - - ovn_buffered_packets_remove(ctx, bp); - } - - ds_destroy(&ip); -} - -bool -ovn_buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx) -{ - return !ovs_list_is_empty(&ctx->ready_packets_data); -} - -bool -ovn_buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx) -{ - return !hmap_is_empty(&ctx->buffered_packets); -} - -void -ovn_buffered_packets_ctx_init(struct buffered_packets_ctx *ctx) -{ - hmap_init(&ctx->buffered_packets); - ovs_list_init(&ctx->ready_packets_data); -} - -void -ovn_buffered_packets_ctx_destroy(struct buffered_packets_ctx *ctx) -{ - struct packet_data *pd; - LIST_FOR_EACH_POP (pd, node, &ctx->ready_packets_data) { - ovn_packet_data_destroy(pd); - } - - struct buffered_packets *bp; - HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) { - ovn_buffered_packets_remove(ctx, bp); - } - hmap_destroy(&ctx->buffered_packets); -} - -/* mac_binding related static functions. */ -static size_t -keys_ip_hash(uint32_t dp_key, uint32_t port_key, struct in6_addr *ip) -{ - return hash_bytes(ip, sizeof *ip, hash_2words(dp_key, port_key)); -} - -static struct mac_binding * -mac_binding_find(const struct mac_bindings_map *mac_bindings, - uint32_t dp_key, uint32_t port_key, struct in6_addr *ip, - size_t hash) -{ - struct mac_binding *mb; - - HMAP_FOR_EACH_WITH_HASH (mb, hmap_node, hash, &mac_bindings->map) { - if (mb->dp_key == dp_key && mb->port_key == port_key && - IN6_ARE_ADDR_EQUAL(&mb->ip, ip)) { - return mb; - } - } - - return NULL; -} - -/* fdb related static functions. */ - -static size_t -fdb_entry_hash(uint32_t dp_key, struct eth_addr *mac) -{ - uint64_t mac64 = eth_addr_to_uint64(*mac); - return hash_2words(dp_key, hash_uint64(mac64)); -} - -static struct fdb_entry * -fdb_entry_find(struct hmap *fdbs, uint32_t dp_key, - struct eth_addr *mac, size_t hash) -{ - struct fdb_entry *fdb_e; - HMAP_FOR_EACH_WITH_HASH (fdb_e, hmap_node, hash, fdbs) { - if (fdb_e->dp_key == dp_key && eth_addr_equals(fdb_e->mac, *mac)) { - return fdb_e; - } - } - - return NULL; -} - -/* packet buffering static functions. */ -static struct buffered_packets * -buffered_packets_find(struct buffered_packets_ctx *ctx, uint64_t dp_key, - uint64_t port_key, struct in6_addr *ip, uint32_t hash) -{ - struct buffered_packets *mb; - - HMAP_FOR_EACH_WITH_HASH (mb, hmap_node, hash, &ctx->buffered_packets) { - if (mb->dp_key == dp_key && mb->port_key == port_key && - IN6_ARE_ADDR_EQUAL(&mb->ip, ip)) { - return mb; - } - } - - return NULL; -} - -static void -ovn_buffered_packets_remove(struct buffered_packets_ctx *ctx, - struct buffered_packets *bp) -{ - struct packet_data *pd; - - LIST_FOR_EACH_POP (pd, node, &bp->queue) { - ovn_packet_data_destroy(pd); - } - - hmap_remove(&ctx->buffered_packets, &bp->hmap_node); - free(bp); -} - -static void -buffered_packets_db_lookup(struct buffered_packets *bp, struct ds *ip, - struct eth_addr *mac, - struct ovsdb_idl_index *sbrec_pb_by_key, - struct ovsdb_idl_index *sbrec_dp_by_key, - struct ovsdb_idl_index *sbrec_pb_by_name, - struct ovsdb_idl_index *sbrec_mb_by_lport_ip) -{ - const struct sbrec_port_binding *pb = lport_lookup_by_key(sbrec_dp_by_key, - sbrec_pb_by_key, - bp->dp_key, - bp->port_key); - if (!pb) { - return; - } - - if (!strcmp(pb->type, "chassisredirect")) { - const char *dgp_name = - smap_get_def(&pb->options, "distributed-port", ""); - pb = lport_lookup_by_name(sbrec_pb_by_name, dgp_name); - if (!pb) { - return; - } - } - - ipv6_format_mapped(&bp->ip, ip); - const struct sbrec_mac_binding *smb = - ovn_mac_binding_lookup(sbrec_mb_by_lport_ip, pb->logical_port, - ds_cstr_ro(ip)); - ds_clear(ip); - - if (!smb) { - return; - } - - eth_addr_from_string(smb->mac, mac); -} diff --git a/controller/mac-learn.h b/controller/mac-learn.h deleted file mode 100644 index 20a015e1a..000000000 --- a/controller/mac-learn.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2020 Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OVN_MAC_LEARN_H -#define OVN_MAC_LEARN_H 1 - -#include -#include - -#include "dp-packet.h" -#include "openvswitch/hmap.h" -#include "openvswitch/list.h" -#include "openvswitch/ofpbuf.h" -#include "openvswitch/ofp-packet.h" - -struct ovsdb_idl_index; - -struct mac_binding { - struct hmap_node hmap_node; /* In a hmap. */ - - /* Key. */ - uint32_t dp_key; - uint32_t port_key; /* Port from where this mac_binding is learnt. */ - struct in6_addr ip; - - /* Value. */ - struct eth_addr mac; - - /* Absolute time (in ms) when a user specific timeout expires for - * this entry. */ - long long timeout_at_ms; -}; - -struct mac_bindings_map { - struct hmap map; - /* Maximum capacity of the associated map. "0" means unlimited. */ - size_t max_size; -}; - -void ovn_mac_bindings_map_init(struct mac_bindings_map *mac_bindings, - size_t max_size); -void ovn_mac_bindings_map_destroy(struct mac_bindings_map *mac_bindings); -void ovn_mac_bindings_map_wait(struct mac_bindings_map *mac_bindings); -void ovn_mac_binding_remove(struct mac_binding *mb, - struct mac_bindings_map *mac_bindings); -bool ovn_mac_binding_timed_out(const struct mac_binding *mb, - long long now); - -struct mac_binding *ovn_mac_binding_add(struct mac_bindings_map *mac_bindings, - uint32_t dp_key, uint32_t port_key, - struct in6_addr *ip, - struct eth_addr mac, - uint32_t timeout_ms); -const struct sbrec_mac_binding * -ovn_mac_binding_lookup(struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, - const char *logical_port, const char *ip); - - -struct fdb_entry { - struct hmap_node hmap_node; /* In a hmap. */ - - /* Key. */ - uint32_t dp_key; - struct eth_addr mac; - - /* value. */ - uint32_t port_key; -}; - -void ovn_fdb_init(struct hmap *fdbs); -void ovn_fdbs_flush(struct hmap *fdbs); -void ovn_fdbs_destroy(struct hmap *fdbs); - -struct fdb_entry *ovn_fdb_add(struct hmap *fdbs, - uint32_t dp_key, struct eth_addr mac, - uint32_t port_key); - - -struct packet_data { - struct ovs_list node; - - struct ofpbuf *continuation; - struct ofputil_packet_in pin; -}; - -struct buffered_packets { - struct hmap_node hmap_node; - - struct in6_addr ip; - uint64_t dp_key; - uint64_t port_key; - - /* Queue of packet_data associated with this struct. */ - struct ovs_list queue; - - /* Timestamp in ms when the buffered packet should expire. */ - long long int expire_at_ms; - - /* Timestamp in ms when the buffered packet should do full SB lookup.*/ - long long int lookup_at_ms; -}; - -struct buffered_packets_ctx { - /* Map of all buffered packets waiting for the MAC address. */ - struct hmap buffered_packets; - /* List of packet data that are ready to be sent. */ - struct ovs_list ready_packets_data; -}; - -struct packet_data * -ovn_packet_data_create(const struct ofputil_packet_in *pin, - const struct ofpbuf *continuation); -void ovn_packet_data_destroy(struct packet_data *pd); -struct buffered_packets * -ovn_buffered_packets_add(struct buffered_packets_ctx *ctx, uint64_t dp_key, - uint64_t port_key, struct in6_addr ip); -void ovn_buffered_packets_packet_data_enqueue(struct buffered_packets *bp, - struct packet_data *pd); -void -ovn_buffered_packets_ctx_run(struct buffered_packets_ctx *ctx, - const struct mac_bindings_map *recent_mbs, - struct ovsdb_idl_index *sbrec_pb_by_key, - struct ovsdb_idl_index *sbrec_dp_by_key, - struct ovsdb_idl_index *sbrec_pb_by_name, - struct ovsdb_idl_index *sbrec_mb_by_lport_ip); -void ovn_buffered_packets_ctx_init(struct buffered_packets_ctx *ctx); -void ovn_buffered_packets_ctx_destroy(struct buffered_packets_ctx *ctx); -bool -ovn_buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx); -bool ovn_buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx); - -#endif /* OVN_MAC_LEARN_H */ diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index cde45e35e..cd50db823 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -3275,6 +3275,70 @@ en_lb_data_cleanup(void *data) uuidset_destroy(&lb_data->new); } +static void +mac_binding_add_sb(struct mac_cache_data *data, + const struct sbrec_mac_binding *smb, + struct ovsdb_idl_index *sbrec_pb_by_name) +{ + struct mac_binding_data mb_data; + if (!mac_binding_data_from_sbrec(&mb_data, smb, sbrec_pb_by_name)) { + return; + } + + struct mac_binding *mb = mac_binding_add(&data->mac_bindings, mb_data, 0); + + mb->sbrec_mb = smb; +} + +static void +mac_binding_remove_sb(struct mac_cache_data *data, + const struct sbrec_mac_binding *smb, + struct ovsdb_idl_index *sbrec_pb_by_name) +{ + struct mac_binding_data mb_data; + if (!mac_binding_data_from_sbrec(&mb_data, smb, sbrec_pb_by_name)) { + return; + } + + struct mac_binding *mb = mac_binding_find(&data->mac_bindings, &mb_data); + if (!mb) { + return; + } + + mac_binding_remove(&data->mac_bindings, mb); +} + +static void +fdb_add_sb(struct mac_cache_data *data, const struct sbrec_fdb *sfdb, + struct uuid dp_uuid) +{ + struct fdb_data fdb_data; + if (!fdb_data_from_sbrec(&fdb_data, sfdb)) { + return; + } + + struct fdb *fdb = fdb_add(&data->fdbs, fdb_data); + + fdb->sbrec_fdb = sfdb; + fdb->dp_uuid = dp_uuid; +} + +static void +fdb_remove_sb(struct mac_cache_data *data, const struct sbrec_fdb *sfdb) +{ + struct fdb_data fdb_data; + if (!fdb_data_from_sbrec(&fdb_data, sfdb)) { + return; + } + + struct fdb *fdb = fdb_find(&data->fdbs, &fdb_data); + if (!fdb) { + return; + } + + fdb_remove(&data->fdbs, fdb); +} + static void mac_cache_mb_handle_for_datapath(struct mac_cache_data *data, const struct sbrec_datapath_binding *dp, @@ -3291,9 +3355,9 @@ mac_cache_mb_handle_for_datapath(struct mac_cache_data *data, const struct sbrec_mac_binding *mb; SBREC_MAC_BINDING_FOR_EACH_EQUAL (mb, mb_index_row, sbrec_mb_by_dp) { if (has_threshold) { - mac_cache_mac_binding_add(data, mb, sbrec_pb_by_name); + mac_binding_add_sb(data, mb, sbrec_pb_by_name); } else { - mac_cache_mac_binding_remove(data, mb, sbrec_pb_by_name); + mac_binding_remove_sb(data, mb, sbrec_pb_by_name); } } @@ -3314,9 +3378,9 @@ mac_cache_fdb_handle_for_datapath(struct mac_cache_data *data, const struct sbrec_fdb *fdb; SBREC_FDB_FOR_EACH_EQUAL (fdb, fdb_index_row, sbrec_fdb_by_dp_key) { if (has_threshold) { - mac_cache_fdb_add(data, fdb, dp->header_.uuid); + fdb_add_sb(data, fdb, dp->header_.uuid); } else { - mac_cache_fdb_remove(data, fdb); + fdb_remove_sb(data, fdb); } } @@ -3354,8 +3418,8 @@ en_mac_cache_run(struct engine_node *node, void *data) "name"); mac_cache_thresholds_clear(cache_data); - mac_cache_mac_bindings_clear(cache_data); - mac_cache_fdbs_clear(cache_data); + mac_bindings_clear(&cache_data->mac_bindings); + fdbs_clear(&cache_data->fdbs); const struct sbrec_mac_binding *sbrec_mb; SBREC_MAC_BINDING_TABLE_FOR_EACH (sbrec_mb, mb_table) { @@ -3366,7 +3430,8 @@ en_mac_cache_run(struct engine_node *node, void *data) if (mac_cache_threshold_add(cache_data, sbrec_mb->datapath, MAC_CACHE_MAC_BINDING)) { - mac_cache_mac_binding_add(cache_data, sbrec_mb, sbrec_pb_by_name); + mac_binding_add_sb(cache_data, sbrec_mb, + sbrec_pb_by_name); } } @@ -3381,8 +3446,8 @@ en_mac_cache_run(struct engine_node *node, void *data) if (mac_cache_threshold_add(cache_data, local_dp->datapath, MAC_CACHE_FDB)) { - mac_cache_fdb_add(cache_data, sbrec_fdb, - local_dp->datapath->header_.uuid); + fdb_add_sb(cache_data, sbrec_fdb, + local_dp->datapath->header_.uuid); } } @@ -3406,13 +3471,13 @@ mac_cache_sb_mac_binding_handler(struct engine_node *node, void *data) const struct sbrec_mac_binding *sbrec_mb; SBREC_MAC_BINDING_TABLE_FOR_EACH_TRACKED (sbrec_mb, mb_table) { - if (!mac_cache_sb_mac_binding_updated(sbrec_mb)) { + if (!sb_mac_binding_updated(sbrec_mb)) { continue; } if (!sbrec_mac_binding_is_new(sbrec_mb)) { - mac_cache_mac_binding_remove(cache_data, sbrec_mb, - sbrec_pb_by_name); + mac_binding_remove_sb(cache_data, sbrec_mb, + sbrec_pb_by_name); } if (sbrec_mac_binding_is_deleted(sbrec_mb) || @@ -3423,7 +3488,8 @@ mac_cache_sb_mac_binding_handler(struct engine_node *node, void *data) if (mac_cache_threshold_add(cache_data, sbrec_mb->datapath, MAC_CACHE_MAC_BINDING)) { - mac_cache_mac_binding_add(cache_data, sbrec_mb, sbrec_pb_by_name); + mac_binding_add_sb(cache_data, sbrec_mb, + sbrec_pb_by_name); } } @@ -3448,12 +3514,12 @@ mac_cache_sb_fdb_handler(struct engine_node *node, void *data) struct local_datapath *local_dp; const struct sbrec_fdb *sbrec_fdb; SBREC_FDB_TABLE_FOR_EACH_TRACKED (sbrec_fdb, fdb_table) { - if (!mac_cache_sb_fdb_updated(sbrec_fdb)) { + if (!sb_fdb_updated(sbrec_fdb)) { continue; } if (!sbrec_fdb_is_new(sbrec_fdb)) { - mac_cache_fdb_remove(cache_data, sbrec_fdb); + fdb_remove_sb(cache_data, sbrec_fdb); } local_dp = get_local_datapath(&rt_data->local_datapaths, @@ -3464,8 +3530,8 @@ mac_cache_sb_fdb_handler(struct engine_node *node, void *data) if (mac_cache_threshold_add(cache_data, local_dp->datapath, MAC_CACHE_FDB)) { - mac_cache_fdb_add(cache_data, sbrec_fdb, - local_dp->datapath->header_.uuid); + fdb_add_sb(cache_data, sbrec_fdb, + local_dp->datapath->header_.uuid); } } @@ -3582,9 +3648,9 @@ en_mac_cache_cleanup(void *data) for (size_t i = 0; i < MAC_CACHE_MAX; i++) { hmap_destroy(&cache_data->thresholds[i]); } - mac_cache_mac_bindings_clear(cache_data); + mac_bindings_clear(&cache_data->mac_bindings); hmap_destroy(&cache_data->mac_bindings); - mac_cache_fdbs_clear(cache_data); + fdbs_clear(&cache_data->fdbs); hmap_destroy(&cache_data->fdbs); } diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 0ee6d8fa8..6a2c3dc68 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -27,7 +27,7 @@ #include "ha-chassis.h" #include "local_data.h" #include "lport.h" -#include "mac-learn.h" +#include "mac-cache.h" #include "nx-match.h" #include "ofctrl.h" #include "latch.h" @@ -382,7 +382,7 @@ static void run_put_fdb(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, struct ovsdb_idl_index *sbrec_port_binding_by_key, struct ovsdb_idl_index *sbrec_datapath_binding_by_key, - const struct fdb_entry *fdb_e) + const struct fdb *fdb) OVS_REQUIRES(pinctrl_mutex); static void run_put_fdbs(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_port_binding_by_key, @@ -1523,13 +1523,13 @@ static struct buffered_packets_ctx buffered_packets_ctx; static void init_buffered_packets_ctx(void) { - ovn_buffered_packets_ctx_init(&buffered_packets_ctx); + buffered_packets_ctx_init(&buffered_packets_ctx); } static void destroy_buffered_packets_ctx(void) { - ovn_buffered_packets_ctx_destroy(&buffered_packets_ctx); + buffered_packets_ctx_destroy(&buffered_packets_ctx); } /* Called with in the pinctrl_handler thread context. */ @@ -1539,27 +1539,29 @@ pinctrl_handle_buffered_packets(const struct ofputil_packet_in *pin, bool is_arp) OVS_REQUIRES(pinctrl_mutex) { - struct in6_addr ip; const struct match *md = &pin->flow_metadata; - uint64_t dp_key = ntohll(md->flow.metadata); - uint64_t oport_key = md->flow.regs[MFF_LOG_OUTPORT - MFF_REG0]; + struct mac_binding_data mb_data = (struct mac_binding_data) { + .dp_key = ntohll(md->flow.metadata), + .port_key = md->flow.regs[MFF_LOG_OUTPORT - MFF_REG0], + .mac = eth_addr_zero, + }; if (is_arp) { - ip = in6_addr_mapped_ipv4(htonl(md->flow.regs[0])); + mb_data.ip = in6_addr_mapped_ipv4(htonl(md->flow.regs[0])); } else { ovs_be128 ip6 = hton128(flow_get_xxreg(&md->flow, 0)); - memcpy(&ip, &ip6, sizeof ip); + memcpy(&mb_data.ip, &ip6, sizeof mb_data.ip); } - struct buffered_packets *bp = - ovn_buffered_packets_add(&buffered_packets_ctx, dp_key, oport_key, ip); + struct buffered_packets *bp = buffered_packets_add(&buffered_packets_ctx, + mb_data); if (!bp) { COVERAGE_INC(pinctrl_drop_buffered_packets_map); return; } - struct packet_data *pd = ovn_packet_data_create(pin, continuation); - ovn_buffered_packets_packet_data_enqueue(bp, pd); + struct bp_packet_data *pd = bp_packet_data_create(pin, continuation); + buffered_packets_packet_data_enqueue(bp, pd); /* There is a chance that the MAC binding was already created. */ notify_pinctrl_main(); @@ -4772,18 +4774,18 @@ pinctrl_destroy(void) #define MAX_MAC_BINDINGS 1000 /* Contains "struct mac_binding"s. */ -static struct mac_bindings_map put_mac_bindings; +static struct hmap put_mac_bindings; static void init_put_mac_bindings(void) { - ovn_mac_bindings_map_init(&put_mac_bindings, MAX_MAC_BINDINGS); + hmap_init(&put_mac_bindings); } static void destroy_put_mac_bindings(void) { - ovn_mac_bindings_map_destroy(&put_mac_bindings); + hmap_destroy(&put_mac_bindings); } /* Called with in the pinctrl_handler thread context. */ @@ -4793,15 +4795,22 @@ pinctrl_handle_put_mac_binding(const struct flow *md, bool is_arp) OVS_REQUIRES(pinctrl_mutex) { - uint32_t dp_key = ntohll(md->metadata); - uint32_t port_key = md->regs[MFF_LOG_INPORT - MFF_REG0]; - struct in6_addr ip_key; + if (hmap_count(&put_mac_bindings) >= MAX_MAC_BINDINGS) { + COVERAGE_INC(pinctrl_drop_put_mac_binding); + return; + } + + struct mac_binding_data mb_data = (struct mac_binding_data) { + .dp_key = ntohll(md->metadata), + .port_key = md->regs[MFF_LOG_INPORT - MFF_REG0], + .mac = headers->dl_src, + }; if (is_arp) { - ip_key = in6_addr_mapped_ipv4(htonl(md->regs[0])); + mb_data.ip = in6_addr_mapped_ipv4(htonl(md->regs[0])); } else { ovs_be128 ip6 = hton128(flow_get_xxreg(md, 0)); - memcpy(&ip_key, &ip6, sizeof ip_key); + memcpy(&mb_data.ip, &ip6, sizeof mb_data.ip); } /* If the ARP reply was unicast we should not delay it, @@ -4809,13 +4818,8 @@ pinctrl_handle_put_mac_binding(const struct flow *md, uint32_t delay = eth_addr_is_multicast(headers->dl_dst) ? random_range(MAX_MAC_BINDING_DELAY_MSEC) + 1 : 0; - struct mac_binding *mb = ovn_mac_binding_add(&put_mac_bindings, dp_key, - port_key, &ip_key, - headers->dl_src, delay); - if (!mb) { - COVERAGE_INC(pinctrl_drop_put_mac_binding); - return; - } + long long timestamp = time_msec() + delay; + mac_binding_add(&put_mac_bindings, mb_data, timestamp); /* We can send the buffered packet once the main ovn-controller * thread calls pinctrl_run() and it writes the mac_bindings stored @@ -4831,11 +4835,11 @@ send_mac_binding_buffered_pkts(struct rconn *swconn) enum ofp_version version = rconn_get_version(swconn); enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); - struct packet_data *pd; + struct bp_packet_data *pd; LIST_FOR_EACH_POP (pd, node, &buffered_packets_ctx.ready_packets_data) { queue_msg(swconn, ofputil_encode_resume(&pd->pin, pd->continuation, proto)); - ovn_packet_data_destroy(pd); + bp_packet_data_destroy(pd); } ovs_list_init(&buffered_packets_ctx.ready_packets_data); @@ -4856,7 +4860,7 @@ mac_binding_add_to_sb(struct ovsdb_idl_txn *ovnsb_idl_txn, snprintf(mac_string, sizeof mac_string, ETH_ADDR_FMT, ETH_ADDR_ARGS(ea)); const struct sbrec_mac_binding *b = - ovn_mac_binding_lookup(sbrec_mac_binding_by_lport_ip, + mac_binding_lookup(sbrec_mac_binding_by_lport_ip, logical_port, ip); if (!b) { if (update_only) { @@ -4930,24 +4934,24 @@ run_put_mac_binding(struct ovsdb_idl_txn *ovnsb_idl_txn, /* Convert logical datapath and logical port key into lport. */ const struct sbrec_port_binding *pb = lport_lookup_by_key( sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, - mb->dp_key, mb->port_key); + mb->data.dp_key, mb->data.port_key); if (!pb) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_WARN_RL(&rl, "unknown logical port with datapath %"PRIu32" " - "and port %"PRIu32, mb->dp_key, mb->port_key); + "and port %"PRIu32, mb->data.dp_key, mb->data.port_key); return; } /* Convert ethernet argument to string form for database. */ char mac_string[ETH_ADDR_STRLEN + 1]; snprintf(mac_string, sizeof mac_string, - ETH_ADDR_FMT, ETH_ADDR_ARGS(mb->mac)); + ETH_ADDR_FMT, ETH_ADDR_ARGS(mb->data.mac)); struct ds ip_s = DS_EMPTY_INITIALIZER; - ipv6_format_mapped(&mb->ip, &ip_s); + ipv6_format_mapped(&mb->data.ip, &ip_s); mac_binding_add_to_sb(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - pb->logical_port, pb->datapath, mb->mac, + pb->logical_port, pb->datapath, mb->data.mac, ds_cstr(&ip_s), false); ds_destroy(&ip_s); } @@ -4968,13 +4972,13 @@ run_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, long long now = time_msec(); struct mac_binding *mb; - HMAP_FOR_EACH_SAFE (mb, hmap_node, &put_mac_bindings.map) { - if (ovn_mac_binding_timed_out(mb, now)) { + HMAP_FOR_EACH_SAFE (mb, hmap_node, &put_mac_bindings) { + if (now >= mb->timestamp) { run_put_mac_binding(ovnsb_idl_txn, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, sbrec_mac_binding_by_lport_ip, mb); - ovn_mac_binding_remove(mb, &put_mac_bindings); + mac_binding_remove(&put_mac_bindings, mb); } } } @@ -4987,33 +4991,24 @@ run_buffered_binding(const struct sbrec_mac_binding_table *mac_binding_table, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip) OVS_REQUIRES(pinctrl_mutex) { - if (!ovn_buffered_packets_ctx_has_packets(&buffered_packets_ctx)) { + if (!buffered_packets_ctx_has_packets(&buffered_packets_ctx)) { return; } - struct mac_bindings_map recent_mbs; - ovn_mac_bindings_map_init(&recent_mbs, 0); + struct hmap recent_mbs = HMAP_INITIALIZER(&recent_mbs); const struct sbrec_mac_binding *smb; SBREC_MAC_BINDING_TABLE_FOR_EACH_TRACKED (smb, mac_binding_table) { const struct sbrec_port_binding *pb = lport_lookup_by_name( sbrec_port_binding_by_name, smb->logical_port); - if (!pb || !pb->datapath) { - continue; - } - - struct in6_addr ip; - if (!ip46_parse(smb->ip, &ip)) { - continue; - } - struct eth_addr mac; - if (!eth_addr_from_string(smb->mac, &mac)) { + struct mac_binding_data mb_data; + if (!mac_binding_data_from_sbrec(&mb_data, smb, + sbrec_port_binding_by_name)) { continue; } - ovn_mac_binding_add(&recent_mbs, smb->datapath->tunnel_key, - pb->tunnel_key, &ip, mac, 0); + mac_binding_add(&recent_mbs, mb_data, 0); const char *redirect_port = smap_get(&pb->options, "chassis-redirect-port"); @@ -5029,19 +5024,20 @@ run_buffered_binding(const struct sbrec_mac_binding_table *mac_binding_table, /* Add the same entry also for chassisredirect port as the buffered * traffic might be buffered on the cr port. */ - ovn_mac_binding_add(&recent_mbs, smb->datapath->tunnel_key, - pb->tunnel_key, &ip, mac, 0); + mb_data.port_key = pb->tunnel_key; + mac_binding_add(&recent_mbs, mb_data, 0); } - ovn_buffered_packets_ctx_run(&buffered_packets_ctx, &recent_mbs, + buffered_packets_ctx_run(&buffered_packets_ctx, &recent_mbs, sbrec_port_binding_by_key, sbrec_datapath_binding_by_key, sbrec_port_binding_by_name, sbrec_mac_binding_by_lport_ip); - ovn_mac_bindings_map_destroy(&recent_mbs); + mac_bindings_clear(&recent_mbs); + hmap_destroy(&recent_mbs); - if (ovn_buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx)) { + if (buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx)) { notify_pinctrl_handler(); } } @@ -5050,8 +5046,13 @@ static void wait_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn) OVS_REQUIRES(pinctrl_mutex) { - if (ovnsb_idl_txn) { - ovn_mac_bindings_map_wait(&put_mac_bindings); + if (!ovnsb_idl_txn) { + return; + } + + struct mac_binding *mb; + HMAP_FOR_EACH (mb, hmap_node, &put_mac_bindings) { + poll_timer_wait_until(mb->timestamp); } } @@ -6692,7 +6693,7 @@ may_inject_pkts(void) !shash_is_empty(&send_garp_rarp_data) || ipv6_prefixd_should_inject() || !ovs_list_is_empty(&mcast_query_list) || - ovn_buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx) || + buffered_packets_ctx_is_ready_to_send(&buffered_packets_ctx) || bfd_monitor_should_inject()); } @@ -8903,6 +8904,8 @@ pinctrl_mg_split_buff_handler(struct rconn *swconn, struct dp_packet *pkt, ofpbuf_uninit(&ofpacts); } +#define MAX_FDB_ENTRIES 1000 + static struct hmap put_fdbs; /* MAC learning (fdb) related functions. Runs within the main @@ -8911,13 +8914,13 @@ static struct hmap put_fdbs; static void init_fdb_entries(void) { - ovn_fdb_init(&put_fdbs); + hmap_init(&put_fdbs); } static void destroy_fdb_entries(void) { - ovn_fdbs_destroy(&put_fdbs); + hmap_destroy(&put_fdbs); } static const struct sbrec_fdb * @@ -8941,21 +8944,21 @@ run_put_fdb(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_fdb_by_dp_key_mac, struct ovsdb_idl_index *sbrec_port_binding_by_key, struct ovsdb_idl_index *sbrec_datapath_binding_by_key, - const struct fdb_entry *fdb_e) + const struct fdb *fdb) { /* Convert ethernet argument to string form for database. */ char mac_string[ETH_ADDR_STRLEN + 1]; snprintf(mac_string, sizeof mac_string, - ETH_ADDR_FMT, ETH_ADDR_ARGS(fdb_e->mac)); + ETH_ADDR_FMT, ETH_ADDR_ARGS(fdb->data.mac)); /* Update or add an FDB entry. */ const struct sbrec_port_binding *sb_entry_pb = NULL; const struct sbrec_port_binding *new_entry_pb = NULL; const struct sbrec_fdb *sb_fdb = - fdb_lookup(sbrec_fdb_by_dp_key_mac, fdb_e->dp_key, mac_string); + fdb_lookup(sbrec_fdb_by_dp_key_mac, fdb->data.dp_key, mac_string); if (!sb_fdb) { sb_fdb = sbrec_fdb_insert(ovnsb_idl_txn); - sbrec_fdb_set_dp_key(sb_fdb, fdb_e->dp_key); + sbrec_fdb_set_dp_key(sb_fdb, fdb->data.dp_key); sbrec_fdb_set_mac(sb_fdb, mac_string); } else { /* check whether sb_fdb->port_key is vif or localnet type */ @@ -8964,12 +8967,12 @@ run_put_fdb(struct ovsdb_idl_txn *ovnsb_idl_txn, sb_fdb->dp_key, sb_fdb->port_key); new_entry_pb = lport_lookup_by_key( sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, - fdb_e->dp_key, fdb_e->port_key); + fdb->data.dp_key, fdb->data.port_key); } /* Do not have localnet overwrite a previous vif entry */ if (!sb_entry_pb || !new_entry_pb || strcmp(sb_entry_pb->type, "") || strcmp(new_entry_pb->type, "localnet")) { - sbrec_fdb_set_port_key(sb_fdb, fdb_e->port_key); + sbrec_fdb_set_port_key(sb_fdb, fdb->data.port_key); } /* For backward compatibility check if timestamp column is available @@ -8990,13 +8993,13 @@ run_put_fdbs(struct ovsdb_idl_txn *ovnsb_idl_txn, return; } - const struct fdb_entry *fdb_e; - HMAP_FOR_EACH (fdb_e, hmap_node, &put_fdbs) { + const struct fdb *fdb; + HMAP_FOR_EACH (fdb, hmap_node, &put_fdbs) { run_put_fdb(ovnsb_idl_txn, sbrec_fdb_by_dp_key_mac, sbrec_port_binding_by_key, - sbrec_datapath_binding_by_key, fdb_e); + sbrec_datapath_binding_by_key, fdb); } - ovn_fdbs_flush(&put_fdbs); + fdbs_clear(&put_fdbs); } @@ -9013,9 +9016,17 @@ static void pinctrl_handle_put_fdb(const struct flow *md, const struct flow *headers) OVS_REQUIRES(pinctrl_mutex) { - uint32_t dp_key = ntohll(md->metadata); - uint32_t port_key = md->regs[MFF_LOG_INPORT - MFF_REG0]; + if (hmap_count(&put_mac_bindings) >= MAX_FDB_ENTRIES) { + COVERAGE_INC(pinctrl_drop_put_mac_binding); + return; + } + + struct fdb_data fdb_data = (struct fdb_data) { + .dp_key = ntohll(md->metadata), + .port_key = md->regs[MFF_LOG_INPORT - MFF_REG0], + .mac = headers->dl_src, + }; - ovn_fdb_add(&put_fdbs, dp_key, headers->dl_src, port_key); + fdb_add(&put_fdbs, fdb_data); notify_pinctrl_main(); } diff --git a/controller/statctrl.c b/controller/statctrl.c index cce31cce6..ca514bbee 100644 --- a/controller/statctrl.c +++ b/controller/statctrl.c @@ -136,7 +136,7 @@ statctrl_init(void) .table_id = OFTABLE_MAC_CACHE_USE, }; STATS_NODE(MAC_BINDING, mac_binding_request, mac_cache_stats_destroy, - mac_cache_mb_stats_process_flow_stats, mac_cache_mb_stats_run); + mac_binding_stats_process_flow_stats, mac_binding_stats_run); struct ofputil_flow_stats_request fdb_request = { .cookie = htonll(0), @@ -146,8 +146,7 @@ statctrl_init(void) .table_id = OFTABLE_LOOKUP_FDB, }; STATS_NODE(FDB, fdb_request, mac_cache_stats_destroy, - mac_cache_fdb_stats_process_flow_stats, - mac_cache_fdb_stats_run); + fdb_stats_process_flow_stats, fdb_stats_run); statctrl_ctx.thread = ovs_thread_create("ovn_statctrl", statctrl_thread_handler, From patchwork Tue May 7 06:25:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Musil X-Patchwork-Id: 1932229 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=FtydoU21; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VYSvR5CzKz1xnS for ; Tue, 7 May 2024 16:25:39 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 5481A82ACA; Tue, 7 May 2024 06:25:37 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id FPW0zoZ9XpDy; Tue, 7 May 2024 06:25:31 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 27BD18272C 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=FtydoU21 Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 27BD18272C; Tue, 7 May 2024 06:25:31 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D1E61C0077; Tue, 7 May 2024 06:25:30 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 73982C0DD5 for ; Tue, 7 May 2024 06:25:29 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 58C9241555 for ; Tue, 7 May 2024 06:25:29 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 8kmY14F3lYA9 for ; Tue, 7 May 2024 06:25:27 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124; helo=us-smtp-delivery-124.mimecast.com; envelope-from=amusil@redhat.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org 82E6340156 Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=none dis=none) header.from=redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 82E6340156 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=FtydoU21 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp2.osuosl.org (Postfix) with ESMTPS id 82E6340156 for ; Tue, 7 May 2024 06:25:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1715063126; 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=2/WDYuzxR4td74DrQ+e3ROJowHF1sJG+gwO6YPtza0o=; b=FtydoU21ce185a4CDcuAnn7+nJvZqVVCg0EQqA2ZsG0R5La//Gz/yN4PJ+0zX9cGiAm2Dx 9y0itB7CeHn25zSvn1THDamnGX6yyqtNmIjyQ6drHF2wpJ4k+KJ7MkUn/pt9R74c4aFWfZ pH1tBFcOOPA0HUs2YXi+uX0+UAKvFqs= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-41-bR3A84BrNWycNtvrNkiGNg-1; Tue, 07 May 2024 02:25:22 -0400 X-MC-Unique: bR3A84BrNWycNtvrNkiGNg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 96F9A80B3DD; Tue, 7 May 2024 06:25:22 +0000 (UTC) Received: from amusil.brq.redhat.com (unknown [10.43.17.32]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1CE1C271B6; Tue, 7 May 2024 06:25:21 +0000 (UTC) From: Ales Musil To: dev@openvswitch.org Date: Tue, 7 May 2024 08:25:17 +0200 Message-ID: <20240507062517.387329-5-amusil@redhat.com> In-Reply-To: <20240507062517.387329-1-amusil@redhat.com> References: <20240507062517.387329-1-amusil@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn v2 4/4] controller: Use datapath key for the mac cache thresholds. 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" Use datapath tunnel key instead of UUID for the mac cache threshold handling. At the same time simplify the thresholds into single hmap. The tunnel key is unique so there shouldn't be any overlap. Having two thresholds per datapath is currently invalid configuration anyway. The switch to datapath's tunnel key requires somehow costly synchronization when the tunnel key changes. However, this is fine as the key shouldn't change very often in some cases it won't change at all. Also fix wrong check in the aging tests that would ignore failure. Acked-by: Mark Michelson Signed-off-by: Ales Musil --- v2: Rebase on top of main. --- controller/mac-cache.c | 132 ++++++++++++++++++------------------ controller/mac-cache.h | 29 ++++---- controller/ovn-controller.c | 105 +++++++++++++--------------- tests/ovn.at | 4 +- 4 files changed, 128 insertions(+), 142 deletions(-) diff --git a/controller/mac-cache.c b/controller/mac-cache.c index c52f913ce..d8c4e2aed 100644 --- a/controller/mac-cache.c +++ b/controller/mac-cache.c @@ -16,6 +16,7 @@ #include #include +#include "local_data.h" #include "lport.h" #include "mac-cache.h" #include "openvswitch/hmap.h" @@ -39,11 +40,8 @@ static uint32_t fdb_data_hash(const struct fdb_data *fdb_data); static inline bool fdb_data_equals(const struct fdb_data *a, const struct fdb_data *b); -static struct mac_cache_threshold * -mac_cache_threshold_find(struct hmap *thresholds, const struct uuid *uuid); static uint64_t -mac_cache_threshold_get_value_ms(const struct sbrec_datapath_binding *dp, - enum mac_cache_type type); +mac_cache_threshold_get_value_ms(const struct sbrec_datapath_binding *dp); static void mac_cache_threshold_remove(struct hmap *thresholds, struct mac_cache_threshold *threshold); @@ -67,60 +65,82 @@ buffered_packets_db_lookup(struct buffered_packets *bp, struct ovsdb_idl_index *sbrec_mb_by_lport_ip); /* Thresholds. */ -bool +void mac_cache_threshold_add(struct mac_cache_data *data, - const struct sbrec_datapath_binding *dp, - enum mac_cache_type type) + const struct sbrec_datapath_binding *dp) { - struct hmap *thresholds = &data->thresholds[type]; struct mac_cache_threshold *threshold = - mac_cache_threshold_find(thresholds, &dp->header_.uuid); + mac_cache_threshold_find(data, dp->tunnel_key); if (threshold) { - return true; + return; } - uint64_t value = mac_cache_threshold_get_value_ms(dp, type); + uint64_t value = mac_cache_threshold_get_value_ms(dp); if (!value) { - return false; + return; } threshold = xmalloc(sizeof *threshold); - threshold->uuid = dp->header_.uuid; + threshold->dp_key = dp->tunnel_key; threshold->value = value; threshold->dump_period = (3 * value) / 4; - hmap_insert(thresholds, &threshold->hmap_node, - uuid_hash(&dp->header_.uuid)); - - return true; + hmap_insert(&data->thresholds, &threshold->hmap_node, dp->tunnel_key); } -bool +void mac_cache_threshold_replace(struct mac_cache_data *data, const struct sbrec_datapath_binding *dp, - enum mac_cache_type type) + const struct hmap *local_datapaths) { - struct hmap *thresholds = &data->thresholds[type]; struct mac_cache_threshold *threshold = - mac_cache_threshold_find(thresholds, &dp->header_.uuid); + mac_cache_threshold_find(data, dp->tunnel_key); if (threshold) { - mac_cache_threshold_remove(thresholds, threshold); + mac_cache_threshold_remove(&data->thresholds, threshold); + } + + if (!get_local_datapath(local_datapaths, dp->tunnel_key)) { + return; } - return mac_cache_threshold_add(data, dp, type); + mac_cache_threshold_add(data, dp); +} + + +struct mac_cache_threshold * +mac_cache_threshold_find(struct mac_cache_data *data, uint32_t dp_key) +{ + struct mac_cache_threshold *threshold; + HMAP_FOR_EACH_WITH_HASH (threshold, hmap_node, dp_key, &data->thresholds) { + if (threshold->dp_key == dp_key) { + return threshold; + } + } + + return NULL; } void -mac_cache_thresholds_clear(struct mac_cache_data *data) +mac_cache_thresholds_sync(struct mac_cache_data *data, + const struct hmap *local_datapaths) { - for (size_t i = 0; i < MAC_CACHE_MAX; i++) { - struct mac_cache_threshold *threshold; - HMAP_FOR_EACH_POP (threshold, hmap_node, &data->thresholds[i]) { - free(threshold); + struct mac_cache_threshold *threshold; + HMAP_FOR_EACH_SAFE (threshold, hmap_node, &data->thresholds) { + if (!get_local_datapath(local_datapaths, threshold->dp_key)) { + mac_cache_threshold_remove(&data->thresholds, threshold); } } } +void +mac_cache_thresholds_clear(struct mac_cache_data *data) +{ + struct mac_cache_threshold *threshold; + HMAP_FOR_EACH_POP (threshold, hmap_node, &data->thresholds) { + free(threshold); + } +} + /* MAC binding. */ struct mac_binding * mac_binding_add(struct hmap *map, struct mac_binding_data mb_data, @@ -231,7 +251,6 @@ fdb_add(struct hmap *map, struct fdb_data fdb_data) { if (!fdb) { fdb = xmalloc(sizeof *fdb); fdb->sbrec_fdb = NULL; - fdb->dp_uuid = UUID_ZERO; hmap_insert(map, &fdb->hmap_node, fdb_data_hash(&fdb_data)); } @@ -343,7 +362,6 @@ mac_binding_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, void *data) { struct mac_cache_data *cache_data = data; - struct hmap *thresholds = &cache_data->thresholds[MAC_CACHE_MAC_BINDING]; long long timewall_now = time_wall_msec(); struct mac_cache_stats *stats; @@ -355,9 +373,8 @@ mac_binding_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, continue; } - struct uuid *dp_uuid = &mb->sbrec_mb->datapath->header_.uuid; struct mac_cache_threshold *threshold = - mac_cache_threshold_find(thresholds, dp_uuid); + mac_cache_threshold_find(cache_data, mb->data.dp_key); /* If "idle_age" is under threshold it means that the mac binding is * used on this chassis. Also make sure that we don't update the @@ -371,7 +388,7 @@ mac_binding_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, free(stats); } - mac_cache_update_req_delay(thresholds, req_delay); + mac_cache_update_req_delay(&cache_data->thresholds, req_delay); } /* FDB stat processing. */ @@ -396,7 +413,6 @@ fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, void *data) { struct mac_cache_data *cache_data = data; - struct hmap *thresholds = &cache_data->thresholds[MAC_CACHE_FDB]; long long timewall_now = time_wall_msec(); struct mac_cache_stats *stats; @@ -409,7 +425,8 @@ fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, } struct mac_cache_threshold *threshold = - mac_cache_threshold_find(thresholds, &fdb->dp_uuid); + mac_cache_threshold_find(cache_data, fdb->data.dp_key); + /* If "idle_age" is under threshold it means that the mac binding is * used on this chassis. Also make sure that we don't update the * timestamp more than once during the dump period. */ @@ -422,7 +439,7 @@ fdb_stats_run(struct ovs_list *stats_list, uint64_t *req_delay, free(stats); } - mac_cache_update_req_delay(thresholds, req_delay); + mac_cache_update_req_delay(&cache_data->thresholds, req_delay); } /* Packet buffering. */ @@ -625,41 +642,22 @@ fdb_data_equals(const struct fdb_data *a, const struct fdb_data *b) eth_addr_equals(a->mac, b->mac); } - -static struct mac_cache_threshold * -mac_cache_threshold_find(struct hmap *thresholds, const struct uuid *uuid) +static uint64_t +mac_cache_threshold_get_value_ms(const struct sbrec_datapath_binding *dp) { - uint32_t hash = uuid_hash(uuid); + uint64_t mb_value = + smap_get_uint(&dp->external_ids, "mac_binding_age_threshold", 0); + uint64_t fdb_value = + smap_get_uint(&dp->external_ids, "fdb_age_threshold", 0); - struct mac_cache_threshold *threshold; - HMAP_FOR_EACH_WITH_HASH (threshold, hmap_node, hash, thresholds) { - if (uuid_equals(&threshold->uuid, uuid)) { - return threshold; - } + if (mb_value && fdb_value) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Invalid aging threshold configuration for datapath:" + " "UUID_FMT, UUID_ARGS(&dp->header_.uuid)); + return 0; } - return NULL; -} - -static uint64_t -mac_cache_threshold_get_value_ms(const struct sbrec_datapath_binding *dp, - enum mac_cache_type type) -{ - uint64_t value = 0; - switch (type) { - case MAC_CACHE_MAC_BINDING: - value = smap_get_uint(&dp->external_ids, "mac_binding_age_threshold", - 0); - break; - case MAC_CACHE_FDB: - value = smap_get_uint(&dp->external_ids, "fdb_age_threshold", 0); - break; - case MAC_CACHE_MAX: - default: - break; - } - - return value * 1000; + return mb_value ? mb_value * 1000 : fdb_value * 1000; } static void diff --git a/controller/mac-cache.h b/controller/mac-cache.h index 932f6cfd4..3c78f9440 100644 --- a/controller/mac-cache.h +++ b/controller/mac-cache.h @@ -29,15 +29,9 @@ struct ovsdb_idl_index; -enum mac_cache_type { - MAC_CACHE_MAC_BINDING, - MAC_CACHE_FDB, - MAC_CACHE_MAX -}; - struct mac_cache_data { - /* 'struct mac_cache_threshold' by datapath UUID. */ - struct hmap thresholds[MAC_CACHE_MAX]; + /* 'struct mac_cache_threshold' by datapath's tunnel_key. */ + struct hmap thresholds; /* 'struct mac_cache_mac_binding' by 'struct mac_cache_mb_data' that are * local and have threshold > 0. */ struct hmap mac_bindings; @@ -48,8 +42,8 @@ struct mac_cache_data { struct mac_cache_threshold { struct hmap_node hmap_node; - /* Datapath UUID. */ - struct uuid uuid; + /* Datapath tunnel key. */ + uint32_t dp_key; /* Aging threshold in ms. */ uint64_t value; /* Statistics dump period. */ @@ -89,8 +83,6 @@ struct fdb { struct fdb_data data; /* Reference to the SB FDB record. */ const struct sbrec_fdb *sbrec_fdb; - /* UUID of datapath for this FDB record. */ - struct uuid dp_uuid; }; struct bp_packet_data { @@ -123,12 +115,15 @@ struct buffered_packets_ctx { }; /* Thresholds. */ -bool mac_cache_threshold_add(struct mac_cache_data *data, - const struct sbrec_datapath_binding *dp, - enum mac_cache_type type); -bool mac_cache_threshold_replace(struct mac_cache_data *data, +void mac_cache_threshold_add(struct mac_cache_data *data, + const struct sbrec_datapath_binding *dp); +void mac_cache_threshold_replace(struct mac_cache_data *data, const struct sbrec_datapath_binding *dp, - enum mac_cache_type type); + const struct hmap *local_datapaths); +struct mac_cache_threshold * +mac_cache_threshold_find(struct mac_cache_data *data, uint32_t dp_key); +void mac_cache_thresholds_sync(struct mac_cache_data *data, + const struct hmap *local_datapaths); void mac_cache_thresholds_clear(struct mac_cache_data *data); /* MAC binding. */ diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index cd50db823..453dc62fd 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -3309,8 +3309,7 @@ mac_binding_remove_sb(struct mac_cache_data *data, } static void -fdb_add_sb(struct mac_cache_data *data, const struct sbrec_fdb *sfdb, - struct uuid dp_uuid) +fdb_add_sb(struct mac_cache_data *data, const struct sbrec_fdb *sfdb) { struct fdb_data fdb_data; if (!fdb_data_from_sbrec(&fdb_data, sfdb)) { @@ -3320,7 +3319,6 @@ fdb_add_sb(struct mac_cache_data *data, const struct sbrec_fdb *sfdb, struct fdb *fdb = fdb_add(&data->fdbs, fdb_data); fdb->sbrec_fdb = sfdb; - fdb->dp_uuid = dp_uuid; } static void @@ -3345,8 +3343,7 @@ mac_cache_mb_handle_for_datapath(struct mac_cache_data *data, struct ovsdb_idl_index *sbrec_mb_by_dp, struct ovsdb_idl_index *sbrec_pb_by_name) { - bool has_threshold = - mac_cache_threshold_replace(data, dp, MAC_CACHE_MAC_BINDING); + bool has_threshold = mac_cache_threshold_find(data, dp->tunnel_key); struct sbrec_mac_binding *mb_index_row = sbrec_mac_binding_index_init_row(sbrec_mb_by_dp); @@ -3369,7 +3366,7 @@ mac_cache_fdb_handle_for_datapath(struct mac_cache_data *data, const struct sbrec_datapath_binding *dp, struct ovsdb_idl_index *sbrec_fdb_by_dp_key) { - bool has_threshold = mac_cache_threshold_replace(data, dp, MAC_CACHE_FDB); + bool has_threshold = mac_cache_threshold_find(data, dp->tunnel_key); struct sbrec_fdb *fdb_index_row = sbrec_fdb_index_init_row(sbrec_fdb_by_dp_key); @@ -3378,7 +3375,7 @@ mac_cache_fdb_handle_for_datapath(struct mac_cache_data *data, const struct sbrec_fdb *fdb; SBREC_FDB_FOR_EACH_EQUAL (fdb, fdb_index_row, sbrec_fdb_by_dp_key) { if (has_threshold) { - fdb_add_sb(data, fdb, dp->header_.uuid); + fdb_add_sb(data, fdb); } else { fdb_remove_sb(data, fdb); } @@ -3393,9 +3390,7 @@ en_mac_cache_init(struct engine_node *node OVS_UNUSED, { struct mac_cache_data *cache_data = xzalloc(sizeof *cache_data); - for (size_t i = 0; i < MAC_CACHE_MAX; i++) { - hmap_init(&cache_data->thresholds[i]); - } + hmap_init(&cache_data->thresholds); hmap_init(&cache_data->mac_bindings); hmap_init(&cache_data->fdbs); @@ -3408,47 +3403,37 @@ en_mac_cache_run(struct engine_node *node, void *data) struct mac_cache_data *cache_data = data; struct ed_type_runtime_data *rt_data = engine_get_input_data("runtime_data", node); - const struct sbrec_mac_binding_table *mb_table = - EN_OVSDB_GET(engine_get_input("SB_mac_binding", node)); - const struct sbrec_fdb_table *fdb_table = - EN_OVSDB_GET(engine_get_input("SB_fdb", node)); + const struct sbrec_datapath_binding_table *dp_table = + EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node)); + struct ovsdb_idl_index *sbrec_mb_by_dp = + engine_ovsdb_node_get_index( + engine_get_input("SB_mac_binding", node), + "datapath"); struct ovsdb_idl_index *sbrec_pb_by_name = engine_ovsdb_node_get_index( engine_get_input("SB_port_binding", node), "name"); + struct ovsdb_idl_index *sbrec_fdb_by_dp_key = + engine_ovsdb_node_get_index( + engine_get_input("SB_fdb", node), + "dp_key"); mac_cache_thresholds_clear(cache_data); mac_bindings_clear(&cache_data->mac_bindings); fdbs_clear(&cache_data->fdbs); - const struct sbrec_mac_binding *sbrec_mb; - SBREC_MAC_BINDING_TABLE_FOR_EACH (sbrec_mb, mb_table) { + const struct sbrec_datapath_binding *sbrec_dp; + SBREC_DATAPATH_BINDING_TABLE_FOR_EACH (sbrec_dp, dp_table) { if (!get_local_datapath(&rt_data->local_datapaths, - sbrec_mb->datapath->tunnel_key)) { - continue; - } - - if (mac_cache_threshold_add(cache_data, sbrec_mb->datapath, - MAC_CACHE_MAC_BINDING)) { - mac_binding_add_sb(cache_data, sbrec_mb, - sbrec_pb_by_name); - } - } - - struct local_datapath *local_dp; - const struct sbrec_fdb *sbrec_fdb; - SBREC_FDB_TABLE_FOR_EACH (sbrec_fdb, fdb_table) { - local_dp = get_local_datapath(&rt_data->local_datapaths, - sbrec_fdb->dp_key); - if (!local_dp) { + sbrec_dp->tunnel_key)) { continue; } - if (mac_cache_threshold_add(cache_data, local_dp->datapath, - MAC_CACHE_FDB)) { - fdb_add_sb(cache_data, sbrec_fdb, - local_dp->datapath->header_.uuid); - } + mac_cache_threshold_add(cache_data, sbrec_dp); + mac_cache_mb_handle_for_datapath(cache_data, sbrec_dp, + sbrec_mb_by_dp, sbrec_pb_by_name); + mac_cache_fdb_handle_for_datapath(cache_data, sbrec_dp, + sbrec_fdb_by_dp_key); } engine_set_node_state(node, EN_UPDATED); @@ -3486,10 +3471,9 @@ mac_cache_sb_mac_binding_handler(struct engine_node *node, void *data) continue; } - if (mac_cache_threshold_add(cache_data, sbrec_mb->datapath, - MAC_CACHE_MAC_BINDING)) { - mac_binding_add_sb(cache_data, sbrec_mb, - sbrec_pb_by_name); + if (mac_cache_threshold_find(cache_data, + sbrec_mb->datapath->tunnel_key)) { + mac_binding_add_sb(cache_data, sbrec_mb, sbrec_pb_by_name); } } @@ -3528,10 +3512,8 @@ mac_cache_sb_fdb_handler(struct engine_node *node, void *data) continue; } - if (mac_cache_threshold_add(cache_data, local_dp->datapath, - MAC_CACHE_FDB)) { - fdb_add_sb(cache_data, sbrec_fdb, - local_dp->datapath->header_.uuid); + if (mac_cache_threshold_find(cache_data, sbrec_fdb->dp_key)) { + fdb_add_sb(cache_data, sbrec_fdb); } } @@ -3571,10 +3553,14 @@ mac_cache_runtime_data_handler(struct engine_node *node, void *data OVS_UNUSED) struct tracked_datapath *tdp; HMAP_FOR_EACH (tdp, node, &rt_data->tracked_dp_bindings) { - if (tdp->tracked_type != TRACKED_RESOURCE_NEW) { + if (tdp->tracked_type == TRACKED_RESOURCE_UPDATED) { continue; } + mac_cache_threshold_replace(cache_data, tdp->dp, + &rt_data->local_datapaths); + } + HMAP_FOR_EACH (tdp, node, &rt_data->tracked_dp_bindings) { mac_cache_mb_handle_for_datapath(cache_data, tdp->dp, sbrec_mb_by_dp, sbrec_pb_by_name); @@ -3613,16 +3599,25 @@ mac_cache_sb_datapath_binding_handler(struct engine_node *node, void *data) size_t previous_mb_size = hmap_count(&cache_data->mac_bindings); size_t previous_fdb_size = hmap_count(&cache_data->fdbs); + bool sync_needed = false; const struct sbrec_datapath_binding *sbrec_dp; - SBREC_DATAPATH_BINDING_TABLE_FOR_EACH (sbrec_dp, dp_table) { - if (sbrec_datapath_binding_is_new(sbrec_dp) || - sbrec_datapath_binding_is_deleted(sbrec_dp) || - !get_local_datapath(&rt_data->local_datapaths, - sbrec_dp->tunnel_key)) { - continue; + SBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (sbrec_dp, dp_table) { + if (!sbrec_datapath_binding_is_new(sbrec_dp) && + sbrec_datapath_binding_is_updated( + sbrec_dp, SBREC_DATAPATH_BINDING_COL_TUNNEL_KEY)) { + sync_needed = true; } + mac_cache_threshold_replace(cache_data, sbrec_dp, + &rt_data->local_datapaths); + } + + if (sync_needed) { + mac_cache_thresholds_sync(cache_data, &rt_data->local_datapaths); + } + + SBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (sbrec_dp, dp_table) { mac_cache_mb_handle_for_datapath(cache_data, sbrec_dp, sbrec_mb_by_dp, sbrec_pb_by_name); @@ -3645,9 +3640,7 @@ en_mac_cache_cleanup(void *data) struct mac_cache_data *cache_data = data; mac_cache_thresholds_clear(cache_data); - for (size_t i = 0; i < MAC_CACHE_MAX; i++) { - hmap_destroy(&cache_data->thresholds[i]); - } + hmap_destroy(&cache_data->thresholds); mac_bindings_clear(&cache_data->mac_bindings); hmap_destroy(&cache_data->mac_bindings); fdbs_clear(&cache_data->fdbs); diff --git a/tests/ovn.at b/tests/ovn.at index 784b3dd1f..9c173f6cf 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -34540,7 +34540,7 @@ OVS_CTL_TIMEOUT=10 OVS_WAIT_UNTIL([ test "$timestamp" != "$(fetch_column mac_binding timestamp ip='192.168.10.20')" ]) -check $(test "$(fetch_column mac_binding timestamp ip='192.168.10.20')" != "") +check test "$(fetch_column mac_binding timestamp ip='192.168.10.20')" != "" # Check if the records are removed after some inactivity OVS_WAIT_UNTIL([ @@ -36445,7 +36445,7 @@ OVS_WAIT_UNTIL([ test "$timestamp" != "$curr_timestamp" ]) timestamp=$(fetch_column fdb timestamp mac='"00:00:00:00:10:20"') -check $(test "$timestamp" != "") +check test "$timestamp" != "" # Check if the records are removed after some inactivity wait_row_count fdb 0 mac='"00:00:00:00:10:20"'