From patchwork Thu Aug 5 14:50:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frode Nordahl X-Patchwork-Id: 1513943 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=TlXAuDCD; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GgWmW35DRz9sW8 for ; Fri, 6 Aug 2021 00:52:27 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id B9C7C83AD4; Thu, 5 Aug 2021 14:52:24 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id S1Nli5OH4k7F; Thu, 5 Aug 2021 14:52:23 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 83B3E83AB4; Thu, 5 Aug 2021 14:52:22 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 9A3A1C0028; Thu, 5 Aug 2021 14:52:21 +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 212ABC0020 for ; Thu, 5 Aug 2021 14:52:20 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id F2E1B4042A for ; Thu, 5 Aug 2021 14:52:19 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp2.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Tdzj6t6926Bn for ; Thu, 5 Aug 2021 14:52:17 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by smtp2.osuosl.org (Postfix) with ESMTPS id A47C94033A for ; Thu, 5 Aug 2021 14:52:17 +0000 (UTC) Received: by mail-lf1-x12b.google.com with SMTP id z2so11700175lft.1 for ; Thu, 05 Aug 2021 07:52:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xPlhWUu+tlI+RS75vJThPnON/mUJQia5HmCTQ3tPnxU=; b=TlXAuDCDiZv55Chl7gCfFnSSLdrcRSSuid1rHhQNaxARvfa9ysHDJE8HM7T1W8EKPl nR+1YwNA2TVfDyZbpF7EbMVgwxypD3//p8+zN1FnAD1+R4U57kIY7d6sSxlQ2boOZCwJ SZW1V4m/w7oP4Er953vZM8ws5uZhtDOkCSwAj75y0u0yyIy6U2WNlBDdXkLVfVa3y9CC Gl6YzZni2RZZ9DhVg3xoUFumGH7yQcNTKYqv02oCyyr64UXzIPglFE3Z/eRd0v1jDz8o 8q3T7yVF1cRDigesJxpoPTQiFvbxt0D7wzxNwP1sVzDov3Fx1cb8XPCRznvYa6Ko94Cw MHYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xPlhWUu+tlI+RS75vJThPnON/mUJQia5HmCTQ3tPnxU=; b=lMKWG0xTsEd1spXk2pBopRns5TXo3k4Ny+QEt9IdRXCJvcFl847ycAmo9SVq34oe77 UOpu5tYhWwoyYUHi0eu+gKE+nQ/F0tzwGRbp5hxNfXPkVvVzXkkxaj44hUnEWHGX4i5L +PobCvk1pGit7jDTS0tNzKoJjokk6U1kG4SN2mIX/5C3+c7gT9grS38PstALbW4FuTHY LJKkfEOd1iXmmkIHVLBDog7IY+r7w0No5Z9Oem+TCZpsK66TyMd7eQUeNuG24OJbVSGf fzlevR+bfSqbB9Opm3jPc5fW5RITQAUJJHMB/E+nC1JcHEgeDr+YqS4tLAX81KIOHPBO 9TzQ== X-Gm-Message-State: AOAM530fy4q/m+gNTeaCTq+k7hkx7v7FPtjPmDvNMtnzHcbZQ0dkYsy1 fn+o1QP9P5Bfe2sHR79izIYb6fIdcQc= X-Google-Smtp-Source: ABdhPJyoGcLFnqJgfmRsw+A0NSiigJqGPcQybEE758sCWThnJ4muTnUaOwDsaKyN/PsH9w3Nh4sD1A== X-Received: by 2002:a05:6512:4010:: with SMTP id br16mr3959719lfb.27.1628175135250; Thu, 05 Aug 2021 07:52:15 -0700 (PDT) Received: from ti0189a330-1161.bb.online.no (ti0189a330-1161.bb.online.no. [88.88.219.141]) by smtp.gmail.com with ESMTPSA id p14sm536632lfa.117.2021.08.05.07.52.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Aug 2021 07:52:15 -0700 (PDT) From: Frode Nordahl To: dev@openvswitch.org Date: Thu, 5 Aug 2021 16:50:08 +0200 Message-Id: <20210805145013.3033919-2-frode.nordahl@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805145013.3033919-1-frode.nordahl@gmail.com> References: <20210805145013.3033919-1-frode.nordahl@gmail.com> MIME-Version: 1.0 Cc: i.maximets@ovn.org Subject: [ovs-dev] [RFC PATCH ovn 1/6] ovn-sb: Add plugged_by column to Port_Binding. 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" ovn-northd will fill this column with UUID of Chassis referenced in Logical_Switch_Port options:requested-chassis when options:plug-type is defined. Signed-off-by: Frode Nordahl --- northd/ovn-northd.c | 31 +++++++++++++++++++++++++++++++ ovn-nb.xml | 38 ++++++++++++++++++++++++++++++++++++++ ovn-sb.ovsschema | 10 +++++++--- ovn-sb.xml | 15 +++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index a0eaa1247..847860219 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -3164,6 +3164,35 @@ ovn_port_update_sbrec(struct northd_context *ctx, * ha_chassis_group cleared in the same transaction. */ sbrec_port_binding_set_ha_chassis_group(op->sb, NULL); } + + const char *plug_type; /* May be NULL. */ + const char *requested_chassis; /* May be NULL. */ + bool reset_plugged_by = false; + plug_type = smap_get(&op->nbsp->options, "plug-type"); + requested_chassis = smap_get(&op->nbsp->options, + "requested-chassis"); + if (plug_type && requested_chassis) { + const struct sbrec_chassis *chassis; /* May be NULL. */ + chassis = chassis_lookup_by_name(sbrec_chassis_by_name, + requested_chassis); + if (chassis) { + sbrec_port_binding_set_plugged_by(op->sb, chassis); + } else { + reset_plugged_by = true; + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT( + 1, 1); + VLOG_WARN_RL( + &rl, + "Unknown chassis '%s' set as " + "options:requested-chassis on LSP '%s'.", + requested_chassis, op->nbsp->name); + } + } else if (op->sb->plugged_by) { + reset_plugged_by = true; + } + if (reset_plugged_by) { + sbrec_port_binding_set_plugged_by(op->sb, NULL); + } } else { const char *chassis = NULL; if (op->peer && op->peer->od && op->peer->od->nbr) { @@ -14883,6 +14912,8 @@ main(int argc, char *argv[]) add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_nat_addresses); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_chassis); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, + &sbrec_port_binding_col_plugged_by); ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_gateway_chassis); ovsdb_idl_add_column(ovnsb_idl_loop.idl, diff --git a/ovn-nb.xml b/ovn-nb.xml index c1176e81f..d2cf3a984 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -1020,6 +1020,44 @@ DHCP reply.

+ + +

+ These options apply to logical ports with + and + set. +

+ + + If set, OVN will attempt to to perform plugging of this VIF. In + order to get this port plugged by the OVN controller, OVN must be + built with support for VIF plugging. The default behavior is for + the CMS to do the VIF plugging. + Supported values: representor + + + + MAC address for identifying PF device. When + is also set, this + option is used to identify PF to use as base to locate the correct + VF representor port. When + is not set this + option is used to locate a PF representor port. + + + + Logical VF number relative to PF device specified in + . + + + + Requested MTU for plugged interfaces. When set the OVN controller + will fill the column + of the Open vSwitch database's + table. This in turn will + make OVS vswitchd update the MTU of the linked interface. + +
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index e5ab41db9..4df326ff4 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "20.20.0", - "cksum": "605270161 26670", + "version": "20.21.0", + "cksum": "888060012 26935", "tables": { "SB_Global": { "columns": { @@ -232,7 +232,11 @@ "external_ids": {"type": {"key": "string", "value": "string", "min": 0, - "max": "unlimited"}}}, + "max": "unlimited"}}, + "plugged_by": {"type": {"key": {"type": "uuid", + "refTable": "Chassis", + "refType": "weak"}, + "min": 0, "max": 1}}}, "indexes": [["datapath", "tunnel_key"], ["logical_port"]], "isRoot": true}, "MAC_Binding": { diff --git a/ovn-sb.xml b/ovn-sb.xml index e6ce243cf..536b9a31b 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -2992,6 +2992,21 @@ tcp.flags = RST; + + Chassis that should plug this port, this column must be a + record. This is populated by + ovn-northd when the and is defined. In order to get this port plugged by + the OVN controller, OVN must be built with support for VIF plugging. + The default behavior is for the CMS to do the VIF plugging. + From patchwork Thu Aug 5 14:50:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frode Nordahl X-Patchwork-Id: 1513944 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=lm+zK4oG; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GgWmY5w8Pz9s5R for ; Fri, 6 Aug 2021 00:52:29 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id A8B4683AE4; Thu, 5 Aug 2021 14:52:26 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id VWmTr50jyZmo; Thu, 5 Aug 2021 14:52:25 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id D13A183ACA; Thu, 5 Aug 2021 14:52:23 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 76C71C0021; Thu, 5 Aug 2021 14:52:22 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 251C6C0010 for ; Thu, 5 Aug 2021 14:52:21 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id EDE7483A72 for ; Thu, 5 Aug 2021 14:52:20 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id sePHiY1Q99uZ for ; Thu, 5 Aug 2021 14:52:19 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by smtp1.osuosl.org (Postfix) with ESMTPS id 91CB683A40 for ; Thu, 5 Aug 2021 14:52:18 +0000 (UTC) Received: by mail-lf1-x134.google.com with SMTP id b6so11600880lff.10 for ; Thu, 05 Aug 2021 07:52:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1dqDMFE9mADBJBhmdAhxk+iXpc1tNYne8TUHQEc/Lfo=; b=lm+zK4oGcV6tIHJap8yzh52HS3dpifsBNAS+/G/tnlKi4rEztEccZHlUpZU71+vu41 Ar+MemUTJVWEVEusSnRlm64+Ces8+JnGGLCH0/9q13CE0yhSOjgDCA6dVZDw55YhSODL CO1UqA+vZ67cXqPo6GOr3QOYzqhrnWL6voXcocGKdcrYjrwVI53koK/dACkqZM88kjPv oWGbXM1gx5JE/0cEOUCA9nUYyBIO4mXteSfDmvIl/g8yAhUWMRp6YDDgnkjWkEzy/uDd 5uel0LCcTrALR2d+XM6y+BZdAN/0XeDymO8TPgnsl+4XzEybPJe2Inwrt/uQaa2ps0u3 hpkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1dqDMFE9mADBJBhmdAhxk+iXpc1tNYne8TUHQEc/Lfo=; b=lkvmABvAPznYyyUOIf/JTmw4cjQp922SUM+GE/MGNvuPfGrz4Q83HfyOATU1xOH2ju wF8+7YoYRBdMnQNJaWzPGiGnTuu6lZ5Vn2FwYene9M+2arp0MZ1DzZ7JEfD0b8PnIiMH 34EgyfX9r1loz1HIZd9jax3o70n3luFfv7b90Rv+tZRIB8fCgE1ffp0Tz/0UZqVF58Hy p25Py8DFYYx/LKhtv/NVafu2j3obPB7PmGEmLPg5saRipOUBEbJHuUWJyS+lMSJjZ1MN Io9oiaYwcGEzxngl03MFVoaX069dYom0tNaUz/fquM7Va9Baa5H8O3RAQWb1qO/nytZZ r5IQ== X-Gm-Message-State: AOAM533i4giC+2nXcve83SpcB3wkiRIZSKnVD3K0YV+3HwlvbyTWWdWa BeV32dBskyESKf8r9IWhtruIIR5/dNQ= X-Google-Smtp-Source: ABdhPJz32q1DjoZnxwqTtFsfO4WQqZTKaYi9r89v2GJHWJMwyXYGQZ4Onj+9Wd3T3kJQjgB14ZbqOg== X-Received: by 2002:a05:6512:ea9:: with SMTP id bi41mr3926650lfb.103.1628175135873; Thu, 05 Aug 2021 07:52:15 -0700 (PDT) Received: from ti0189a330-1161.bb.online.no (ti0189a330-1161.bb.online.no. [88.88.219.141]) by smtp.gmail.com with ESMTPSA id p14sm536632lfa.117.2021.08.05.07.52.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Aug 2021 07:52:15 -0700 (PDT) From: Frode Nordahl To: dev@openvswitch.org Date: Thu, 5 Aug 2021 16:50:09 +0200 Message-Id: <20210805145013.3033919-3-frode.nordahl@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805145013.3033919-1-frode.nordahl@gmail.com> References: <20210805145013.3033919-1-frode.nordahl@gmail.com> MIME-Version: 1.0 Cc: i.maximets@ovn.org Subject: [ovs-dev] [RFC PATCH ovn 2/6] lib: Move OVS port functions to ovsport module X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Up until now the controller patch module has been the only consumer of functions to maintain OVS ports and interfaces. With the introduction of infrastructure for plugging providers these functions will also be consumed by the controller binding module. As such we introduce a new module called ovsport where these shared utility functions can live and be consumed by multiple modules. Signed-off-by: Frode Nordahl --- lib/automake.mk | 4 +- lib/ovsport.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/ovsport.h | 61 ++++++++++++ 3 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 lib/ovsport.c create mode 100644 lib/ovsport.h diff --git a/lib/automake.mk b/lib/automake.mk index ddfe33948..d82908b92 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -32,7 +32,9 @@ lib_libovn_la_SOURCES = \ lib/inc-proc-eng.h \ lib/lb.c \ lib/lb.h \ - lib/stopwatch-names.h + lib/stopwatch-names.h \ + lib/ovsport.h \ + lib/ovsport.c nodist_lib_libovn_la_SOURCES = \ lib/ovn-dirs.c \ lib/ovn-nb-idl.c \ diff --git a/lib/ovsport.c b/lib/ovsport.c new file mode 100644 index 000000000..d81d9521e --- /dev/null +++ b/lib/ovsport.c @@ -0,0 +1,253 @@ +/* Copyright (c) 2021 Canonical + * + * 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 "ovsport.h" + +#include "lib/vswitch-idl.h" +#include "openvswitch/vlog.h" + +VLOG_DEFINE_THIS_MODULE(ovsport); + +/* Create a port and interface record and add it to 'bridge' in the Open + * vSwitch database represented by 'ovs_idl_txn'. + * + * 'name' is required and is used both for the name of the port and interface + * records. Depending on the contents of the optional 'iface_type' parameter + * the name may need to refer to an existing interface in the system. It is + * the callers responsibility to ensure that no other port with the desired + * name already exist. + * + * 'iface_type' optionally specifies the type of intercace, otherwise set it to + * NULL. + * + * 'port_external_ids' - the contents of the map will be used to fill the + * external_ids column of the created port record, otherwise set it to NULL. + * + * 'iface_external_ids' - the contents of the map will be used to fill the + * external_ids column of the created interface record, otherwise set it to + * NULL. + * + * 'iface_options' - the contents of the map will be used to fill the options + * column of the created interface record, otherwise set it to NULL. + * + * 'iface_mtu_request' - if a value > 0 is provided it will be filled into the + * mtu_request column of the created interface record. */ +void +ovs_create_port(struct ovsdb_idl_txn *ovs_idl_txn, + const struct ovsrec_bridge *bridge, + const char *name, + const char *iface_type, + const struct smap *port_external_ids, + const struct smap *iface_external_ids, + const struct smap *iface_options, + const int64_t iface_mtu_request) +{ + struct ovsrec_interface *iface; + iface = ovsrec_interface_insert(ovs_idl_txn); + ovsrec_interface_set_name(iface, name); + if (iface_type) { + ovsrec_interface_set_type(iface, iface_type); + } + ovsrec_interface_set_external_ids(iface, iface_external_ids); + ovsrec_interface_set_options(iface, iface_options); + ovsrec_interface_set_mtu_request( + iface, &iface_mtu_request, iface_mtu_request > 0); + + struct ovsrec_port *port; + port = ovsrec_port_insert(ovs_idl_txn); + ovsrec_port_set_name(port, name); + ovsrec_port_set_interfaces(port, &iface, 1); + ovsrec_port_set_external_ids(port, port_external_ids); + + ovsrec_bridge_update_ports_addvalue(bridge, port); + ovsrec_bridge_verify_ports(bridge); +} + +/* Remove 'port' from 'bridge' and delete the 'port' recrd and any records + * with a weakRef to it. */ +void +ovs_remove_port(const struct ovsrec_bridge *bridge, + const struct ovsrec_port *port) +{ + ovsrec_bridge_update_ports_delvalue(bridge, port); + ovsrec_bridge_verify_ports(bridge); + ovsrec_port_delete(port); +} + +static void update_interface_smap_column( + const struct ovsrec_interface *, const struct smap *, + const struct smap *, void (*fsetkey)(const struct ovsrec_interface *, + const char *, const char *)); +static void maintain_interface_smap_column( + const struct ovsrec_interface *, const struct sset *, + const struct smap *, const struct smap *, + void (*fsetkey)(const struct ovsrec_interface *, const char *, + const char *), + void (*fdelkey)(const struct ovsrec_interface *, + const char *)); + +/* Update interface record as represented by 'iface'. + * + * 'type' optionally specifies the type of interface, to unset type set to an + * empty string, to not update type set to NULL. + * + * 'external_ids' optionally provide a map of external_ids to update, to not + * update external_ids set to NULL. + * + * 'mnt_external_ids' optionally provide set of 'external_ids' to maintain. + * When set the function will make sure that all keys in the 'mnt_external_ids' + * set have values from the 'external_ids' map in the database. Every key that + * exist in 'mnt_external_ids' with no corresponding key in 'external_ids' will + * be removed from the database if present. Set to NULL to not maintain the + * record in this way. + * + * 'options' optionally provide a map of options to update, to not + * update options set to NULL. + * + * 'mnt_options' optionally provide set of 'options' to maintain. + * When set the function will make sure that all keys in the 'mnt_options' set + * have values from the 'options' map in the database. Every key that exist in + * 'mnt_options' with no corresponding key in 'options' will be + * removed from the database if present. Set to NULL to not maintain the + * record in this way. + * + * 'iface_mtu_request' - if a value > 0 is provided it will be filled into the + * mtu_request column of the created interface record. */ +void +ovs_update_iface(const struct ovsrec_interface *iface, + const char *type, + const struct smap *external_ids, + const struct sset *mnt_external_ids, + const struct smap *options, + const struct sset *mnt_options, + const int64_t mtu_request) +{ + if (type && strcmp(iface->type, type)) { + ovsrec_interface_set_type(iface, type); + } + if (external_ids && mnt_external_ids) { + maintain_interface_smap_column( + iface, mnt_external_ids, external_ids, &iface->external_ids, + ovsrec_interface_update_external_ids_setkey, + ovsrec_interface_update_external_ids_delkey); + } else if (external_ids) { + update_interface_smap_column( + iface, external_ids, &iface->external_ids, + ovsrec_interface_update_external_ids_setkey); + } + if (options && mnt_options) { + maintain_interface_smap_column( + iface, mnt_options, options, &iface->options, + ovsrec_interface_update_options_setkey, + ovsrec_interface_update_options_delkey); + } else if (options) { + update_interface_smap_column( + iface, options, &iface->options, + ovsrec_interface_update_options_setkey); + } + if (mtu_request > 0) + { + if ((iface->mtu_request && *iface->mtu_request != mtu_request) + || !iface->mtu_request) + { + ovsrec_interface_set_mtu_request( + iface, &mtu_request, mtu_request > 0); + } + } else if (iface->mtu_request) { + ovsrec_interface_update_mtu_request_delvalue(iface, + *iface->mtu_request); + } +} + +const struct ovsrec_port * +ovsport_lookup_by_interfaces( + struct ovsdb_idl_index *ovsrec_port_by_interfaces, + struct ovsrec_interface **interfaces, + const size_t n_interfaces) +{ + struct ovsrec_port *port = ovsrec_port_index_init_row( + ovsrec_port_by_interfaces); + ovsrec_port_index_set_interfaces(port, interfaces, n_interfaces); + + const struct ovsrec_port *retval = ovsrec_port_index_find( + ovsrec_port_by_interfaces, port); + + ovsrec_port_index_destroy_row(port); + + return retval; +} + +const struct +ovsrec_port * ovsport_lookup_by_interface( + struct ovsdb_idl_index *ovsrec_port_by_interfaces, + struct ovsrec_interface *interface) +{ + struct ovsrec_interface *interfaces[] = {interface}; + + return ovsport_lookup_by_interfaces(ovsrec_port_by_interfaces, + interfaces, 1); +} + +/* Update an interface map column with the key/value pairs present in the + * provided smap, only applying changes when necessary. */ +static void +update_interface_smap_column( + const struct ovsrec_interface *iface, + const struct smap *smap, + const struct smap *db_smap, + void (*fsetkey)(const struct ovsrec_interface *, + const char *, const char *)) +{ + struct smap_node *node; + SMAP_FOR_EACH(node, smap) { + const char *db_value = smap_get(db_smap, node->key); + + if ((db_value && strcmp(db_value, node->value)) + || !db_value) + { + fsetkey(iface, node->key, node->value); + } + } +} + +/* Like update_interface_smap_column, but also takes an sset with all the keys + * we want to maintain. Any key present in the sset but not in the provided + * smap will be removed from the database if present there. */ +static void +maintain_interface_smap_column( + const struct ovsrec_interface *iface, + const struct sset *mnt_items, + const struct smap *smap, + const struct smap *db_smap, + void (*fsetkey)(const struct ovsrec_interface *, + const char *, const char *), + void (*fdelkey)(const struct ovsrec_interface *, + const char *)) +{ + const char *ref_name; + SSET_FOR_EACH(ref_name, mnt_items) { + const char *value = smap_get(smap, ref_name); + const char *db_value = smap_get(db_smap, ref_name); + if (!value && db_value) { + fdelkey(iface, ref_name); + } else if ((db_value && value && strcmp(db_value, value)) + || (value && !db_value)) + { + fsetkey(iface, ref_name, value); + } + } +} + diff --git a/lib/ovsport.h b/lib/ovsport.h new file mode 100644 index 000000000..e30a7953f --- /dev/null +++ b/lib/ovsport.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2021 Canonical + * + * 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 OVSPORT_H +#define OVSPORT_H 1 + +/* OVS Ports + * ========= + * + * This module contains utility functions for adding, removing and maintaining + * ports and their interface records on OVS bridges. */ + +#include "smap.h" +#include "sset.h" + +#include +#include + +struct ovsdb_idl_txn; +struct ovsrec_bridge; +struct ovsrec_port; +struct ovsrec_interface; +struct ovsdb_idl_index; + +void ovs_create_port(struct ovsdb_idl_txn *ovs_idl_txn, + const struct ovsrec_bridge *bridge, + const char *name, + const char *iface_type, + const struct smap *port_external_ids, + const struct smap *iface_external_ids, + const struct smap *iface_options, + const int64_t iface_mtu_request); +void ovs_remove_port(const struct ovsrec_bridge *bridge, + const struct ovsrec_port *port); +void ovs_update_iface(const struct ovsrec_interface *iface, + const char *type, + const struct smap *external_ids, + const struct sset *mnt_external_ids, + const struct smap *options, + const struct sset *mnt_options, + const int64_t mtu_request); +const struct ovsrec_port * ovsport_lookup_by_interfaces( + struct ovsdb_idl_index *, struct ovsrec_interface **, + const size_t n_interfaces); +const struct ovsrec_port * ovsport_lookup_by_interface( + struct ovsdb_idl_index *, struct ovsrec_interface *); + + +#endif /* lib/ovsport.h */ From patchwork Thu Aug 5 14:50:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frode Nordahl X-Patchwork-Id: 1513945 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=bCtgRpR9; dkim-atps=neutral Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GgWmZ6Fqqz9sW8 for ; Fri, 6 Aug 2021 00:52:30 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id EA6BC4057D; Thu, 5 Aug 2021 14:52:27 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 0_0xsutwByua; Thu, 5 Aug 2021 14:52:26 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 5B1F7404E5; Thu, 5 Aug 2021 14:52:25 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 53EAFC0027; Thu, 5 Aug 2021 14:52:23 +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 6858DC0010 for ; Thu, 5 Aug 2021 14:52:21 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 482EE4045C for ; Thu, 5 Aug 2021 14:52:21 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp2.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5SDORrkcF4xl for ; Thu, 5 Aug 2021 14:52:19 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-lf1-x129.google.com (mail-lf1-x129.google.com [IPv6:2a00:1450:4864:20::129]) by smtp2.osuosl.org (Postfix) with ESMTPS id DD990400F7 for ; Thu, 5 Aug 2021 14:52:18 +0000 (UTC) Received: by mail-lf1-x129.google.com with SMTP id p38so11755079lfa.0 for ; Thu, 05 Aug 2021 07:52:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SCDbZv7A81XBwYJZ5M3c07U7fdZ9CzrjHNpVGb3f5Rg=; b=bCtgRpR9oJMeZBNLSmgnUaFwzdFPW7ivMSQqFny3/9Jtw+L4G2DjCjIsRnVB4OhzAA 29v/14UASCHj5Y/T/b8i6JMG7WHs/MkoEjHLpO1InMKVOmRAf7v1BN/baR+qG7ML3URQ +7/HYxHdY7rqpJkNEorD4L6Zj7QniHfJ93/inwS3PA4YzvQZ3yLgkFV8F/9+bUBxtgu9 ivFbYhbnzNeCvFKOLuJWpp1jEZYH76s/5P9DnPCLZJ5SPf/sYiw9yiGVuze6vA9sT1s0 xwHaxFBo+fuX2NuJrRbNWyt/CyYG7H4pIQKjfLKKeAKy44uz2L/jJrsnrzkieit1juwG +ckg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SCDbZv7A81XBwYJZ5M3c07U7fdZ9CzrjHNpVGb3f5Rg=; b=cPOvOU649oqrnH3PNI0X2LnPhpKCCQ9utNFaZFu4yopLTs3IJl6Ke7DfCgrwrNFeKP C2u97UeUbxu3VN++nK20E0kT+7KfAgeZUfzZDy0lflLA3E5StcyUVU7DKtPaK5nLNPv2 XT6ome4TvkLZ/o8YHNnUH2P6jB2Gg5Og+92H0llSn/sGznC///x35uCztA2Npa4iAWNF /5GU0LCIgI5mmGUnP+wgS/J5ZFyEF2z6FLv1WRwe1acmvLKYwsDJXTDKhWIJKLkJWYQQ Ht/ZsBuQO7Fx6sVZNSLS6aEV4mgXJXhF4yWDnF3RvLlcdms0Drismm5Xy979feePJpXr Qymg== X-Gm-Message-State: AOAM532IYKr0WRV7O1HRGxWoNN3rWIapYAx1RqF1SNY0ullvX7BOJqEo TJH0Ekd+uXzGhmqZ3SLVRMsKv5KwweQ= X-Google-Smtp-Source: ABdhPJy/MALlPSbVT4zVzRvW3b+L34a8P0AlmvUjcnhTH9q2XMe+FTdSoZtrUouvvN8hX/bxIv/0PQ== X-Received: by 2002:a05:6512:1511:: with SMTP id bq17mr4071587lfb.341.1628175136584; Thu, 05 Aug 2021 07:52:16 -0700 (PDT) Received: from ti0189a330-1161.bb.online.no (ti0189a330-1161.bb.online.no. [88.88.219.141]) by smtp.gmail.com with ESMTPSA id p14sm536632lfa.117.2021.08.05.07.52.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Aug 2021 07:52:16 -0700 (PDT) From: Frode Nordahl To: dev@openvswitch.org Date: Thu, 5 Aug 2021 16:50:10 +0200 Message-Id: <20210805145013.3033919-4-frode.nordahl@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805145013.3033919-1-frode.nordahl@gmail.com> References: <20210805145013.3033919-1-frode.nordahl@gmail.com> MIME-Version: 1.0 Cc: i.maximets@ovn.org Subject: [ovs-dev] [RFC PATCH ovn 3/6] patch: Consume ovsport functions 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" Make use of the common functions for maintaining OVS ports. Signed-off-by: Frode Nordahl --- controller/patch.c | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/controller/patch.c b/controller/patch.c index a661025da..b26e93e53 100644 --- a/controller/patch.c +++ b/controller/patch.c @@ -16,6 +16,7 @@ #include #include "patch.h" +#include "ovsport.h" #include "hash.h" #include "lflow.h" @@ -91,28 +92,10 @@ create_patch_port(struct ovsdb_idl_txn *ovs_idl_txn, "ovn-controller: creating patch port '%s' from '%s' to '%s'", src_name, src->name, dst->name); - struct ovsrec_interface *iface; - iface = ovsrec_interface_insert(ovs_idl_txn); - ovsrec_interface_set_name(iface, src_name); - ovsrec_interface_set_type(iface, "patch"); - const struct smap options = SMAP_CONST1(&options, "peer", dst_name); - ovsrec_interface_set_options(iface, &options); - - struct ovsrec_port *port; - port = ovsrec_port_insert(ovs_idl_txn); - ovsrec_port_set_name(port, src_name); - ovsrec_port_set_interfaces(port, &iface, 1); - const struct smap ids = SMAP_CONST1(&ids, key, value); - ovsrec_port_set_external_ids(port, &ids); - - struct ovsrec_port **ports; - ports = xmalloc(sizeof *ports * (src->n_ports + 1)); - memcpy(ports, src->ports, sizeof *ports * src->n_ports); - ports[src->n_ports] = port; - ovsrec_bridge_verify_ports(src); - ovsrec_bridge_set_ports(src, ports, src->n_ports + 1); - - free(ports); + const struct smap if_options = SMAP_CONST1(&if_options, "peer", dst_name); + const struct smap port_ids = SMAP_CONST1(&port_ids, key, value); + ovs_create_port(ovs_idl_txn, src, src_name, "patch", &port_ids, NULL, + &if_options, 0); } static void @@ -130,17 +113,7 @@ remove_port(const struct ovsrec_bridge_table *bridge_table, if (bridge->ports[i] != port) { continue; } - struct ovsrec_port **new_ports; - new_ports = xmemdup(bridge->ports, - sizeof *new_ports * (bridge->n_ports - 1)); - if (i != bridge->n_ports - 1) { - /* Removed port was not last */ - new_ports[i] = bridge->ports[bridge->n_ports - 1]; - } - ovsrec_bridge_verify_ports(bridge); - ovsrec_bridge_set_ports(bridge, new_ports, bridge->n_ports - 1); - free(new_ports); - ovsrec_port_delete(port); + ovs_remove_port(bridge, port); return; } } From patchwork Thu Aug 5 14:50:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frode Nordahl X-Patchwork-Id: 1513948 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=fbpWTB5K; dkim-atps=neutral Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GgWmh0bRXz9sW8 for ; Fri, 6 Aug 2021 00:52:36 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 7C16260A3C; Thu, 5 Aug 2021 14:52:33 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UanE3gM4-xNO; Thu, 5 Aug 2021 14:52:28 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id E79CA608B8; Thu, 5 Aug 2021 14:52:26 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 19D32C002C; Thu, 5 Aug 2021 14:52:24 +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 E4E4BC002B for ; Thu, 5 Aug 2021 14:52:21 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id CB30A6079B for ; Thu, 5 Aug 2021 14:52:21 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id y02qhF6Meu2X for ; Thu, 5 Aug 2021 14:52:20 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by smtp3.osuosl.org (Postfix) with ESMTPS id DA0E5605CA for ; Thu, 5 Aug 2021 14:52:19 +0000 (UTC) Received: by mail-lf1-x133.google.com with SMTP id bq29so11678381lfb.5 for ; Thu, 05 Aug 2021 07:52:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XRfGrdR3hLub3qcCuhXRL9f92OsUtMSBvuAtXtUhaAY=; b=fbpWTB5KW+rMnf7f+MQ8j/0Pb67oy9M1beuxQSTI/JBV5lA6ROYrclVIWahgEYWXOO I8NGuk8Kn5rz6b3sKCoZZFj6xbs0vQcxrZVMwEQYuc90Z5DRAbw1roEa181TO5+8Ii20 jFx351DmQ5AZHTGOumfO1fSwXkfl34kt+wsn/dhsFBaqJOGuMR7JPdaAf3F49HYkMQvY b49UtqpBIyLk+i5GhkGeY6TeBjUDMzPAeYuz8mqO6ncVnSs3gbdwVdGK9rBs5VFUQvTF UoBcWOAVpSFLVkjMMdXNYIBsE5qaup2OsOYkZSLC7igGGiM2dr+OYxN6gn+l07gazZvY XXTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=XRfGrdR3hLub3qcCuhXRL9f92OsUtMSBvuAtXtUhaAY=; b=DAwEgZSfrQocES6ATnIGCLuibb+GmaXts/bGPQ5lcMSnC+vUB2i5d+Txw2+HJR8wJV mz6DTLTTx2d6aKI65HAUSIcfVf2tZjnsExUvWs+pc2R0R6K6kb9O+A7l5ZFFXc7+lM6Y +VjKwo4LJ2btFRCefQRs2CYopZ1Mb51raZXqiZo9CpSLDFJwpuIuUMXMvwwKgPgzuh52 lEfato6LccBJjyzviFqOr5JuYar3DIkoGuhOoGpmoRBgc1m/hqXnGQpxMUceKeATcOj5 hU/EXVp71C/mSEeczPD64tM4+tepiHBCQSHm7h4FMWsvX0yKIhWrNQjnVBvW98yNUsOz UqhA== X-Gm-Message-State: AOAM531i1bJKEb/NHR1Z7yQyFcMv/v5IykGHklNxNfZhZtY0BBEFVtxt CJ3xhF48DMvwocZWJnI//dQVzKf9A9k= X-Google-Smtp-Source: ABdhPJwyerL9TOTYcy3Glond1XjXadDqIq2hv9P56CdQmuvvk02v2mLs/QsDB7BUgT62TsaMAUacGw== X-Received: by 2002:a05:6512:3f99:: with SMTP id x25mr3838184lfa.225.1628175137432; Thu, 05 Aug 2021 07:52:17 -0700 (PDT) Received: from ti0189a330-1161.bb.online.no (ti0189a330-1161.bb.online.no. [88.88.219.141]) by smtp.gmail.com with ESMTPSA id p14sm536632lfa.117.2021.08.05.07.52.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Aug 2021 07:52:17 -0700 (PDT) From: Frode Nordahl To: dev@openvswitch.org Date: Thu, 5 Aug 2021 16:50:11 +0200 Message-Id: <20210805145013.3033919-5-frode.nordahl@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805145013.3033919-1-frode.nordahl@gmail.com> References: <20210805145013.3033919-1-frode.nordahl@gmail.com> MIME-Version: 1.0 Cc: i.maximets@ovn.org Subject: [ovs-dev] [RFC PATCH ovn 4/6] lib: Add infrastructure for plugging providers 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" This module contains the infrastructure for registering and instantiating plugging classes which may be hosted inside or outside the core OVN repository. The data structures and functions for interacting with these plugging classes also live here. Signed-off-by: Frode Nordahl --- lib/automake.mk | 6 +- lib/plug-provider.h | 106 ++++++++++++++ lib/plug-test.c | 129 +++++++++++++++++ lib/plug.c | 342 ++++++++++++++++++++++++++++++++++++++++++++ lib/plug.h | 101 +++++++++++++ 5 files changed, 683 insertions(+), 1 deletion(-) create mode 100644 lib/plug-provider.h create mode 100644 lib/plug-test.c create mode 100644 lib/plug.c create mode 100644 lib/plug.h diff --git a/lib/automake.mk b/lib/automake.mk index d82908b92..272e48b4d 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -34,7 +34,11 @@ lib_libovn_la_SOURCES = \ lib/lb.h \ lib/stopwatch-names.h \ lib/ovsport.h \ - lib/ovsport.c + lib/ovsport.c \ + lib/plug-provider.h \ + lib/plug.h \ + lib/plug.c \ + lib/plug-test.c nodist_lib_libovn_la_SOURCES = \ lib/ovn-dirs.c \ lib/ovn-nb-idl.c \ diff --git a/lib/plug-provider.h b/lib/plug-provider.h new file mode 100644 index 000000000..f39637a5b --- /dev/null +++ b/lib/plug-provider.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2021 Canonical + * + * 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 PLUG_PROVIDER_H +#define PLUG_PROVIDER_H 1 + +/* Provider interface to pluggers. A plugger implementation performs lookup + * and/or initialization of ports, typically representor ports, using generic + * non-blocking hardware interfaces. This allows the ovn-controller to, upon + * the CMS's request, create ports and interfaces in the chassis's Open vSwitch + * instances (also known as vif plugging). + */ + +#include + +#include "plug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct plug { + const struct plug_class *plug_class; +}; + +struct plug_class { + /* Type of plugger in this class. */ + const char *type; + + /* Interface options this plugger will maintain. This set is used + * to know which items to remove when maintaining the database record. */ + struct sset *maintained_iface_options; + + /* Called when the plug provider is registered, typically at program + * startup. + * + * This function may be set to null if a plug class needs no + * initialization at registration time. */ + int (*init)(void); + + /* Called when the plug provider is unregistered, typically at program + * exit. + * + * This function may be set to null if a plug class needs no + * de-initialization at unregister time.*/ + int (*destroy)(void); + + /* Creates or returns a reference to an existing plug class instance. + * + * If successful, stores a pointer to the plug instance in '*plugp' */ + int (*open)(const struct plug_class *class, struct plug **plugp); + + /* Closes plug class instance and frees associated memory. */ + int (*close)(struct plug *plug); + + /* Performs periodic work needed by plugger, if any is necessary. Returns + * true if something changed, false otherwise. */ + bool (*run)(struct plug *plug); + + /* Pass plug_port_ctx_in to plug implementation to prepare for port + * creation/update. + * + * The plug implemantation can perform lookup or any per port + * initialization and should fill plug_port_ctx_out with data required for + * port/interface creation. The plug implementation should return true if + * it wants the caller to create/update a port/interface, false otherwise. + * + * Data in the plug_port_ctx_out struct is owned by the plugging library, + * and a call must be made to the plug_port_ctx_destroy callback to free + * up any allocations when done with port creation/update. + */ + bool (*plug_port_prepare)(const struct plug_port_ctx_in *, + struct plug_port_ctx_out *); + + /* Notify plugging library that port update is done. */ + void (*plug_port_finish)(const struct plug_port_ctx_in *, + struct plug_port_ctx_out *); + + /* Free any allocations made by the plug_port_prepare callback. */ + void (*plug_port_ctx_destroy)(const struct plug_port_ctx_in *, + struct plug_port_ctx_out *); +}; + +extern const struct plug_class plug_test_class; +#if 0 // replace with ifdef HAVE_XXX once hooked up with build system +extern const struct plug_class plug_representor_class; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* plug-provider.h */ diff --git a/lib/plug-test.c b/lib/plug-test.c new file mode 100644 index 000000000..bacbad685 --- /dev/null +++ b/lib/plug-test.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 Canonical + * + * 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 "plug-provider.h" +#include "plug.h" + +#include + +#include "ovsport.h" +#include "openvswitch/vlog.h" +#include "smap.h" +#include "sset.h" + +VLOG_DEFINE_THIS_MODULE(plug_test); + +struct plug_test { + struct plug plug; +}; + +static struct sset plug_test_maintained_iface_options; + +static int +plug_test_init(void) +{ + sset_init(&plug_test_maintained_iface_options); + sset_add(&plug_test_maintained_iface_options, "dpdk-devargs"); + + return 0; +} + +static int +plug_test_destroy(void) +{ + sset_destroy(&plug_test_maintained_iface_options); + + return 0; +} + +static int +plug_test_open(const struct plug_class *class, struct plug **plugp) +{ + struct plug_test *plug; + + plug = xmalloc(sizeof *plug); + plug->plug.plug_class = class; + *plugp = &plug->plug; + + VLOG_INFO("plug_test_open(%p)", plug); + return 0; +} + +static int +plug_test_close(struct plug *plug) +{ + VLOG_INFO("plug_test_close(%p)", plug); + free(plug); + + return 0; +} + +static bool +plug_test_run(struct plug *plug) +{ + VLOG_INFO("plug_test_run(%p)", plug); + + return false; +} + +static bool +plug_test_port_prepare(const struct plug_port_ctx_in *ctx_in, + struct plug_port_ctx_out *ctx_out) +{ + VLOG_INFO("plug_test_port_prepare: %s", ctx_in->lport_name); + if (ctx_in->op_type == PLUG_OP_CREATE) + { + ctx_out->name = strdup("test"); + ctx_out->type = strdup("internal"); + ctx_out->iface_options = xmalloc(sizeof *ctx_out->iface_options); + smap_init(ctx_out->iface_options); + } + + return true; +} + +static void +plug_test_port_finish(const struct plug_port_ctx_in *ctx_in, + struct plug_port_ctx_out *ctx_out OVS_UNUSED) +{ + VLOG_INFO("plug_test_port_finish: %s", ctx_in->lport_name); +} + +static void +plug_test_port_ctx_destroy(const struct plug_port_ctx_in *ctx_in, + struct plug_port_ctx_out *ctx_out) +{ + VLOG_INFO("plug_test_port_ctx_destroy: %s", ctx_in->lport_name); + ovs_assert(ctx_in->op_type == PLUG_OP_CREATE); + free(ctx_out->name); + free(ctx_out->type); + smap_destroy(ctx_out->iface_options); + free(ctx_out->iface_options); +} + +const struct plug_class plug_test_class = { + .type = "test", + .maintained_iface_options = &plug_test_maintained_iface_options, + .init = plug_test_init, + .destroy = plug_test_destroy, + .open = plug_test_open, + .close = plug_test_close, + .run = plug_test_run, + .plug_port_prepare = plug_test_port_prepare, + .plug_port_finish = plug_test_port_finish, + .plug_port_ctx_destroy = plug_test_port_ctx_destroy, +}; diff --git a/lib/plug.c b/lib/plug.c new file mode 100644 index 000000000..4a8650385 --- /dev/null +++ b/lib/plug.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2021 Canonical + * + * 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 "plug-provider.h" +#include "plug.h" + +#include +#include +#include + +#include "ovsport.h" +#include "openvswitch/vlog.h" +#include "openvswitch/shash.h" +#include "smap.h" +#include "sset.h" + +VLOG_DEFINE_THIS_MODULE(plug); + +static const struct plug_class *base_plug_classes[] = { + &plug_test_class, +#if 0 // replace with ifdef HAVE_XXX once hooked up with build system + &plug_representor_class, +#endif +}; + +struct registered_plug_class { + const struct plug_class *plug_class; + int refcount; +}; +static struct shash plug_classes = SHASH_INITIALIZER(&plug_classes); +static struct shash plug_instances = SHASH_INITIALIZER(&plug_instances); + +/* Protects 'plug_classes', including the refcount. */ +static struct ovs_mutex plug_classes_mutex = OVS_MUTEX_INITIALIZER; +/* Protects 'plug_instances' */ +static struct ovs_mutex plug_instances_mutex = OVS_MUTEX_INITIALIZER; + +/* Initialize the the plug infrastructure by registering known plug classes */ +static void +plug_initialize(void) +{ + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; + + if (ovsthread_once_start(&once)) { + for (int i = 0; i < ARRAY_SIZE(base_plug_classes); i++) { + plug_register_provider(base_plug_classes[i]); + } + } + + ovsthread_once_done(&once); +} + +static int +plug_register_provider__(const struct plug_class *new_class) +{ + struct registered_plug_class *rc; + int error; + + if (shash_find(&plug_classes, new_class->type)) { + VLOG_WARN("attempted to register duplicate plug provider: %s", + new_class->type); + return EEXIST; + } + + error = new_class->init ? new_class->init() : 0; + if (error) { + VLOG_WARN("failed to initialize %s plug class: %s", + new_class->type, ovs_strerror(error)); + return error; + } + + rc = xmalloc(sizeof *rc); + rc->plug_class = new_class; + rc->refcount = 0; + + shash_add(&plug_classes, new_class->type, rc); + + return 0; +} + +/* Register the new plug provider referred to in 'new_class' and perform any + * class level initialization as specified in its plug_class. */ +int +plug_register_provider(const struct plug_class *new_class) +{ + int error; + + ovs_mutex_lock(&plug_classes_mutex); + error = plug_register_provider__(new_class); + ovs_mutex_unlock(&plug_classes_mutex); + + return error; +} + +static int +plug_unregister_provider__(const char *type) +{ + int error; + struct shash_node *node; + struct registered_plug_class *rc; + + node = shash_find(&plug_classes, type); + if (!node) { + return EINVAL; + } + + rc = node->data; + if (rc->refcount) { + VLOG_WARN("attempted to unregister in use plug provider: %s", type); + return EBUSY; + } + + error = rc->plug_class->destroy ? rc->plug_class->destroy() : 0; + if (error) { + VLOG_WARN("failed to destroy %s plug class: %s", + rc->plug_class->type, ovs_strerror(error)); + return error; + } + + shash_delete(&plug_classes, node); + free(rc); + + return 0; +} + +/* Unregister the plug provider identified by 'type' and perform any class + * level de-initialization as specified in its plug_class. */ +int +plug_unregister_provider(const char *type) +{ + int error; + + plug_initialize(); + + ovs_mutex_lock(&plug_classes_mutex); + error = plug_unregister_provider__(type); + ovs_mutex_unlock(&plug_classes_mutex); + + return error; +} + +static void +plug_class_unref(struct registered_plug_class *rc) +{ + ovs_mutex_lock(&plug_classes_mutex); + ovs_assert(rc->refcount); + rc->refcount--; + ovs_mutex_unlock(&plug_classes_mutex); +} + +static struct registered_plug_class * +plug_class_lookup(const char *type) +{ + struct registered_plug_class *rc; + + ovs_mutex_lock(&plug_classes_mutex); + rc = shash_find_data(&plug_classes, type); + if (rc) { + rc->refcount++; + } + ovs_mutex_unlock(&plug_classes_mutex); + + return rc; +} + +static int +plug_open__(const char *type, struct plug **plugp) +{ + struct plug *plug = NULL; + int error; + struct registered_plug_class *rc; + + plug_initialize(); + rc = plug_class_lookup(type); + if (!rc) { + VLOG_WARN("unable to open plug provider of unknown type: %s", type); + error = EINVAL; + goto out; + } + + error = rc->plug_class->open(rc->plug_class, &plug); + if (error) { + plug_class_unref(rc); + } + +out: + *plugp = error ? NULL: plug; + return error; +} + +/* Create, or retrieve the already created instance of plug class from a + * previous call to plug_open, identified by 'type' and store a reference to it + * in '*plugp'. + * + * The plug implementation will perform any initialization and allocations it + * needs, and the plug infrastructure will store a reference to it. Subsequent + * calls to this function with the same 'type' parameter will return the same + * object, until the instance is removed with a call to plug_close. */ +int +plug_open(const char *type, struct plug **plugp) +{ + struct plug *instance = shash_find_data(&plug_instances, type); + int error; + + if (instance) { + *plugp = instance; + return 0; + } + + error = plug_open__(type, plugp); + if (error) { + return error; + } + + ovs_mutex_lock(&plug_instances_mutex); + shash_add(&plug_instances, type, *plugp); + ovs_mutex_unlock(&plug_instances_mutex); + + return 0; +} + +/* Close the plug class instance previously created by a call to 'plug_open'. + * + * The plug implementation will perform any destruction of its data and the + * plug infrastructure will remove its references to it. */ +void +plug_close(struct plug *plug) +{ + if (plug) { + ovs_mutex_lock(&plug_instances_mutex); + shash_find_and_delete(&plug_instances, plug->plug_class->type); + ovs_mutex_unlock(&plug_instances_mutex); + + struct registered_plug_class *rc; + rc = shash_find_data(&plug_classes, plug->plug_class->type); + rc->plug_class->close(plug); + plug_class_unref(rc); + } +} + +/* Close any previously instantiated plug classes and unregister the plug + * providers. */ +void +plug_destroy_all(void) +{ + struct shash_node *node, *next; + SHASH_FOR_EACH_SAFE(node, next, &plug_instances) { + struct plug *plug = node->data; + plug_close(plug); + } + SHASH_FOR_EACH_SAFE(node, next, &plug_classes) { + struct registered_plug_class *rc = node->data; + plug_unregister_provider(rc->plug_class->type); + } +} + +/* Iterate over previously instantiated plug classes and call their 'run' + * function if defined. + * + * If any of the instances report they have changed something this function + * will return 'true', otherwise it will return 'false'. */ +bool +plug_run_instances(void) +{ + struct shash_node *node; + bool something_changed = false; + + ovs_mutex_lock(&plug_instances_mutex); + SHASH_FOR_EACH(node, &plug_instances) { + struct plug *instance = node->data; + if (instance->plug_class->run(instance)) { + something_changed = true; + } + } + ovs_mutex_unlock(&plug_instances_mutex); + + return something_changed; +} + +/* Get the class level 'maintained_iface_options' set. */ +struct sset * +plug_class_get_maintained_iface_options(struct plug *plug) +{ + return plug->plug_class->maintained_iface_options; +} + +/* Prepare the logical port as identified by 'ctx_in' for port creation, update + * or removal as specified by 'ctx_in->op_type'. + * + * When 'ctx_in->op_type' is PLUG_OP_CREATE the plug implementation must fill + * 'ctx_out' with data to apply to the interface record maintained by OVN on + * its behalf. + * + * When 'ctx_in_op_type' is PLUG_OP_REMOVE 'ctx_out' should be set to NULL and + * the plug implementation must not attempt to use 'ctx_out'. + * + * The data in 'ctx_out' is owned by the plug implementation, and a call must + * be made to plug_port_ctx_destroy when done with it. */ +bool +plug_port_prepare(const struct plug *plug, + const struct plug_port_ctx_in *ctx_in, + struct plug_port_ctx_out *ctx_out) +{ + if (ctx_out) { + memset(ctx_out, 0, sizeof(*ctx_out)); + } + return plug->plug_class->plug_port_prepare(ctx_in, ctx_out); +} + +/* Notify the plug implementation that a port creation, update or removal has + * been completed */ +void +plug_port_finish(const struct plug *plug, + const struct plug_port_ctx_in *ctx_in, + struct plug_port_ctx_out *ctx_out) +{ + plug->plug_class->plug_port_finish(ctx_in, ctx_out); +} + +/* Free any data allocated to 'ctx_out' in a prevous call to + * plug_port_prepare. */ +void +plug_port_ctx_destroy(const struct plug *plug, + const struct plug_port_ctx_in *ctx_in, + struct plug_port_ctx_out *ctx_out) +{ + plug->plug_class->plug_port_ctx_destroy(ctx_in, ctx_out); +} diff --git a/lib/plug.h b/lib/plug.h new file mode 100644 index 000000000..7a92ee1c8 --- /dev/null +++ b/lib/plug.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2021 Canonical + * + * 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 PLUG_H +#define PLUG_H 1 + +/* + * Plug, the plugging interface. This module contains the infrastructure for + * registering and instantiating plugging classes which may be hosted inside + * or outside the core OVN repository. The data structures and functions for + * interacting with these plugging classes also live here. + */ + +#include "smap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct plug; +struct plug_class; +struct ovsdb_idl_txn; +struct ovsrec_bridge; + +enum plug_op_type { + PLUG_OP_CREATE = 1, /* Port is created or updated */ + PLUG_OP_REMOVE, /* Port is removed from this chassis */ +}; + +struct plug_port_ctx_in { + /* Operation being performed */ + enum plug_op_type op_type; + + /* Whether the chassis uses DPDK */ + bool use_dpdk; + + /* Name of logical port, can be useful for plugging library to track any + * per port resource initialization. */ + const char *lport_name; + + /* Logical port options, while OVN will forward the contents verbatim from + * the Southbound database, the convention is for the plugging library to + * only make decisions based on the plug-* options. */ + const struct smap *lport_options; + + /* When OVN knows about an existing interface record associated with this + * lport, these will be filled in with information about it. */ + const char *iface_name; + const char *iface_type; + const struct smap *iface_options; +}; + +struct plug_port_ctx_out { + /* The name to use for port and interface record. */ + char *name; + + /* Type of interface to create. */ + char *type; + + /* Options to set on the interface record. */ + struct smap *iface_options; +}; + + +int plug_register_provider(const struct plug_class *); +int plug_unregister_provider(const char *type); +void plug_destroy_all(void); +int plug_open(const char *type, struct plug **); +void plug_close(struct plug *); +bool plug_run_instances(void); + +struct sset * plug_class_get_maintained_iface_options(struct plug *); + +bool plug_port_prepare(const struct plug *, + const struct plug_port_ctx_in *, + struct plug_port_ctx_out *); +void plug_port_finish(const struct plug *, + const struct plug_port_ctx_in *, + struct plug_port_ctx_out *); +void plug_port_ctx_destroy(const struct plug *, + const struct plug_port_ctx_in *, + struct plug_port_ctx_out *); + +#ifdef __cplusplus +} +#endif + +#endif /* plug.h */ From patchwork Thu Aug 5 14:50:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frode Nordahl X-Patchwork-Id: 1513946 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=ILujiKVe; dkim-atps=neutral Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GgWmd6bX5z9s5R for ; Fri, 6 Aug 2021 00:52:33 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id D813F40595; Thu, 5 Aug 2021 14:52:30 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EwuYAPyqwyBk; Thu, 5 Aug 2021 14:52:29 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 61F1140582; Thu, 5 Aug 2021 14:52:28 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BE45EC0030; Thu, 5 Aug 2021 14:52:24 +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 3167EC001C for ; Thu, 5 Aug 2021 14:52:22 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 72EEE4045C for ; Thu, 5 Aug 2021 14:52:21 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp2.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HIZNwy5itB3d for ; Thu, 5 Aug 2021 14:52:20 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by smtp2.osuosl.org (Postfix) with ESMTPS id 67EE740432 for ; Thu, 5 Aug 2021 14:52:20 +0000 (UTC) Received: by mail-lj1-x22d.google.com with SMTP id h11so7422436ljo.12 for ; Thu, 05 Aug 2021 07:52:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PqfcxKIl6qsKojBHzx019EyNrhs6rHFY9wYl/NK3hYU=; b=ILujiKVemAWC5DwRbSn9PmKebV2cYKj1RnCQnyfMCHr5Yi/6ntkmuucK/v25/SReRY 4C6MuB3B+7WFklhPFw1UeIyLW7yIhfsvs8rDay3FeoBLhmrcQHb30mt90ARuKLaULy91 5jgPe7fcmro9KBZPblkF6BAqDSmHz4W3PQZZ8vLlumPLquXl2/GOIyvd413C+J/8+eZr pApZ/+HfoQwbzju8vTfiRmz+rMbG/+a70YtU4z/YUXxMjDjHLBphX49ZXsole/iCfEhC HVpSk47eazlq7+PszH6phA1/WEfwc+CIVNbud613TedObYIB5yD4WhH6sKaNCxGNzyH2 LRcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PqfcxKIl6qsKojBHzx019EyNrhs6rHFY9wYl/NK3hYU=; b=YlkFdrlCaeK2gVbhhcs0EEryt2YPHpwngcN696/apKEj2nuWTXsByCimLHyZqw21Qo +N3uPq4RHcpIkAN1Dli+iUf1AOropNlSPAjtClFh2y0HygcqAwFb71euw+za1HrT2uio qo/LYi0+Va5jLxNLhjxMU1jPEW4HZU/HcHBNxU3FGc2m2peOZvLuwKDoMpV3oLh2Nrrt EyKnkDWqzbQ6CP0gF1ZKJpLmYOZb/43GUAgovYp2ZtPqiMsJsFVfnTEUHQ7XrUBDiRXK 6pzlzJd7UNKEyBUwF3joNaHWio/RosdzqJ2wEgDkmLwMJybzF/qG+2W+MFzuTzWjk2h6 bddA== X-Gm-Message-State: AOAM533Ejsax+5WnKPPghV8AOinPwN1gVSiTIHBu2XCLTx3svMLVriuA 0a0nCeDVjQkkP+tYncevSC1DaFoy26I= X-Google-Smtp-Source: ABdhPJzpRdm31VJoMBJG17jaQjNSmAKDy1Ocir4wfHeP4/WNFYUk4OvWD+MS6zxEGzkXsMB0nLWDgg== X-Received: by 2002:a2e:9743:: with SMTP id f3mr3486803ljj.380.1628175138274; Thu, 05 Aug 2021 07:52:18 -0700 (PDT) Received: from ti0189a330-1161.bb.online.no (ti0189a330-1161.bb.online.no. [88.88.219.141]) by smtp.gmail.com with ESMTPSA id p14sm536632lfa.117.2021.08.05.07.52.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Aug 2021 07:52:17 -0700 (PDT) From: Frode Nordahl To: dev@openvswitch.org Date: Thu, 5 Aug 2021 16:50:12 +0200 Message-Id: <20210805145013.3033919-6-frode.nordahl@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805145013.3033919-1-frode.nordahl@gmail.com> References: <20210805145013.3033919-1-frode.nordahl@gmail.com> MIME-Version: 1.0 Cc: i.maximets@ovn.org Subject: [ovs-dev] [RFC PATCH ovn 5/6] controller: Add port by interfaces index 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" To be able to effectively remove ports previously plugged by us we need to look up ports by interface records. Signed-off-by: Frode Nordahl --- controller/ovn-controller.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 75f16b15e..cf051f0be 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -1238,6 +1238,11 @@ init_binding_ctx(struct engine_node *node, engine_get_input("SB_port_binding", node), "datapath"); + struct ovsdb_idl_index *ovsrec_port_by_interfaces = + engine_ovsdb_node_get_index( + engine_get_input("OVS_port", node), + "interfaces"); + struct controller_engine_ctx *ctrl_ctx = engine_get_context()->client_ctx; b_ctx_in->ovnsb_idl_txn = engine_get_context()->ovnsb_idl_txn; @@ -1245,6 +1250,7 @@ init_binding_ctx(struct engine_node *node, b_ctx_in->sbrec_datapath_binding_by_key = sbrec_datapath_binding_by_key; b_ctx_in->sbrec_port_binding_by_datapath = sbrec_port_binding_by_datapath; b_ctx_in->sbrec_port_binding_by_name = sbrec_port_binding_by_name; + b_ctx_in->ovsrec_port_by_interfaces = ovsrec_port_by_interfaces; b_ctx_in->port_table = port_table; b_ctx_in->iface_table = iface_table; b_ctx_in->qos_table = qos_table; @@ -3084,6 +3090,11 @@ main(int argc, char *argv[]) struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER( ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true)); ctrl_register_ovs_idl(ovs_idl_loop.idl); + + struct ovsdb_idl_index *ovsrec_port_by_interfaces + = ovsdb_idl_index_create1(ovs_idl_loop.idl, + &ovsrec_port_col_interfaces); + ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl); /* Configure OVN SB database. */ @@ -3347,6 +3358,8 @@ main(int argc, char *argv[]) sbrec_port_binding_by_datapath); engine_ovsdb_node_add_index(&en_sb_datapath_binding, "key", sbrec_datapath_binding_by_key); + engine_ovsdb_node_add_index(&en_ovs_port, "interfaces", + ovsrec_port_by_interfaces); struct ed_type_lflow_output *lflow_output_data = engine_get_internal_data(&en_lflow_output); From patchwork Thu Aug 5 14:50:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frode Nordahl X-Patchwork-Id: 1513947 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=jV193d42; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GgWmg2sgcz9s5R for ; Fri, 6 Aug 2021 00:52:35 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 3FBD883AEE; Thu, 5 Aug 2021 14:52:33 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id BisRKRal2Trf; Thu, 5 Aug 2021 14:52:31 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id ED63783B0E; Thu, 5 Aug 2021 14:52:29 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 77800C0033; Thu, 5 Aug 2021 14:52:25 +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 EF91CC001F for ; Thu, 5 Aug 2021 14:52:22 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id A3D6E40510 for ; Thu, 5 Aug 2021 14:52:22 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp4.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id p_cvocCtLOpj for ; Thu, 5 Aug 2021 14:52:21 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by smtp4.osuosl.org (Postfix) with ESMTPS id 1CFD9404EC for ; Thu, 5 Aug 2021 14:52:20 +0000 (UTC) Received: by mail-lf1-x132.google.com with SMTP id bq29so11678525lfb.5 for ; Thu, 05 Aug 2021 07:52:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=CupI8Ib+JdlN7IAIY7XCLffNDzkvCN3tGT6tWtTnc68=; b=jV193d421cJO69LrssLa2zQ7DQtb6MIrGsJGip4q+9Stu1WBuEvYYBANFwxpJuPGfQ JMrUdvMoPPTsiosf9kxTWLyhu+tcRn9ELP8awW4IgGI/+cxSHgdeq2XCFJdVal/Ex3Kn 68aUV+pCk/Eh+iaBFqyMIPQHqJhXEh+6o4ULvIWHSv+TC4E64UAz1nz8uaIEhBBfdAdo urjV+wfSHakWs+hwicyBHUS7I6qv6tLUgZ69YnDsTCDhw2HxGH7tBTMepLp+DzYIaycu mfGY5hL3vPEhPpMO4yiqDKI9gp2ih7/e2LNj7mxfVp8cka6RIqJvc2gK47jxVVXklYGg vEXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=CupI8Ib+JdlN7IAIY7XCLffNDzkvCN3tGT6tWtTnc68=; b=jPh0Ze790obDC37rp09M1BZbYqhVrEiP05+oUgReT/iHnlx7MS6yXmNul7yHA38SNL iognxnyyjx9odclkQ/m4gyVfiST7neb7+5a8FS9iuRAby3C2pWmSZPKYfF7NDabG3OF+ ffciD+fOo46mxjYRUKDOjo9Mobq64YqdF1nB5dkesNFofWQOe61qpBH/Cw40tjRaJ2PR OFGscSkQG7LGJJeU8p6sQgHrhEe3Aw8bZLCG0YmhZEG2ufLoQ46hKmC5+1XHloutie4Z vYHi/qgxOnz4ucHrcKgrBrO9QFyT1yw9dfzCuZ9UJKuJilhuiYnXIqz8p6EfT6mgsCFG +jVQ== X-Gm-Message-State: AOAM530CTPv+IDRMMpNz4RZbUZAc4GeziLyqR/AYgf56d/LkPgHgiPM9 EI8b5NChhLYNLgxe2fiAZ7HLiO1OTO0= X-Google-Smtp-Source: ABdhPJwMUkxtKmAkisCadc/YXE0QlW75ripCkSIaAlSdvBj1uox7LnzePCSVLBfvHy1VWRQ9NRbIMg== X-Received: by 2002:ac2:58e1:: with SMTP id v1mr4051582lfo.52.1628175138906; Thu, 05 Aug 2021 07:52:18 -0700 (PDT) Received: from ti0189a330-1161.bb.online.no (ti0189a330-1161.bb.online.no. [88.88.219.141]) by smtp.gmail.com with ESMTPSA id p14sm536632lfa.117.2021.08.05.07.52.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Aug 2021 07:52:18 -0700 (PDT) From: Frode Nordahl To: dev@openvswitch.org Date: Thu, 5 Aug 2021 16:50:13 +0200 Message-Id: <20210805145013.3033919-7-frode.nordahl@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210805145013.3033919-1-frode.nordahl@gmail.com> References: <20210805145013.3033919-1-frode.nordahl@gmail.com> MIME-Version: 1.0 Cc: i.maximets@ovn.org Subject: [ovs-dev] [RFC PATCH ovn 6/6] binding: Consider plugging of ports on CMS request 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" When OVN is linked with an appropriate plugging implementation, CMS can request OVN to plug individual lports into the local Open vSwitch instance. The port and instance record will be maintained during the lifetime of the lport and it will be removed on release of lport. TODO: The functions considering plugging or unplugging of interfaces are currently oblivious to the fact that the binding module has data structures to keep track of these. The functions should be good citizens and learn to update those appropriately as they take action. Signed-off-by: Frode Nordahl --- controller/binding.c | 175 ++++++++++++++++++++++++++++++++++++ controller/binding.h | 1 + controller/ovn-controller.c | 5 ++ 3 files changed, 181 insertions(+) diff --git a/controller/binding.c b/controller/binding.c index 2a10d7586..db1132095 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -35,7 +35,9 @@ #include "local_data.h" #include "lport.h" #include "ovn-controller.h" +#include "ovsport.h" #include "patch.h" +#include "plug.h" VLOG_DEFINE_THIS_MODULE(binding); @@ -45,6 +47,8 @@ VLOG_DEFINE_THIS_MODULE(binding); */ #define OVN_INSTALLED_EXT_ID "ovn-installed" +#define OVN_PLUGGED_EXT_ID "ovn-plugged" + #define OVN_QOS_TYPE "linux-htb" struct qos_queue { @@ -71,10 +75,13 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface); ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_type); ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_external_ids); ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd); ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd_status); ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_status); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_options); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_mtu_request); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_qos); ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_type); @@ -1046,6 +1053,18 @@ is_binding_lport_this_chassis(struct binding_lport *b_lport, b_lport->pb->chassis == chassis); } +static bool +chassis_uses_dpdk(const struct ovsrec_open_vswitch_table *ovs_table, + const struct ovsrec_bridge *br_int) +{ + const struct ovsrec_open_vswitch *cfg; + + cfg = ovsrec_open_vswitch_table_first(ovs_table); + + return (cfg && cfg->dpdk_initialized && + !strcmp(br_int->datapath_type, "netdev")); +} + static bool can_bind_on_this_chassis(const struct sbrec_chassis *chassis_rec, const char *requested_chassis) @@ -1055,6 +1074,14 @@ can_bind_on_this_chassis(const struct sbrec_chassis *chassis_rec, || !strcmp(requested_chassis, chassis_rec->hostname); } +static bool +can_plug_on_this_chassis(const struct sbrec_chassis *chassis_rec, + const struct sbrec_port_binding *pb) +{ + return pb->plugged_by && uuid_equals(&chassis_rec->header_.uuid, + &pb->plugged_by->header_.uuid); +} + /* Returns 'true' if the 'lbinding' has binding lports of type LP_CONTAINER, * 'false' otherwise. */ static bool @@ -1088,6 +1115,48 @@ release_binding_lport(const struct sbrec_chassis *chassis_rec, return true; } +static void +consider_unplug_lport(const struct sbrec_port_binding *pb, + struct binding_ctx_in *b_ctx_in, + struct binding_lport *b_lport) +{ + const char *plug_type = smap_get(&b_lport->lbinding->iface->external_ids, + OVN_PLUGGED_EXT_ID); + if (plug_type) + { + const struct ovsrec_port *port = ovsport_lookup_by_interface( + b_ctx_in->ovsrec_port_by_interfaces, + (struct ovsrec_interface *) b_lport->lbinding->iface); + if (port) { + struct plug *plug; + if (plug_open(plug_type, &plug)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, + "Unable to open plug provider for " + "plug-type: '%s' lport %s", + plug_type, pb->logical_port); + return; + } + const struct plug_port_ctx_in plug_ctx_in = { + .op_type = PLUG_OP_REMOVE, + .use_dpdk = chassis_uses_dpdk(b_ctx_in->ovs_table, + b_ctx_in->br_int), + .lport_name = (const char *)pb->logical_port, + .lport_options = (const struct smap *)&pb->options, + .iface_name = b_lport->lbinding->iface->name, + .iface_type = b_lport->lbinding->iface->type, + .iface_options = &b_lport->lbinding->iface->options, + }; + plug_port_prepare(plug, &plug_ctx_in, NULL); + VLOG_INFO("Unplugging port %s from %s for lport %s on this " + "chassis.", + port->name, b_ctx_in->br_int->name, pb->logical_port); + ovs_remove_port(b_ctx_in->br_int, port); + plug_port_finish(plug, &plug_ctx_in, NULL); + } + } +} + static bool consider_vif_lport_(const struct sbrec_port_binding *pb, bool can_bind, const char *vif_chassis, @@ -1138,6 +1207,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, if (pb->chassis == b_ctx_in->chassis_rec) { /* Release the lport if there is no lbinding. */ if (!lbinding_set || !can_bind) { + consider_unplug_lport(pb, b_ctx_in, b_lport); return release_lport(pb, !b_ctx_in->ovnsb_idl_txn, b_ctx_out->tracked_dp_bindings, b_ctx_out->if_mgr); @@ -1147,6 +1217,106 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, return true; } +static int64_t +get_plug_mtu_request(const struct smap *lport_options) +{ + return smap_get_int(lport_options, "plug-mtu-request", 0); +} + +static bool +consider_plug_lport(const struct sbrec_port_binding *pb, + struct binding_ctx_in *b_ctx_in, + struct local_binding *lbinding) +{ + bool ret = true; + + if (can_plug_on_this_chassis(b_ctx_in->chassis_rec, pb)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + const char *plug_type = smap_get(&pb->options, "plug-type"); + if (!plug_type) { + /* This should never happen, but better safe than sorry */ + VLOG_WARN_RL(&rl, + "Possible database inconsistency detected: " + "Port_Binding->plugged_by points at this chassis, " + "but Port_Binding->options:plug-type not set. " + "lport %s", + pb->logical_port); + return false; + } + + struct plug *plug; + if (plug_open(plug_type, &plug)) { + VLOG_WARN_RL(&rl, + "Unable to open plug provider for plug-type: '%s' " + "lport %s", + plug_type, pb->logical_port); + return false; + } + struct plug_port_ctx_in plug_ctx_in = { + .op_type = PLUG_OP_CREATE, + .use_dpdk = chassis_uses_dpdk(b_ctx_in->ovs_table, + b_ctx_in->br_int), + .lport_name = (const char *)pb->logical_port, + .lport_options = (const struct smap *)&pb->options, + }; + struct plug_port_ctx_out plug_ctx_out; + const struct smap iface_external_ids = SMAP_CONST2( + &iface_external_ids, + OVN_PLUGGED_EXT_ID, plug_type, + "iface-id", pb->logical_port); + if (!plug_port_prepare(plug, &plug_ctx_in, &plug_ctx_out)) { + VLOG_INFO_RL(&rl, + "Not plugging lport %s on direction from plugging " + "library.", + pb->logical_port); + ret = false; + goto out; + } + + if (lbinding) { + if (smap_get(&lbinding->iface->external_ids, + OVN_PLUGGED_EXT_ID)) + { + if (strcmp(lbinding->iface->name, plug_ctx_out.name)) { + VLOG_WARN("Attempt of incompatible change to existing " + "port detected, please recreate port: %s", + pb->logical_port); + ret = false; + goto out; + } + VLOG_DBG("updating iface for: %s", pb->logical_port); + ovs_update_iface(lbinding->iface, plug_ctx_out.type, + &iface_external_ids, + NULL, + plug_ctx_out.iface_options, + plug_class_get_maintained_iface_options(plug), + get_plug_mtu_request(&pb->options)); + } else { + VLOG_WARN_RL(&rl, + "CMS requested plugging but port not maintained " + "by OVN already exsists in local vSwitch: %s", + pb->logical_port); + } + } else { + VLOG_INFO("Plugging port %s into %s for lport %s on this " + "chassis.", + plug_ctx_out.name, b_ctx_in->br_int->name, + pb->logical_port); + VLOG_DBG("creating port for: %s", pb->logical_port); + ovs_create_port(b_ctx_in->ovs_idl_txn, b_ctx_in->br_int, + plug_ctx_out.name, plug_ctx_out.type, + NULL, &iface_external_ids, + plug_ctx_out.iface_options, + get_plug_mtu_request(&pb->options)); + } +out: + plug_port_finish(plug, &plug_ctx_in, &plug_ctx_out); + plug_port_ctx_destroy(plug, &plug_ctx_in, &plug_ctx_out); + } + + return ret; +} + static bool consider_vif_lport(const struct sbrec_port_binding *pb, struct binding_ctx_in *b_ctx_in, @@ -1170,6 +1340,7 @@ consider_vif_lport(const struct sbrec_port_binding *pb, b_lport = local_binding_add_lport(binding_lports, lbinding, pb, LP_VIF); } + consider_plug_lport(pb, b_ctx_in, lbinding); return consider_vif_lport_(pb, can_bind, vif_chassis, b_ctx_in, b_ctx_out, b_lport, qos_map); } @@ -1563,6 +1734,10 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct binding_ctx_out *b_ctx_out) const struct sbrec_port_binding *pb; }; + /* For any open plug provider instances, perform periodic non-blocking + * maintenance */ + plug_run_instances(); + /* Run through each binding record to see if it is resident on this * chassis and update the binding accordingly. This includes both * directly connected logical ports and children of those ports diff --git a/controller/binding.h b/controller/binding.h index f1abc4b9c..8f4521806 100644 --- a/controller/binding.h +++ b/controller/binding.h @@ -46,6 +46,7 @@ struct binding_ctx_in { struct ovsdb_idl_index *sbrec_datapath_binding_by_key; struct ovsdb_idl_index *sbrec_port_binding_by_datapath; struct ovsdb_idl_index *sbrec_port_binding_by_name; + struct ovsdb_idl_index *ovsrec_port_by_interfaces; const struct ovsrec_port_table *port_table; const struct ovsrec_qos_table *qos_table; const struct sbrec_port_binding_table *port_binding_table; diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index cf051f0be..98d9bf61d 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -55,6 +55,7 @@ #include "lib/ovn-sb-idl.h" #include "lib/ovn-util.h" #include "patch.h" +#include "plug.h" #include "physical.h" #include "pinctrl.h" #include "openvswitch/poll-loop.h" @@ -231,6 +232,9 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, sbrec_port_binding_add_clause_chassis(&pb, OVSDB_F_EQ, &chassis->header_.uuid); + sbrec_port_binding_add_clause_plugged_by(&pb, OVSDB_F_EQ, + &chassis->header_.uuid); + /* Ensure that we find out about l2gateway and l3gateway ports that * should be present on this chassis. Otherwise, we might never find * out about those ports, if their datapaths don't otherwise have a VIF @@ -3881,6 +3885,7 @@ loop_done: pinctrl_destroy(); patch_destroy(); if_status_mgr_destroy(if_mgr); + plug_destroy_all(); ovsdb_idl_loop_destroy(&ovs_idl_loop); ovsdb_idl_loop_destroy(&ovnsb_idl_loop);