From patchwork Thu May 24 22:10:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920127 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="S5XKKXs8"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNqy43K5z9s0q for ; Fri, 25 May 2018 08:10:54 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4FF6EC46; Thu, 24 May 2018 22:10:20 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 582D4CCB for ; Thu, 24 May 2018 22:10:19 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f68.google.com (mail-pg0-f68.google.com [74.125.83.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 61F6B6C1 for ; Thu, 24 May 2018 22:10:18 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id p8-v6so1372135pgq.10 for ; Thu, 24 May 2018 15:10: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; bh=xiLFgJ+B4ntw7t3cxmrOqE8Jj9uSJA3q+nDs7JdnAW8=; b=S5XKKXs8qYKW9Bo2Gqbouc8rDIMqRz749wjkqgobLlAbDT/FMAMaN8ugRjj/YNPfr0 AKR4p4BLuFuZPxDmu/13b6oV0RV8AS5FrjZfRQ6IW6Sh0nE6PJ/OskpfoO0cR+6e4ksr g3bygn4vZ9h40653kZwyJ6+HsKy2KJY5GAjWDFvcnd0m6hmQLP6aSGDRJv5sa1w8FF9F cr1WpwU662LW0xZ8H5K75qwtSM+FfxPwH943ZFTArnfWoNqTU+XvHg0+0A1JK4TpGB8u lnPvlfkVs3Sc/S2lG7rvZ+tjgnkAAVZnsoNSbk92I76/gXJrcyZ3DWvEpzuijOvHNzM6 8WNA== 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; bh=xiLFgJ+B4ntw7t3cxmrOqE8Jj9uSJA3q+nDs7JdnAW8=; b=BwCmho21tvvbqYRoSrS7SG6nrVOnmmqjd9YZC5qGV4E+4p24ReMzvEwNjE4EvdnX4s C/Odsed6Pk7kS6QDlovp70KqnV0s/9x26gnUqNlPlD7xTsMNRptRkHj/3JIwPm1cXY44 I3i/V33wvWEr5yU/FYdHUUoEWV/RYFdmykchPv5+UJEjNjPNdEOxIvgfxGWmBxUPP+8b TKp/sJ4tb50e2Zm83S8YRDwk6vu+DfewJBD6KToWfgRcUmL6IUDoO8MxBn8g2N9EHQIg aiiYJvExwFGiYAYeshPyaEd2flI8irj77807hAvhY2GpjEa4bincCCKAINj/6EFl9Trw C3Cg== X-Gm-Message-State: ALKqPwd5xu8tdzPuu2MBRwpkID7GOKEI9KVO80LgMOnh1Ks6JKzbJX+e isFea7buLQNF3cxcaO4GviTozQ== X-Google-Smtp-Source: AB8JxZqLLlsvRrA6Mo4t/86K9bN8Y0uf2/zVvqOUbL0od487bAHF+jbPdZH2ofZDH/yBRDFhCcBVmA== X-Received: by 2002:a63:af0e:: with SMTP id w14-v6mr7341578pge.221.1527199817475; Thu, 24 May 2018 15:10:17 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:16 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:42 -0700 Message-Id: <1527199851-107563-2-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 01/10] ovn-controller: Incremental processing engine X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch implements the engine which will be used in future patches for ovn-controller incremental processing. Signed-off-by: Han Zhou --- ovn/lib/automake.mk | 4 +- ovn/lib/inc-proc-eng.c | 141 ++++++++++++++++++++++++++++++++++ ovn/lib/inc-proc-eng.h | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 ovn/lib/inc-proc-eng.c create mode 100644 ovn/lib/inc-proc-eng.h diff --git a/ovn/lib/automake.mk b/ovn/lib/automake.mk index 6178fc2..c1d37c5 100644 --- a/ovn/lib/automake.mk +++ b/ovn/lib/automake.mk @@ -17,7 +17,9 @@ ovn_lib_libovn_la_SOURCES = \ ovn/lib/ovn-util.c \ ovn/lib/ovn-util.h \ ovn/lib/logical-fields.c \ - ovn/lib/logical-fields.h + ovn/lib/logical-fields.h \ + ovn/lib/inc-proc-eng.c \ + ovn/lib/inc-proc-eng.h nodist_ovn_lib_libovn_la_SOURCES = \ ovn/lib/ovn-nb-idl.c \ ovn/lib/ovn-nb-idl.h \ diff --git a/ovn/lib/inc-proc-eng.c b/ovn/lib/inc-proc-eng.c new file mode 100644 index 0000000..8006acd --- /dev/null +++ b/ovn/lib/inc-proc-eng.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2018 eBay 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 +#include +#include +#include +#include + +#include "openvswitch/dynamic-string.h" +#include "openvswitch/hmap.h" +#include "openvswitch/vlog.h" +#include "inc-proc-eng.h" + +VLOG_DEFINE_THIS_MODULE(inc_proc_eng); + +static bool engine_force_recompute = false; + +void +engine_set_force_recompute(bool val) +{ + engine_force_recompute = val; +} + +void +engine_init(struct engine_node *node) +{ + for (size_t i = 0; i < node->n_inputs; i++) { + engine_init(node->inputs[i].node); + } + if (node->init) { + node->init(node); + } +} + +void +engine_cleanup(struct engine_node *node) +{ + for (size_t i = 0; i < node->n_inputs; i++) { + engine_cleanup(node->inputs[i].node); + } + if (node->cleanup) { + node->cleanup(node); + } +} + +struct engine_node * +engine_get_input(const char *input_name, struct engine_node *node) +{ + size_t i; + for (i = 0; i < node->n_inputs; i++) { + if (!strcmp(node->inputs[i].node->name, input_name)) { + return node->inputs[i].node; + } + } + return NULL; +} + +void +engine_add_input(struct engine_node *node, struct engine_node *input, + bool (*change_handler)(struct engine_node *)) +{ + ovs_assert(node->n_inputs < ENGINE_MAX_INPUT); + node->inputs[node->n_inputs].node = input; + node->inputs[node->n_inputs].change_handler = change_handler; + node->n_inputs ++; +} + +void +engine_run(struct engine_node *node, uint64_t run_id) +{ + if (node->run_id == run_id) { + return; + } + node->run_id = run_id; + + node->changed = false; + if (!node->n_inputs) { + node->run(node); + VLOG_DBG("node: %s, changed: %d", node->name, node->changed); + return; + } + + for (size_t i = 0; i < node->n_inputs; i++) { + engine_run(node->inputs[i].node, run_id); + } + + bool need_compute = false; + bool need_recompute = false; + + if (engine_force_recompute) { + need_recompute = true; + } else { + for (size_t i = 0; i < node->n_inputs; i++) { + if (node->inputs[i].node->changed) { + need_compute = true; + if (!node->inputs[i].change_handler) { + need_recompute = true; + break; + } + } + } + } + + if (need_recompute) { + VLOG_DBG("node: %s, recompute (%s)", node->name, + engine_force_recompute ? "forced" : "triggered"); + node->run(node); + } else if (need_compute) { + for (size_t i = 0; i < node->n_inputs; i++) { + if (node->inputs[i].node->changed) { + VLOG_DBG("node: %s, handle change for input %s", + node->name, node->inputs[i].node->name); + if (!node->inputs[i].change_handler(node)) { + VLOG_DBG("node: %s, can't handle change for input %s, " + "fall back to recompute", + node->name, node->inputs[i].node->name); + node->run(node); + break; + } + } + } + } + + VLOG_DBG("node: %s, changed: %d", node->name, node->changed); +} diff --git a/ovn/lib/inc-proc-eng.h b/ovn/lib/inc-proc-eng.h new file mode 100644 index 0000000..8399321 --- /dev/null +++ b/ovn/lib/inc-proc-eng.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2018 eBay 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 INC_PROC_ENG_H +#define INC_PROC_ENG_H 1 + +/* The Incremental Processing Engine is a framework for incrementally + * processing changes from different inputs. The main user is ovn-controller. + * To compute desired states (e.g. openflow rules) based on many inputs (e.g. + * south-bound DB tables, local OVSDB interfaces, etc.), it is straightforward + * to recompute everything when there is any change in any inputs, but it + * is inefficient when the size of the input data becomes large. Instead, + * tracking the changes and update the desired states based on what's changed + * is more efficient and scalable. However, it is not straightforward to + * implement the change-based processing when there are a big number of + * inputs. In addition, what makes it more complicated is that intermediate + * results needs to be computed, which needs to be reused in different part + * of the processing and finally generates the final desired states. It is + * proved to be difficult and error-prone to implement this kind of complex + * processing by ad-hoc implementation. + * + * This framework is to provide a generic way to solve the above problem. + * It does not understand the processing logic, but provides a unified way + * to describe the inputs and dependencies clearly, with interfaces for + * users to implement the processing logic for how to handle each input + * changes. + * + * The engine is composed of engine_nodes. Each engine_node is either + * an input, an output or both (intermediate result). Each engine node + * maintains its own data, which is persistent across interactions. Each node + * has zero to ENGINE_MAX_INPUT inputs, which creates a DAG (directed + * acyclic graph). For each input of each engine_node, there is a + * change_handler to process changes of that input, and update the data + * of the engine_node. Then the user can simply call the run() method + * of the engine so that the processing will happen in the order according + * to the dependencies defined and handle the changes incrementally. + * + * While the more fine-grained dependencies and change-handlers are + * implemented, the more efficient the processing will be, it is not + * realistic to implement all change-processing for all inputs (and + * intermediate results). The engine doesn't require change-handler to be + * implemented for every input of every node. Users can choose to implement + * the most important change-handlers (for the changes happens most + * frequently) for overall performance. When there is no change_handler + * defined for a certain input on a certain engine_node, the run() method + * of the engine_node will be called to fall-back to a full recompute + * against all its inputs. + */ + +#define ENGINE_MAX_INPUT 256 + +struct engine_node; + +struct engine_node_input { + /* The input node. */ + struct engine_node *node; + + /* Change handler for changes of the input node. The changes may need to be + * evaluated against all the other inputs. Returns: + * - true: if change can be handled + * - false: if change cannot be handled (indicating full recompute needed) + */ + bool (*change_handler)(struct engine_node *node); +}; + +struct engine_node { + /* A unique id to distinguish each iteration of the engine_run(). */ + uint64_t run_id; + + /* A unique name for each node. */ + char *name; + + /* Number of inputs of this node. */ + size_t n_inputs; + + /* Inputs of this node. */ + struct engine_node_input inputs[ENGINE_MAX_INPUT]; + + /* Data of this node. It is vague and interpreted by the related functions. + * The content of the data should be changed only by the change_handlers + * and run() function of the current node. Users should ensure that the + * data is read-only in change-handlers of the nodes that depends on this + * node. */ + void *data; + + /* Whether the data changed in the last engine run. */ + bool changed; + + /* Context data for the engine processing, such as OVSDB IDLs. */ + void *context; + + /* Method to initialize data. It may be NULL. */ + void (*init)(struct engine_node *); + + /* Method to clean up data. It may be NULL. */ + void (*cleanup)(struct engine_node *); + + /* Fully processes all inputs of this node and regenerates the data + * of this node */ + void (*run)(struct engine_node *); +}; + +/* Initialize the data for the engine nodes recursively. It calls each node's + * init() method if not NULL. It should be called before the main loop. */ +void engine_init(struct engine_node *); + +/* Execute the processing recursively, which should be called in the main + * loop. */ +void engine_run(struct engine_node *, uint64_t run_id); + +/* Clean up the data for the engine nodes recursively. It calls each node's + * cleanup() method if not NULL. It should be called before the program + * terminates. */ +void engine_cleanup(struct engine_node *); + +/* Get the input node with for */ +struct engine_node * engine_get_input(const char *input_name, + struct engine_node *); + +/* Add an input (dependency) for , with corresponding change_handler, + * which can be NULL. If the change_handler is NULL, the engine will not + * be able to process the change incrementally, and will fall back to call + * the run method to recompute. */ +void engine_add_input(struct engine_node *node, struct engine_node *input, + bool (*change_handler)(struct engine_node *)); + +/* Force the engine to recompute everything if set to true. It is used + * in circumstances when we are not sure there is change or not, or + * when there is change but the engine couldn't be executed in that + * iteration, and the change can't be tracked across iterations */ +void engine_set_force_recompute(bool val); + +/* Macro to define an engine node. */ +#define ENGINE_NODE(NAME, NAME_STR, CTX) \ + struct engine_node en_##NAME = { \ + .name = NAME_STR, \ + .data = &ed_##NAME, \ + .context = CTX, \ + .init = en_##NAME##_init, \ + .run = en_##NAME##_run, \ + .cleanup = en_##NAME##_cleanup, \ + }; + +/* Macro to define member functions of an engine node which represents + * a table of OVSDB */ +#define ENGINE_FUNC_OVSDB(DB_NAME, TBL_NAME, IDL) \ +static void \ +en_##DB_NAME##_##TBL_NAME##_run(struct engine_node *node) \ +{ \ + static bool first_run = true; \ + if (first_run) { \ + first_run = false; \ + node->changed = true; \ + return; \ + } \ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; \ + if (DB_NAME##rec_##TBL_NAME##_track_get_first(ctx->IDL)) { \ + node->changed = true; \ + return; \ + } \ + node->changed = false; \ +} \ +static void (*en_##DB_NAME##_##TBL_NAME##_init)(struct engine_node *node) \ + = NULL; \ +static void (*en_##DB_NAME##_##TBL_NAME##_cleanup)(struct engine_node *node) \ + = NULL; + +/* Macro to define member functions of an engine node which represents + * a table of OVN SB DB */ +#define ENGINE_FUNC_SB(TBL_NAME) \ + ENGINE_FUNC_OVSDB(sb, TBL_NAME, ovnsb_idl) + +/* Macro to define member functions of an engine node which represents + * a table of open_vswitch DB */ +#define ENGINE_FUNC_OVS(TBL_NAME) \ + ENGINE_FUNC_OVSDB(ovs, TBL_NAME, ovs_idl) + +/* Macro to define an engine node which represents a table of OVN SB DB */ +#define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR, CTX) \ + void *ed_sb_##TBL_NAME; \ + ENGINE_NODE(sb_##TBL_NAME, TBL_NAME_STR, CTX) + +/* Macro to define an engine node which represents a table of open_vswitch + * DB */ +#define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR, CTX) \ + void *ed_ovs_##TBL_NAME; \ + ENGINE_NODE(ovs_##TBL_NAME, TBL_NAME_STR, CTX) + +#endif /* ovn/lib/inc-proc-eng.h */ From patchwork Thu May 24 22:10:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920128 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="nkau/JBK"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNrS6HqFz9s0q for ; Fri, 25 May 2018 08:11:20 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 266B2D2A; Thu, 24 May 2018 22:10:21 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id AA0DCCCB for ; Thu, 24 May 2018 22:10:19 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f68.google.com (mail-pg0-f68.google.com [74.125.83.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 27C566D3 for ; Thu, 24 May 2018 22:10:19 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id 15-v6so1056242pge.2 for ; Thu, 24 May 2018 15:10: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; bh=RN8pddBpzV5lMijRLyCJAgs3IQEpMujBc4TaXbGgMqM=; b=nkau/JBKeUXhuVrrtE1q4x7UwqZTMCnIlneO2HzWh0k3y+6Z+kSNVAOnOlyumx7RLT v2dluKa6XUS7BQzUECofwp0d4xQNCGtiyrV+sqr/dFpoaDxbj1gcqQHj2GyvaaAlYXZn qPezcX8v050fS6qxEDGlwyuX2Rsj51v+7KiPcLh2R9zULNepN+cNnvUPuUT4G19a0mzn HIV3zhqmOOQzzrk1fnh0tSbbnTfPmjMq3wCYNVAalNzmhsqmZfvD01u+Id2VXYfPxcUQ NPAql59vpxKT45DE6jVWjGGOrJVTtZZmW3J5AiDsh4FoMpalHyFPU6HgLVbHigXh/4Jx CzKw== 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; bh=RN8pddBpzV5lMijRLyCJAgs3IQEpMujBc4TaXbGgMqM=; b=qmzjkpgYh0e7bPB3ZnYwQm7rFXWFb1OziBHjs1XLkclA+V6e1fmhZd8RtdjaxPNtAS 9Z1C0cYdj6P2KD5TEPAEu0wRg74Q4EUdlf2eVTTiPPtrbFw2zwLDE9LimC+Nv33Ax3zr um06m/rOyim8QGftRDNdyR0+CPHq/vcA4yyhQpapLNaOIxNcjtoKyWTKJqUkxkM3aJGM ibpCjlpcUiDExOyp3SP3T85E4ifMj3nrMIjuZlH/p/fGarD083y7+Ncoos+CAG23gy27 SRqkL0cs4aSn93HL+sZ1i7S9fwgku4bfWDExAr5kAxnMO6g6Y5AwUOJTWNf7iFuMviyx dj2g== X-Gm-Message-State: ALKqPwfPIWiVphhT9+zREaKxvx69LSh2tpA8fNHgeeDRjg6brf6WofPd iNeuRdb9Uq8F7fUNqUgy4QugkA== X-Google-Smtp-Source: AB8JxZoCLnM7JBUruK2Mh3VIULvtJ2LbLi05Dm4FMnLDxcYxXUkC4LrhMSM1dy3e2Fdy7f+k23MXBA== X-Received: by 2002:a63:b506:: with SMTP id y6-v6mr7465568pge.213.1527199818548; Thu, 24 May 2018 15:10:18 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:17 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:43 -0700 Message-Id: <1527199851-107563-3-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 02/10] ovn-controller: Track OVSDB changes X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Track OVSDB changes for future patches of incremental processing Signed-off-by: Han Zhou --- ovn/controller/bfd.c | 4 ++-- ovn/controller/binding.c | 16 ++++++++-------- ovn/controller/encaps.c | 12 ++++++------ ovn/controller/ovn-controller.c | 22 +++++++++++++--------- ovn/controller/physical.c | 12 ++++++------ 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/ovn/controller/bfd.c b/ovn/controller/bfd.c index 8f020d5..d7ea9e8 100644 --- a/ovn/controller/bfd.c +++ b/ovn/controller/bfd.c @@ -34,8 +34,8 @@ bfd_register_ovs_idl(struct ovsdb_idl *ovs_idl) { /* NOTE: this assumes that binding.c has added the * ovsrec_interface table */ - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd_status); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_bfd_status); } diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c index 0785a94..84ff4d6 100644 --- a/ovn/controller/binding.c +++ b/ovn/controller/binding.c @@ -53,16 +53,16 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_qos); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_name); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_interfaces); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_qos); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_external_ids); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd_status); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_status); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); + 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_add_table(ovs_idl, &ovsrec_table_qos); ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_type); diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c index f187a8f..9f33394 100644 --- a/ovn/controller/encaps.c +++ b/ovn/controller/encaps.c @@ -32,13 +32,13 @@ encaps_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge); ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_external_ids); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_name); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_interfaces); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_external_ids); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_type); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_options); + 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_options); } /* Enough context to create a new tunnel, using tunnel_add(). */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 86e1836..d4cc69f 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -520,16 +520,16 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_external_ids); ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_bridges); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_bfd_status); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_type); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_options); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_ofport); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); + 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_type); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_options); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_external_ids); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_name); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_interfaces); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_external_ids); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge); ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports); ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_name); @@ -638,6 +638,7 @@ main(int argc, char *argv[]) create_ovnsb_indexes(ovnsb_idl_loop.idl); lport_init(ovnsb_idl_loop.idl); + ovsdb_idl_track_add_all(ovnsb_idl_loop.idl); ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg); update_sb_monitors(ovnsb_idl_loop.idl, NULL, NULL, NULL); ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl); @@ -833,6 +834,9 @@ main(int argc, char *argv[]) } } } + + ovsdb_idl_track_clear(ctx.ovnsb_idl); + ovsdb_idl_track_clear(ctx.ovs_idl); poll_block(); if (should_service_stop()) { exiting = true; diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index fc8adcf..b3aa27a 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -51,14 +51,14 @@ physical_register_ovs_idl(struct ovsdb_idl *ovs_idl) ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_interfaces); - ovsdb_idl_add_column(ovs_idl, &ovsrec_port_col_external_ids); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_name); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_interfaces); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_external_ids); ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_name); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_ofport); - ovsdb_idl_add_column(ovs_idl, &ovsrec_interface_col_external_ids); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport); + ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_external_ids); } static struct simap localvif_to_ofport = From patchwork Thu May 24 22:10:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920129 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="iqaOo1uY"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNsH12Fcz9s0q for ; Fri, 25 May 2018 08:12:03 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 65659D4C; Thu, 24 May 2018 22:10:23 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E6814D33 for ; Thu, 24 May 2018 22:10:21 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f171.google.com (mail-pf0-f171.google.com [209.85.192.171]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8F035674 for ; Thu, 24 May 2018 22:10:20 +0000 (UTC) Received: by mail-pf0-f171.google.com with SMTP id j20-v6so1542046pff.10 for ; Thu, 24 May 2018 15:10: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; bh=edBKvjjQ+AtrUP73QXxTElElNp833Hf1573oOrBhtPw=; b=iqaOo1uY6GteQS+gGlkMxn3uqmPM/ZrXViS5a+olkBhg+MFL3D0+rrrj2ENMer690W xN4AS0NiLBwL+VnYpWs5COsR8RbPy1CU22ydnFRrG535wAP8IOtfqzXZGSfmlF26zhw3 1HpLdudESrS1JweJMPOGc9UYndRsrU24zM239l5so/5t40M1UByXmmF2F9466UOiVzSI SNE8K8yzh/8lxURg6ZGD3zzssJowLOrJ5xbhOQvjk2ClvU2milh8QrVbjcLC8LPb8LEB LeR1aZYT8RAA7UIejkN15ILC5J43ysZRHM2rLFN/KZfysEm07TbIT65/fqKM+Q132HIE 9nQA== 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; bh=edBKvjjQ+AtrUP73QXxTElElNp833Hf1573oOrBhtPw=; b=lf+8lTdd3TB2/AJ0Kb+ic5q6J6rXGzIMWk7W3uL0FxrjKhMC4G1audqIpBPJTLDM2/ m0/MffTlnZVsRMe8VDDcJWaTM83d7B2gABJq8TkVDTYPSwciwqZsnA/kYwAl78r+xpRT HRDBZuzmxUQuOy135aqdAGIdRYlu+sdw8JL3eKxcdzHfu5jxDN/ULZZJM9ncUojLEgPo oE8erRD/8dbABJPIXWcVvv/UtODy/cAAgFS+OOHjXTNkykSgDlQV3A7NI9uSuVGefh1K 5kSQQ29+0vjji6JkReWsnkvJ3lNNKr/Ma64/fjxV+ZJ1txENQsBvJwpvB2578/yp1yZ1 1ahg== X-Gm-Message-State: ALKqPwcDfmlvtwaNbzX4T1HceIqdP21soj7+m8MyURbo92z1djuan9ee AVP754RlqMFN+hjCOdgYfQpdiQ== X-Google-Smtp-Source: AB8JxZoXpC7Sx0C4Yv9Awu1agWmeztVWKDArPYpH7sI/iwjq/mLs1QefYgsZTl6JJGQNKfy6UOg8jg== X-Received: by 2002:a62:104a:: with SMTP id y71-v6mr8957758pfi.188.1527199819570; Thu, 24 May 2018 15:10:19 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:18 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:44 -0700 Message-Id: <1527199851-107563-4-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 03/10] ovn-controller: Initial use of incremental engine in main X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Incremental proccessing engine is used to compute flows. In this patch we only create 2 engine nodes with simple dependency: runtime_data -> flow_output In each iteration everything is still recomputed. Signed-off-by: Han Zhou --- ovn/controller/ofctrl.c | 21 +- ovn/controller/ofctrl.h | 5 +- ovn/controller/ovn-controller.c | 481 ++++++++++++++++++++++++++-------------- 3 files changed, 337 insertions(+), 170 deletions(-) diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 349de3a..134f0e5 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -477,11 +477,21 @@ recv_S_UPDATE_FLOWS(const struct ofp_header *oh, enum ofptype type, } } + +enum mf_field_id +ofctrl_get_mf_field_id(void) +{ + if (!rconn_is_connected(swconn)) { + return 0; + } + return (state == S_CLEAR_FLOWS || state == S_UPDATE_FLOWS + ? mff_ovn_geneve : 0); +} + /* Runs the OpenFlow state machine against 'br_int', which is local to the * hypervisor on which we are running. Attempts to negotiate a Geneve option - * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. If successful, - * returns the MFF_* field ID for the option, otherwise returns 0. */ -enum mf_field_id + * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. */ +void ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones) { char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name); @@ -494,7 +504,7 @@ ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones) rconn_run(swconn); if (!rconn_is_connected(swconn)) { - return 0; + return; } if (seqno != rconn_get_connection_seqno(swconn)) { seqno = rconn_get_connection_seqno(swconn); @@ -557,9 +567,6 @@ ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones) * point, so ensure that we come back again without waiting. */ poll_immediate_wake(); } - - return (state == S_CLEAR_FLOWS || state == S_UPDATE_FLOWS - ? mff_ovn_geneve : 0); } void diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h index a8b3afc..45081e5 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -33,8 +33,9 @@ struct shash; /* Interface for OVN main loop. */ void ofctrl_init(struct ovn_extend_table *group_table, struct ovn_extend_table *meter_table); -enum mf_field_id ofctrl_run(const struct ovsrec_bridge *br_int, - struct shash *pending_ct_zones); +void ofctrl_run(const struct ovsrec_bridge *br_int, + struct shash *pending_ct_zones); +enum mf_field_id ofctrl_get_mf_field_id(void); bool ofctrl_can_put(void); void ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, int64_t nb_cfg); diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index d4cc69f..91e0293 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -60,6 +60,7 @@ #include "timeval.h" #include "timer.h" #include "stopwatch.h" +#include "ovn/lib/inc-proc-eng.h" VLOG_DEFINE_THIS_MODULE(main); @@ -208,15 +209,26 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, ovsdb_idl_condition_destroy(&dns); } +static const char * +br_int_name(const struct ovsrec_open_vswitch *cfg) +{ + return smap_get_def(&cfg->external_ids, "ovn-bridge", DEFAULT_BRIDGE_NAME); +} + static const struct ovsrec_bridge * -create_br_int(struct controller_ctx *ctx, - const struct ovsrec_open_vswitch *cfg, - const char *bridge_name) +create_br_int(struct controller_ctx *ctx) { if (!ctx->ovs_idl_txn) { return NULL; } + const struct ovsrec_open_vswitch *cfg; + cfg = ovsrec_open_vswitch_first(ctx->ovs_idl); + if (!cfg) { + return NULL; + } + const char *bridge_name = br_int_name(cfg); + ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn, "ovn-controller: creating integration bridge '%s'", bridge_name); @@ -259,15 +271,7 @@ get_br_int(struct controller_ctx *ctx) return NULL; } - const char *br_int_name = smap_get_def(&cfg->external_ids, "ovn-bridge", - DEFAULT_BRIDGE_NAME); - - const struct ovsrec_bridge *br; - br = get_bridge(ctx->ovs_idl, br_int_name); - if (!br) { - return create_br_int(ctx, cfg, br_int_name); - } - return br; + return get_bridge(ctx->ovs_idl, br_int_name(cfg)); } static const char * @@ -476,11 +480,8 @@ restore_ct_zones(struct ovsdb_idl *ovs_idl, return; } - const char *br_int_name = smap_get_def(&cfg->external_ids, "ovn-bridge", - DEFAULT_BRIDGE_NAME); - const struct ovsrec_bridge *br_int; - br_int = get_bridge(ovs_idl, br_int_name); + br_int = get_bridge(ovs_idl, br_int_name(cfg)); if (!br_int) { /* If the integration bridge hasn't been defined, assume that * any existing ct-zone definitions aren't valid. */ @@ -588,6 +589,227 @@ create_ovnsb_indexes(struct ovsdb_idl *ovnsb_idl) OVSDB_INDEX_ASC, NULL); } +struct ed_type_runtime_data { + struct chassis_index chassis_index; + + /* Contains "struct local_datapath" nodes. */ + struct hmap local_datapaths; + + /* Contains the name of each logical port resident on the local + * hypervisor. These logical ports include the VIFs (and their child + * logical ports, if any) that belong to VMs running on the hypervisor, + * l2gateway ports for which options:l2gateway-chassis designates the + * local hypervisor, and localnet ports. */ + struct sset local_lports; + + /* Contains the same ports as local_lports, but in the format: + * _ */ + struct sset local_lport_ids; + struct sset active_tunnels; + struct shash addr_sets; + struct shash port_groups; + + /* connection tracking zones. */ + unsigned long ct_zone_bitmap[BITMAP_N_LONGS(MAX_CT_ZONES)]; + struct shash pending_ct_zones; + struct simap ct_zones; +}; + +static void +en_runtime_data_init(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)node->data; + hmap_init(&data->local_datapaths); + sset_init(&data->local_lports); + sset_init(&data->local_lport_ids); + sset_init(&data->active_tunnels); + shash_init(&data->addr_sets); + shash_init(&data->port_groups); + shash_init(&data->pending_ct_zones); + simap_init(&data->ct_zones); + + /* Initialize connection tracking zones. */ + memset(data->ct_zone_bitmap, 0, sizeof data->ct_zone_bitmap); + bitmap_set1(data->ct_zone_bitmap, 0); /* Zone 0 is reserved. */ + restore_ct_zones(ctx->ovs_idl, &data->ct_zones, data->ct_zone_bitmap); +} + +static void +en_runtime_data_cleanup(struct engine_node *node) +{ + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)node->data; + + expr_const_sets_destroy(&data->addr_sets); + shash_destroy(&data->addr_sets); + expr_const_sets_destroy(&data->port_groups); + shash_destroy(&data->port_groups); + + chassis_index_destroy(&data->chassis_index); + + sset_destroy(&data->local_lports); + sset_destroy(&data->local_lport_ids); + sset_destroy(&data->active_tunnels); + struct local_datapath *cur_node, *next_node; + HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, + &data->local_datapaths) { + free(cur_node->peer_dps); + hmap_remove(&data->local_datapaths, &cur_node->hmap_node); + free(cur_node); + } + hmap_destroy(&data->local_datapaths); + + simap_destroy(&data->ct_zones); + shash_destroy(&data->pending_ct_zones); +} + +static void +en_runtime_data_run(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)node->data; + struct hmap *local_datapaths = &data->local_datapaths; + struct sset *local_lports = &data->local_lports; + struct sset *local_lport_ids = &data->local_lport_ids; + struct sset *active_tunnels = &data->active_tunnels; + struct chassis_index *chassis_index = &data->chassis_index; + struct shash *addr_sets = &data->addr_sets; + struct shash *port_groups = &data->port_groups; + unsigned long *ct_zone_bitmap = data->ct_zone_bitmap; + struct shash *pending_ct_zones = &data->pending_ct_zones; + struct simap *ct_zones = &data->ct_zones; + + static bool first_run = true; + if (first_run) { + /* don't cleanup since there is no data yet */ + first_run = false; + } else { + struct local_datapath *cur_node, *next_node; + HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, local_datapaths) { + free(cur_node->peer_dps); + hmap_remove(local_datapaths, &cur_node->hmap_node); + free(cur_node); + } + hmap_clear(local_datapaths); + sset_destroy(local_lports); + sset_destroy(local_lport_ids); + sset_destroy(active_tunnels); + chassis_index_destroy(chassis_index); + expr_const_sets_destroy(addr_sets); + expr_const_sets_destroy(port_groups); + sset_init(local_lports); + sset_init(local_lport_ids); + sset_init(active_tunnels); + } + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + ovs_assert(br_int && chassis_id); + const struct sbrec_chassis *chassis = NULL; + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + ovs_assert(chassis); + + chassis_index_init(chassis_index, ctx->ovnsb_idl); + bfd_calculate_active_tunnels(br_int, active_tunnels); + binding_run(ctx, br_int, chassis, + chassis_index, active_tunnels, local_datapaths, + local_lports, local_lport_ids); + + addr_sets_init(ctx, addr_sets); + port_groups_init(ctx, port_groups); + update_ct_zones(local_lports, local_datapaths, ct_zones, + ct_zone_bitmap, pending_ct_zones); + + node->changed = true; +} + +struct ed_type_flow_output { + /* desired flows */ + struct hmap flow_table; + /* group ids for load balancing */ + struct ovn_extend_table group_table; + /* meter ids for QoS */ + struct ovn_extend_table meter_table; +}; + +static void +en_flow_output_init(struct engine_node *node) +{ + struct ed_type_flow_output *data = + (struct ed_type_flow_output *)node->data; + hmap_init(&data->flow_table); + ovn_extend_table_init(&data->group_table); + ovn_extend_table_init(&data->meter_table); +} + +static void +en_flow_output_cleanup(struct engine_node *node) +{ + struct ed_type_flow_output *data = + (struct ed_type_flow_output *)node->data; + hmap_destroy(&data->flow_table); + ovn_extend_table_destroy(&data->group_table); + ovn_extend_table_destroy(&data->meter_table); +} + +static void +en_flow_output_run(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *rt_data = + (struct ed_type_runtime_data *)engine_get_input( + "runtime_data", node)->data; + struct hmap *local_datapaths = &rt_data->local_datapaths; + struct sset *local_lports = &rt_data->local_lports; + struct sset *local_lport_ids = &rt_data->local_lport_ids; + struct sset *active_tunnels = &rt_data->active_tunnels; + struct chassis_index *chassis_index = &rt_data->chassis_index; + struct shash *addr_sets = &rt_data->addr_sets; + struct shash *port_groups = &rt_data->port_groups; + struct simap *ct_zones = &rt_data->ct_zones; + + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + + const struct sbrec_chassis *chassis = NULL; + if (chassis_id) { + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + } + + ovs_assert(br_int && chassis); + + struct ed_type_flow_output *fo = + (struct ed_type_flow_output *)node->data; + struct hmap *flow_table = &fo->flow_table; + struct ovn_extend_table *group_table = &fo->group_table; + struct ovn_extend_table *meter_table = &fo->meter_table; + + static bool first_run = true; + if (first_run) { + first_run = false; + } else { + hmap_clear(flow_table); + } + + lflow_run(ctx, chassis, + chassis_index, local_datapaths, group_table, + meter_table, addr_sets, port_groups, flow_table, + active_tunnels, local_lport_ids); + + enum mf_field_id mff_ovn_geneve = ofctrl_get_mf_field_id(); + + physical_run(ctx, mff_ovn_geneve, + br_int, chassis, ct_zones, + flow_table, local_datapaths, local_lports, + chassis_index, active_tunnels); + node->changed = true; +} + int main(int argc, char *argv[]) { @@ -609,17 +831,9 @@ main(int argc, char *argv[]) } unixctl_command_register("exit", "", 0, 0, ovn_controller_exit, &exiting); - /* Initialize group ids for loadbalancing. */ - struct ovn_extend_table group_table; - ovn_extend_table_init(&group_table); - - /* Initialize meter ids for QoS. */ - struct ovn_extend_table meter_table; - ovn_extend_table_init(&meter_table); daemonize_complete(); - ofctrl_init(&group_table, &meter_table); pinctrl_init(); lflow_init(); @@ -643,21 +857,32 @@ main(int argc, char *argv[]) update_sb_monitors(ovnsb_idl_loop.idl, NULL, NULL, NULL); ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl); - /* Initialize connection tracking zones. */ - struct simap ct_zones = SIMAP_INITIALIZER(&ct_zones); - struct shash pending_ct_zones = SHASH_INITIALIZER(&pending_ct_zones); - unsigned long ct_zone_bitmap[BITMAP_N_LONGS(MAX_CT_ZONES)]; - memset(ct_zone_bitmap, 0, sizeof ct_zone_bitmap); - bitmap_set1(ct_zone_bitmap, 0); /* Zone 0 is reserved. */ - restore_ct_zones(ovs_idl_loop.idl, &ct_zones, ct_zone_bitmap); + + stopwatch_create(CONTROLLER_LOOP_STOPWATCH_NAME, SW_MS); + + struct controller_ctx ctx = { + .ovs_idl = ovs_idl_loop.idl, + .ovnsb_idl = ovnsb_idl_loop.idl + }; + struct ed_type_runtime_data ed_runtime_data; + struct ed_type_flow_output ed_flow_output; + + ENGINE_NODE(runtime_data, "runtime_data", &ctx); + ENGINE_NODE(flow_output, "flow_output", &ctx); + + engine_add_input(&en_flow_output, &en_runtime_data, NULL); + engine_init(&en_flow_output); + + ofctrl_init(&ed_flow_output.group_table, + &ed_flow_output.meter_table); unixctl_command_register("ct-zone-list", "", 0, 0, - ct_zone_list, &ct_zones); + ct_zone_list, &ed_runtime_data.ct_zones); struct pending_pkt pending_pkt = { .conn = NULL }; unixctl_command_register("inject-pkt", "MICROFLOW", 1, 1, inject_pkt, &pending_pkt); - stopwatch_create(CONTROLLER_LOOP_STOPWATCH_NAME, SW_MS); + uint64_t engine_run_id = 0; /* Main loop. */ exiting = false; while (!exiting) { @@ -671,145 +896,82 @@ main(int argc, char *argv[]) free(new_ovnsb_remote); } - struct controller_ctx ctx = { - .ovs_idl = ovs_idl_loop.idl, - .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop), - .ovnsb_idl = ovnsb_idl_loop.idl, - .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop), - }; + ctx.ovs_idl = ovs_idl_loop.idl; + ctx.ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop); + ctx.ovnsb_idl = ovnsb_idl_loop.idl; + ctx.ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop); update_probe_interval(&ctx, ovnsb_remote); update_ssl_config(ctx.ovs_idl); - /* Contains "struct local_datapath" nodes. */ - struct hmap local_datapaths = HMAP_INITIALIZER(&local_datapaths); - - /* Contains the name of each logical port resident on the local - * hypervisor. These logical ports include the VIFs (and their child - * logical ports, if any) that belong to VMs running on the hypervisor, - * l2gateway ports for which options:l2gateway-chassis designates the - * local hypervisor, and localnet ports. */ - struct sset local_lports = SSET_INITIALIZER(&local_lports); - /* Contains the same ports as local_lports, but in the format: - * _ */ - struct sset local_lport_ids = SSET_INITIALIZER(&local_lport_ids); - struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels); - const struct ovsrec_bridge *br_int = get_br_int(&ctx); + if (!br_int) { + br_int = create_br_int(&ctx); + } const char *chassis_id = get_chassis_id(ctx.ovs_idl); + const struct sbrec_chassis *chassis + = chassis_id ? chassis_run(&ctx, chassis_id, br_int) : NULL; - struct chassis_index chassis_index; - - chassis_index_init(&chassis_index, ctx.ovnsb_idl); - - const struct sbrec_chassis *chassis = NULL; - if (chassis_id) { - chassis = chassis_run(&ctx, chassis_id, br_int); - encaps_run(&ctx, br_int, chassis_id); - bfd_calculate_active_tunnels(br_int, &active_tunnels); - binding_run(&ctx, br_int, chassis, - &chassis_index, &active_tunnels, &local_datapaths, - &local_lports, &local_lport_ids); - } if (br_int && chassis) { - struct shash addr_sets = SHASH_INITIALIZER(&addr_sets); - addr_sets_init(&ctx, &addr_sets); - struct shash port_groups = SHASH_INITIALIZER(&port_groups); - port_groups_init(&ctx, &port_groups); - + ofctrl_run(br_int, &ed_runtime_data.pending_ct_zones); patch_run(&ctx, br_int, chassis); + encaps_run(&ctx, br_int, chassis_id); - enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int, - &pending_ct_zones); - - pinctrl_run(&ctx, br_int, chassis, &chassis_index, - &local_datapaths, &active_tunnels); - update_ct_zones(&local_lports, &local_datapaths, &ct_zones, - ct_zone_bitmap, &pending_ct_zones); - if (ctx.ovs_idl_txn) { - if (ofctrl_can_put()) { - stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, - time_msec()); - - commit_ct_zones(br_int, &pending_ct_zones); - - struct hmap flow_table = HMAP_INITIALIZER(&flow_table); - lflow_run(&ctx, chassis, - &chassis_index, &local_datapaths, &group_table, - &meter_table, &addr_sets, &port_groups, - &flow_table, &active_tunnels, &local_lport_ids); - - if (chassis_id) { - bfd_run(&ctx, br_int, chassis, &local_datapaths, - &chassis_index); - } - physical_run(&ctx, mff_ovn_geneve, - br_int, chassis, &ct_zones, - &flow_table, &local_datapaths, &local_lports, - &chassis_index, &active_tunnels); - - stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME, - time_msec()); - - ofctrl_put(&flow_table, &pending_ct_zones, - get_nb_cfg(ctx.ovnsb_idl)); - - hmap_destroy(&flow_table); - } - if (ctx.ovnsb_idl_txn) { - int64_t cur_cfg = ofctrl_get_cur_cfg(); - if (cur_cfg && cur_cfg != chassis->nb_cfg) { - sbrec_chassis_set_nb_cfg(chassis, cur_cfg); - } + if (ofctrl_can_put()) { + stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, + time_msec()); + engine_run(&en_flow_output, ++engine_run_id); + stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME, + time_msec()); + + if (ctx.ovs_idl_txn) { + commit_ct_zones(br_int, &ed_runtime_data.pending_ct_zones); + bfd_run(&ctx, br_int, chassis, + &ed_runtime_data.local_datapaths, + &ed_runtime_data.chassis_index); } + ofctrl_put(&ed_flow_output.flow_table, + &ed_runtime_data.pending_ct_zones, + get_nb_cfg(ctx.ovnsb_idl)); + } + pinctrl_run(&ctx, br_int, chassis, &ed_runtime_data.chassis_index, + &ed_runtime_data.local_datapaths, + &ed_runtime_data.active_tunnels); + + update_sb_monitors(ctx.ovnsb_idl, chassis, + &ed_runtime_data.local_lports, + &ed_runtime_data.local_datapaths); + + } + + if (ctx.ovnsb_idl_txn) { + int64_t cur_cfg = ofctrl_get_cur_cfg(); + if (cur_cfg && cur_cfg != chassis->nb_cfg) { + sbrec_chassis_set_nb_cfg(chassis, cur_cfg); } + } - if (pending_pkt.conn) { + + if (pending_pkt.conn) { + if (br_int && chassis) { char *error = ofctrl_inject_pkt(br_int, pending_pkt.flow_s, - &port_groups, &addr_sets); + &ed_runtime_data.port_groups, + &ed_runtime_data.addr_sets); if (error) { unixctl_command_reply_error(pending_pkt.conn, error); free(error); } else { unixctl_command_reply(pending_pkt.conn, NULL); } - pending_pkt.conn = NULL; - free(pending_pkt.flow_s); + } else { + unixctl_command_reply_error(pending_pkt.conn, + "ovn-controller not ready."); } - - update_sb_monitors(ctx.ovnsb_idl, chassis, - &local_lports, &local_datapaths); - - expr_const_sets_destroy(&addr_sets); - shash_destroy(&addr_sets); - expr_const_sets_destroy(&port_groups); - shash_destroy(&port_groups); - } - - /* If we haven't handled the pending packet insertion - * request, the system is not ready. */ - if (pending_pkt.conn) { - unixctl_command_reply_error(pending_pkt.conn, - "ovn-controller not ready."); pending_pkt.conn = NULL; free(pending_pkt.flow_s); } - chassis_index_destroy(&chassis_index); - - sset_destroy(&local_lports); - sset_destroy(&local_lport_ids); - sset_destroy(&active_tunnels); - - struct local_datapath *cur_node, *next_node; - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, &local_datapaths) { - free(cur_node->peer_dps); - hmap_remove(&local_datapaths, &cur_node->hmap_node); - free(cur_node); - } - hmap_destroy(&local_datapaths); - unixctl_server_run(unixctl); unixctl_server_wait(unixctl); @@ -826,10 +988,11 @@ main(int argc, char *argv[]) if (ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop) == 1) { struct shash_node *iter, *iter_next; - SHASH_FOR_EACH_SAFE(iter, iter_next, &pending_ct_zones) { + SHASH_FOR_EACH_SAFE (iter, iter_next, + &ed_runtime_data.pending_ct_zones) { struct ct_zone_pending_entry *ctzpe = iter->data; if (ctzpe->state == CT_ZONE_DB_SENT) { - shash_delete(&pending_ct_zones, iter); + shash_delete(&ed_runtime_data.pending_ct_zones, iter); free(ctzpe); } } @@ -843,26 +1006,28 @@ main(int argc, char *argv[]) } } + engine_cleanup(&en_flow_output); + /* It's time to exit. Clean up the databases. */ bool done = false; while (!done) { - struct controller_ctx ctx = { + struct controller_ctx ctx_ = { .ovs_idl = ovs_idl_loop.idl, .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop), .ovnsb_idl = ovnsb_idl_loop.idl, .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop), }; - const struct ovsrec_bridge *br_int = get_br_int(&ctx); - const char *chassis_id = get_chassis_id(ctx.ovs_idl); + const struct ovsrec_bridge *br_int = get_br_int(&ctx_); + const char *chassis_id = get_chassis_id(ctx_.ovs_idl); const struct sbrec_chassis *chassis - = chassis_id ? get_chassis(ctx.ovnsb_idl, chassis_id) : NULL; + = chassis_id ? get_chassis(ctx_.ovnsb_idl, chassis_id) : NULL; /* Run all of the cleanup functions, even if one of them returns false. * We're done if all of them return true. */ - done = binding_cleanup(&ctx, chassis); - done = chassis_cleanup(&ctx, chassis) && done; - done = encaps_cleanup(&ctx, br_int) && done; + done = binding_cleanup(&ctx_, chassis); + done = chassis_cleanup(&ctx_, chassis) && done; + done = encaps_cleanup(&ctx_, br_int) && done; if (done) { poll_immediate_wake(); } @@ -877,12 +1042,6 @@ main(int argc, char *argv[]) ofctrl_destroy(); pinctrl_destroy(); - simap_destroy(&ct_zones); - shash_destroy(&pending_ct_zones); - - ovn_extend_table_destroy(&group_table); - ovn_extend_table_destroy(&meter_table); - ovsdb_idl_loop_destroy(&ovs_idl_loop); ovsdb_idl_loop_destroy(&ovnsb_idl_loop); From patchwork Thu May 24 22:10:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920131 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="J9dO41HH"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNtR23cpz9s0q for ; Fri, 25 May 2018 08:13:03 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 526FFD67; Thu, 24 May 2018 22:10:25 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 6E30BD3A for ; Thu, 24 May 2018 22:10:22 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f66.google.com (mail-pg0-f66.google.com [74.125.83.66]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id E3B306C1 for ; Thu, 24 May 2018 22:10:20 +0000 (UTC) Received: by mail-pg0-f66.google.com with SMTP id p21-v6so1374790pgd.11 for ; Thu, 24 May 2018 15:10: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; bh=AS1Ft0R6iJ0USXgk4PQP6Wy24CsDN1HpDTjiTuK3KWE=; b=J9dO41HHxkCFjPKxsIXIPZOw2cYztjgu9FU0dneboGc5y9670FjY6XmCUPEibBRFqA vgVbI2F6u0lYfYHFYUNGN7X2UkWB7jrLInSHF4pnJ94hbULooL10inP9QN/odHaIWm0I UAqeNd6Y8WAKyCYUVOH/ca15+MWsU3WUhmTnhR7nOzaxRn9NvWTpop+zieu0xP0lyIpn jrY7BmYvV7M+EZoQ+EckJiLW/HS9oQzitRQMXTptlxVRI55xtQUJXzFcl+lROcEDB31X W16TZjfyc9fc68k/qoRJnMN/LhAllqSr203D/r7stvCThvlbpOpCUE6Qmpwo6nXgFpwK qGiQ== 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; bh=AS1Ft0R6iJ0USXgk4PQP6Wy24CsDN1HpDTjiTuK3KWE=; b=FUlXOuIjKBkWjgzvH4wEyscnRSFNDDqbmCH5k3Blj6Wb+DjxRCW/Kv7D/P//yAxoqF 4vxyD79TcoHtXPGFxtd873qogUe723bTA6y6bej2SqoIRtJ8pkIMlQElkLu2bMPzKHA9 d3xiIdDv+UqLipDi9xPT/8mXOIN0fHZIu9nVpt9pKxZkhu2KwV7eodICXniDyXVvwLf0 c5JhVFpp+pG4lBqhh8grw+z3Ny1pAJr7xTPnBStNnfwxkH0nCR1+FRO9RGWLqe8YNOCd 6kYEiMiKHu3K4EGL7x/QYQ89/HRUvqnLy4Tzyk5p9yykuuxOf5Ia1Pz+GhfWNU1v4s+D TUFA== X-Gm-Message-State: ALKqPwdaln+vSQBrEWa7Kg4lEgz8K/DiHcSLbT+tnsbzc8hSGWj89xr2 iUt5qpwysbsMicBlPCgrHDPzMg== X-Google-Smtp-Source: AB8JxZrJRHERU6QGsPZ+ETfN00yeNdPf68vcFkfvUwC2wuL6LToPzPN9wR+vytD0gFBnPGQN1M4KTw== X-Received: by 2002:a63:8dca:: with SMTP id z193-v6mr3035919pgd.451.1527199820344; Thu, 24 May 2018 15:10:20 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:19 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:45 -0700 Message-Id: <1527199851-107563-5-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 04/10] ovn-controller: Split SB inputs as separate incremental engine nodes X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch expands the incremental processing by spliting SB inputs from runtime_data and add them as input for flow_output. Signed-off-by: Han Zhou --- ovn/controller/ovn-controller.c | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 91e0293..63b797f 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -589,6 +589,20 @@ create_ovnsb_indexes(struct ovsdb_idl *ovnsb_idl) OVSDB_INDEX_ASC, NULL); } +ENGINE_FUNC_SB(chassis); +ENGINE_FUNC_SB(encap); +ENGINE_FUNC_SB(address_set); +ENGINE_FUNC_SB(port_group); +ENGINE_FUNC_SB(multicast_group); +ENGINE_FUNC_SB(datapath_binding); +ENGINE_FUNC_SB(port_binding); +ENGINE_FUNC_SB(mac_binding); +ENGINE_FUNC_SB(logical_flow); +ENGINE_FUNC_SB(dhcp_options); +ENGINE_FUNC_SB(dhcpv6_options); +ENGINE_FUNC_SB(dns); +ENGINE_FUNC_SB(gateway_chassis); + struct ed_type_runtime_data { struct chassis_index chassis_index; @@ -867,10 +881,38 @@ main(int argc, char *argv[]) struct ed_type_runtime_data ed_runtime_data; struct ed_type_flow_output ed_flow_output; + ENGINE_NODE_SB(chassis, "chassis", &ctx); + ENGINE_NODE_SB(encap, "encap", &ctx); + ENGINE_NODE_SB(address_set, "address_set", &ctx); + ENGINE_NODE_SB(port_group, "port_group", &ctx); + ENGINE_NODE_SB(multicast_group, "multicast_group", &ctx); + ENGINE_NODE_SB(datapath_binding, "datapath_binding", &ctx); + ENGINE_NODE_SB(port_binding, "port_binding", &ctx); + ENGINE_NODE_SB(mac_binding, "mac_binding", &ctx); + ENGINE_NODE_SB(logical_flow, "logical_flow", &ctx); + ENGINE_NODE_SB(dhcp_options, "dhcp_options", &ctx); + ENGINE_NODE_SB(dhcpv6_options, "dhcpv6_options", &ctx); + ENGINE_NODE_SB(dns, "dns", &ctx); + ENGINE_NODE_SB(gateway_chassis, "gateway_chassis", &ctx); + ENGINE_NODE(runtime_data, "runtime_data", &ctx); ENGINE_NODE(flow_output, "flow_output", &ctx); - engine_add_input(&en_flow_output, &en_runtime_data, NULL); + + engine_add_input(&en_flow_output, &en_sb_chassis, NULL); + engine_add_input(&en_flow_output, &en_sb_encap, NULL); + engine_add_input(&en_flow_output, &en_sb_address_set, NULL); + engine_add_input(&en_flow_output, &en_sb_port_group, NULL); + engine_add_input(&en_flow_output, &en_sb_multicast_group, NULL); + engine_add_input(&en_flow_output, &en_sb_datapath_binding, NULL); + engine_add_input(&en_flow_output, &en_sb_port_binding, NULL); + engine_add_input(&en_flow_output, &en_sb_mac_binding, NULL); + engine_add_input(&en_flow_output, &en_sb_logical_flow, NULL); + engine_add_input(&en_flow_output, &en_sb_dhcp_options, NULL); + engine_add_input(&en_flow_output, &en_sb_dhcpv6_options, NULL); + engine_add_input(&en_flow_output, &en_sb_dns, NULL); + engine_add_input(&en_flow_output, &en_sb_gateway_chassis, NULL); + engine_init(&en_flow_output); ofctrl_init(&ed_flow_output.group_table, From patchwork Thu May 24 22:10:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920130 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="O3GzkMVP"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNst5qs0z9s0q for ; Fri, 25 May 2018 08:12:34 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 39AA1D5A; Thu, 24 May 2018 22:10:24 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 5B4C8CEE for ; Thu, 24 May 2018 22:10:22 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f173.google.com (mail-pf0-f173.google.com [209.85.192.173]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id DC43E6D8 for ; Thu, 24 May 2018 22:10:21 +0000 (UTC) Received: by mail-pf0-f173.google.com with SMTP id p14-v6so1542413pfh.9 for ; Thu, 24 May 2018 15:10:21 -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; bh=rU38yneEvjwW+JON6EyfbKqUw2zxFsIn/x9tFEq/u5k=; b=O3GzkMVPfp5K+uERJTjPvASVHS7LGOiPMVAdSNLDM9CdCbG4XpXlHgonoiMy9kM/LV 9Sn6nExkNhHrirOLrKS0Jiu/+L0qCtnGYXfnsB3gIHY2ZCKzpW0EIlNFkm1c7KUNJhhk Wec2KHuI0eWp9lqrquOF1wvE1oHzNgFv4pMC4CWbcDsrbA3aBF+0Iu2Z42JyGwAHyY9R lTv6sAe8Xk4uyDit4zKQ4kFOIdFHRX/spru9A7xKLwtpDfe5FMjUOqjdY9LVPvghqwEA rRT9MSGhxkXPlpEOutVrODGyDIaF7G3EWxxV7BZo0CwFoqsfbgOOTGZn1BYYnALBHNB3 fCgg== 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; bh=rU38yneEvjwW+JON6EyfbKqUw2zxFsIn/x9tFEq/u5k=; b=FgJcnO3APxoV/2nTlFep3Kt14anLqt2fBiFN2ldqzvJFtb4pn1/vznUQcjhK/kCFHl TRe/F2/7cZc/DX+CgDFDj96PxTFmV07TPQlAFs3ksdY8jfvy7JVe5peqTbX2Rp8JYErS 0SH+HUMQH1ESHDqaz3elc+4Zf937BR2T5LbiHbPW1Xrumvbbln2egkPxSzaqYh7B6CcZ SE6omUcdjuPEKFuYCpJGb4AbVFQDceQbZ2E4B872cYymq3Q1jrr/AzfM7fpEm5U8S76B 7DheFed1hD0yTI1dVDjcNbybRCvoBRIbejXzxQj0AWrLFdS6NoFtVPhwHv4ow7wPBkDC GNtQ== X-Gm-Message-State: ALKqPwefDeuRihZW/PN60+XFvxBjSMAZB24TP5EDbD72HMEYw6a987Vy EnTUMDnmcCgAIIjeMFRQAc92+A== X-Google-Smtp-Source: AB8JxZpe35rklKOswcoIfw1Wz4KcIDXY0uFzjZYh56aB1QvfO37pWBIXUyclWqEavGLxge3MvJ/oXg== X-Received: by 2002:a62:578e:: with SMTP id i14-v6mr9121895pfj.119.1527199821188; Thu, 24 May 2018 15:10:21 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:20 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:46 -0700 Message-Id: <1527199851-107563-6-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 05/10] ovn-controller: split ovs_idl inputs in incremental engine X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Create nodes for ovs_idl inputs and add ovs_idl inputs and SB inputs as dependencies for runtime_data. With this patch there is no recomputed if there is no change in input. For example, pinctrl input will not trigger flow recompute any more. Signed-off-by: Han Zhou --- ovn/controller/ovn-controller.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 63b797f..e390afd 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -603,6 +603,9 @@ ENGINE_FUNC_SB(dhcpv6_options); ENGINE_FUNC_SB(dns); ENGINE_FUNC_SB(gateway_chassis); +ENGINE_FUNC_OVS(port); +ENGINE_FUNC_OVS(interface); + struct ed_type_runtime_data { struct chassis_index chassis_index; @@ -729,6 +732,7 @@ en_runtime_data_run(struct engine_node *node) chassis_index_init(chassis_index, ctx->ovnsb_idl); bfd_calculate_active_tunnels(br_int, active_tunnels); + /* requires ctx->ovnsb_idl_txn */ binding_run(ctx, br_int, chassis, chassis_index, active_tunnels, local_datapaths, local_lports, local_lport_ids); @@ -895,10 +899,16 @@ main(int argc, char *argv[]) ENGINE_NODE_SB(dns, "dns", &ctx); ENGINE_NODE_SB(gateway_chassis, "gateway_chassis", &ctx); + ENGINE_NODE_OVS(port, "ovs_table_port", &ctx); + ENGINE_NODE_OVS(interface, "ovs_table_interface", &ctx); + ENGINE_NODE(runtime_data, "runtime_data", &ctx); ENGINE_NODE(flow_output, "flow_output", &ctx); engine_add_input(&en_flow_output, &en_runtime_data, NULL); + engine_add_input(&en_flow_output, &en_ovs_port, NULL); + engine_add_input(&en_flow_output, &en_ovs_interface, NULL); + engine_add_input(&en_flow_output, &en_sb_chassis, NULL); engine_add_input(&en_flow_output, &en_sb_encap, NULL); engine_add_input(&en_flow_output, &en_sb_address_set, NULL); @@ -913,6 +923,15 @@ main(int argc, char *argv[]) engine_add_input(&en_flow_output, &en_sb_dns, NULL); engine_add_input(&en_flow_output, &en_sb_gateway_chassis, NULL); + engine_add_input(&en_runtime_data, &en_ovs_port, NULL); + engine_add_input(&en_runtime_data, &en_ovs_interface, NULL); + + engine_add_input(&en_runtime_data, &en_sb_chassis, NULL); + engine_add_input(&en_runtime_data, &en_sb_address_set, NULL); + engine_add_input(&en_runtime_data, &en_sb_datapath_binding, NULL); + engine_add_input(&en_runtime_data, &en_sb_port_binding, NULL); + engine_add_input(&en_runtime_data, &en_sb_gateway_chassis, NULL); + engine_init(&en_flow_output); ofctrl_init(&ed_flow_output.group_table, @@ -925,9 +944,11 @@ main(int argc, char *argv[]) &pending_pkt); uint64_t engine_run_id = 0; + uint64_t old_engine_run_id = 0; /* Main loop. */ exiting = false; while (!exiting) { + old_engine_run_id = engine_run_id; /* Check OVN SB database. */ char *new_ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl); if (strcmp(ovnsb_remote, new_ovnsb_remote)) { @@ -973,10 +994,13 @@ main(int argc, char *argv[]) &ed_runtime_data.local_datapaths, &ed_runtime_data.chassis_index); } - ofctrl_put(&ed_flow_output.flow_table, - &ed_runtime_data.pending_ct_zones, - get_nb_cfg(ctx.ovnsb_idl)); + if (en_flow_output.changed) { + ofctrl_put(&ed_flow_output.flow_table, + &ed_runtime_data.pending_ct_zones, + get_nb_cfg(ctx.ovnsb_idl)); + } } + pinctrl_run(&ctx, br_int, chassis, &ed_runtime_data.chassis_index, &ed_runtime_data.local_datapaths, &ed_runtime_data.active_tunnels); @@ -986,6 +1010,14 @@ main(int argc, char *argv[]) &ed_runtime_data.local_datapaths); } + if (old_engine_run_id == engine_run_id) { + VLOG_DBG("engine did not run, force recompute next time: " + "br_int %p, chassis %p", br_int, chassis); + engine_set_force_recompute(true); + poll_immediate_wake(); + } else { + engine_set_force_recompute(false); + } if (ctx.ovnsb_idl_txn) { int64_t cur_cfg = ofctrl_get_cur_cfg(); From patchwork Thu May 24 22:10:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920136 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="b4+nJInW"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNxc4JGyz9s0q for ; Fri, 25 May 2018 08:15:48 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4E4E9D7A; Thu, 24 May 2018 22:10:36 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id F11E1D3A for ; Thu, 24 May 2018 22:10:27 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f68.google.com (mail-pg0-f68.google.com [74.125.83.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 997B46D8 for ; Thu, 24 May 2018 22:10:24 +0000 (UTC) Received: by mail-pg0-f68.google.com with SMTP id p9-v6so1373737pgc.9 for ; Thu, 24 May 2018 15:10:24 -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; bh=Tx62GNgzZpABpKoXHQJR4jwwatVyWUHE7mLIMpK9dc8=; b=b4+nJInWVerbW/bkLF37HTBAQrpQioVmk+5iG49EGNujWe+0sh2il92pD+zcCijddE E6vMpIHujJ22Da4MQtfyJelmBKzAFZdU9+Dy0XlswjL5AKGygBpQS3LWBI4o1hQt4jwC o4NemevlSyReJXKm1Z3u9l8auWJepkYPsqbWcEVqtSgfNIT0fT8OOy+lDYlL4mZq06Es PJMiW5ywIBGA5ojGqioDxl1tqUVlV73NGjVwLUyeUV/5I/TYcO3cOlp89lcdK7PQTdQM iqaXIZU+EMtBXLefR2ZhayBYfUX7dM/wjpLVOUvgRpg96YVHTZ+wEGiDdCqfXywZAZZD J2kA== 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; bh=Tx62GNgzZpABpKoXHQJR4jwwatVyWUHE7mLIMpK9dc8=; b=l4qjdoP/qS9jvmK9KGebsbmw8+Cco8orBuUbpWop0zSbGC6OkkWyhvF3Sk2X3JFtf3 EcrFZ558SN9uscfkFzpORWzCqJCdl+w4StuRRGPmCB+xWlf3MsSubxllQd48OPaaeZ7A X0fKIH7QWjc8T1dJBjWpyScaPXfg4ZVH/Tr7/PXA0z5wMHYCX6n84HFs+KHP+OE3Pr7M radQ0lrhBgoRlRaFIMOed+VhZvhVNMfaLT3BdcqlvnarIc8HcLFYEVTdV1u3O5Qasawy GkXlPsa33YraWWcZp5r9Q4BQ5RgoN5q+eKZKSn2ps6hwuugljLAQxN5DRKvPnwm7A8z1 KLIg== X-Gm-Message-State: ALKqPwePX+9VSanIf/Pa43szHqudisrH99RdX3mdf94zLdmnVpMlE3L+ tHQIEhcnhpXp6sEKrKnaLZshkQ== X-Google-Smtp-Source: AB8JxZqfq5TN34r5+KM49WcN86l2Rp1DFlSiaiyjn47tXx8cBG8WiQx1cGPJTA0LvYWNk1pS3CHeLA== X-Received: by 2002:a62:fd12:: with SMTP id p18-v6mr8995312pfh.152.1527199822541; Thu, 24 May 2018 15:10:22 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:21 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:47 -0700 Message-Id: <1527199851-107563-7-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 06/10] ovn-controller: Incremental logical flow processing X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Persistents flow-table and implements change handler of flow_output for SB lflow changes. Signed-off-by: Han Zhou --- include/ovn/actions.h | 3 + ovn/controller/lflow.c | 178 +++++++++++++++++++++++------ ovn/controller/lflow.h | 20 +++- ovn/controller/ofctrl.c | 241 ++++++++++++++++++++++++++++------------ ovn/controller/ofctrl.h | 27 ++++- ovn/controller/ovn-controller.c | 116 +++++++++++++------ ovn/controller/physical.c | 89 ++++++++------- ovn/controller/physical.h | 5 +- ovn/lib/actions.c | 6 +- ovn/lib/extend-table.c | 60 +++++++--- ovn/lib/extend-table.h | 16 ++- 11 files changed, 551 insertions(+), 210 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 6384651..5e4bd5b 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -520,6 +520,9 @@ struct ovnact_encode_params { /* A struct to figure out the meter_id for meter actions. */ struct ovn_extend_table *meter_table; + /* The logical flow uuid that drove this action. */ + struct uuid lflow_uuid; + /* OVN maps each logical flow table (ltable), one-to-one, onto a physical * OpenFlow flow table (ptable). A number of parameters describe this * mapping and data related to flow tables: diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c index d09fd10..9d8f693 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -61,7 +61,8 @@ struct condition_aux { const struct chassis_index *chassis_index; }; -static void consider_logical_flow(struct controller_ctx *ctx, +static bool consider_logical_flow(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, const struct chassis_index *chassis_index, const struct sbrec_logical_flow *lflow, const struct hmap *local_datapaths, @@ -74,7 +75,6 @@ static void consider_logical_flow(struct controller_ctx *ctx, uint32_t *conj_id_ofs, const struct shash *addr_sets, const struct shash *port_groups, - struct hmap *flow_table, struct sset *active_tunnels, struct sset *local_lport_ids); @@ -137,7 +137,8 @@ is_switch(const struct sbrec_datapath_binding *ldp) /* Adds the logical flows from the Logical_Flow table to flow tables. */ static void -add_logical_flows(struct controller_ctx *ctx, +add_logical_flows(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, const struct chassis_index *chassis_index, const struct hmap *local_datapaths, struct ovn_extend_table *group_table, @@ -145,11 +146,10 @@ add_logical_flows(struct controller_ctx *ctx, const struct sbrec_chassis *chassis, const struct shash *addr_sets, const struct shash *port_groups, - struct hmap *flow_table, struct sset *active_tunnels, - struct sset *local_lport_ids) + struct sset *local_lport_ids, + uint32_t *conj_id_ofs) { - uint32_t conj_id_ofs = 1; const struct sbrec_logical_flow *lflow; struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts); @@ -171,12 +171,16 @@ add_logical_flows(struct controller_ctx *ctx, nd_ra_opts_init(&nd_ra_opts); SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) { - consider_logical_flow(ctx, chassis_index, - lflow, local_datapaths, - group_table, meter_table, chassis, - &dhcp_opts, &dhcpv6_opts, &nd_ra_opts, - &conj_id_ofs, addr_sets, port_groups, - flow_table, active_tunnels, local_lport_ids); + if (!consider_logical_flow(flow_table, ctx, chassis_index, + lflow, local_datapaths, + group_table, meter_table, chassis, + &dhcp_opts, &dhcpv6_opts, &nd_ra_opts, + conj_id_ofs, addr_sets, port_groups, + active_tunnels, local_lport_ids)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); + VLOG_ERR_RL(&rl, "Conjunction id overflow when processing lflow " + UUID_FMT, UUID_ARGS(&lflow->header_.uuid)); + } } dhcp_opts_destroy(&dhcp_opts); @@ -184,8 +188,95 @@ add_logical_flows(struct controller_ctx *ctx, nd_ra_opts_destroy(&nd_ra_opts); } -static void -consider_logical_flow(struct controller_ctx *ctx, +bool +lflow_handle_changed_flows(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, + const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + const struct hmap *local_datapaths, + struct ovn_extend_table *group_table, + struct ovn_extend_table *meter_table, + const struct shash *addr_sets, + const struct shash *port_groups, + struct sset *active_tunnels, + struct sset *local_lport_ids, + uint32_t *conj_id_ofs) +{ + bool ret = true; + const struct sbrec_logical_flow *lflow; + + struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts); + struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts); + const struct sbrec_dhcp_options *dhcp_opt_row; + SBREC_DHCP_OPTIONS_FOR_EACH (dhcp_opt_row, ctx->ovnsb_idl) { + dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code, + dhcp_opt_row->type); + } + + + const struct sbrec_dhcpv6_options *dhcpv6_opt_row; + SBREC_DHCPV6_OPTIONS_FOR_EACH(dhcpv6_opt_row, ctx->ovnsb_idl) { + dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code, + dhcpv6_opt_row->type); + } + + struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts); + nd_ra_opts_init(&nd_ra_opts); + + /* Handle removed flows first, and then other flows, so that when + * the flows being added and removed have same match conditions + * can be processed in the proper order */ + SBREC_LOGICAL_FLOW_FOR_EACH_TRACKED (lflow, ctx->ovnsb_idl) { + /* Remove any flows that should be removed. */ + if (sbrec_logical_flow_is_deleted(lflow)) { + VLOG_DBG("handle deleted lflow "UUID_FMT, + UUID_ARGS(&lflow->header_.uuid)); + ofctrl_remove_flows(flow_table, &lflow->header_.uuid); + } + } + SBREC_LOGICAL_FLOW_FOR_EACH_TRACKED (lflow, ctx->ovnsb_idl) { + if (!sbrec_logical_flow_is_deleted(lflow)) { + /* Now, add/modify existing flows. If the logical + * flow is a modification, just remove the flows + * for this row, and then add new flows. */ + if (!sbrec_logical_flow_is_new(lflow)) { + VLOG_DBG("handle updated lflow "UUID_FMT, + UUID_ARGS(&lflow->header_.uuid)); + ofctrl_remove_flows(flow_table, &lflow->header_.uuid); + } + VLOG_DBG("handle new lflow "UUID_FMT, + UUID_ARGS(&lflow->header_.uuid)); + if (!consider_logical_flow(flow_table, ctx, chassis_index, + lflow, local_datapaths, + group_table, meter_table, chassis, + &dhcp_opts, &dhcpv6_opts, &nd_ra_opts, + conj_id_ofs, addr_sets, port_groups, + active_tunnels, local_lport_ids)) { + ret = false; + break; + } + } + } + dhcp_opts_destroy(&dhcp_opts); + dhcp_opts_destroy(&dhcpv6_opts); + nd_ra_opts_destroy(&nd_ra_opts); + return ret; +} + +static bool +update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs) +{ + if (*conj_id_ofs + n_conjs < *conj_id_ofs) { + /* overflow */ + return false; + } + *conj_id_ofs += n_conjs; + return true; +} + +static bool +consider_logical_flow(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, const struct chassis_index *chassis_index, const struct sbrec_logical_flow *lflow, const struct hmap *local_datapaths, @@ -198,7 +289,6 @@ consider_logical_flow(struct controller_ctx *ctx, uint32_t *conj_id_ofs, const struct shash *addr_sets, const struct shash *port_groups, - struct hmap *flow_table, struct sset *active_tunnels, struct sset *local_lport_ids) { @@ -207,10 +297,14 @@ consider_logical_flow(struct controller_ctx *ctx, const struct sbrec_datapath_binding *ldp = lflow->logical_datapath; if (!ldp) { - return; + VLOG_DBG("lflow "UUID_FMT" has no datapath binding, skip", + UUID_ARGS(&lflow->header_.uuid)); + return true; } if (!get_local_datapath(local_datapaths, ldp->tunnel_key)) { - return; + VLOG_DBG("lflow "UUID_FMT" is not for local datapath, skip", + UUID_ARGS(&lflow->header_.uuid)); + return true; } /* Determine translation of logical table IDs to physical table IDs. */ @@ -248,7 +342,7 @@ consider_logical_flow(struct controller_ctx *ctx, free(error); ovnacts_free(ovnacts.data, ovnacts.size); ofpbuf_uninit(&ovnacts); - return; + return true; } /* Translate OVN match into table of OpenFlow matches. */ @@ -272,7 +366,7 @@ consider_logical_flow(struct controller_ctx *ctx, free(error); ovnacts_free(ovnacts.data, ovnacts.size); ofpbuf_uninit(&ovnacts); - return; + return true; } struct lookup_port_aux aux = { @@ -288,10 +382,12 @@ consider_logical_flow(struct controller_ctx *ctx, expr_destroy(expr); if (hmap_is_empty(&matches)) { + VLOG_DBG("lflow "UUID_FMT" matches are empty, skip", + UUID_ARGS(&lflow->header_.uuid)); ovnacts_free(ovnacts.data, ovnacts.size); ofpbuf_uninit(&ovnacts); expr_matches_destroy(&matches); - return; + return true; } /* Encode OVN logical actions into OpenFlow. */ @@ -303,6 +399,7 @@ consider_logical_flow(struct controller_ctx *ctx, .is_switch = is_switch(ldp), .group_table = group_table, .meter_table = meter_table, + .lflow_uuid = lflow->header_.uuid, .pipeline = ingress ? OVNACT_P_INGRESS : OVNACT_P_EGRESS, .ingress_ptable = OFTABLE_LOG_INGRESS_PIPELINE, @@ -331,13 +428,18 @@ consider_logical_flow(struct controller_ctx *ctx, char buf[16]; snprintf(buf, sizeof(buf), "%"PRId64"_%"PRId64, dp_id, port_id); if (!sset_contains(local_lport_ids, buf)) { + VLOG_DBG("lflow "UUID_FMT + " port %s in match is not local, skip", + UUID_ARGS(&lflow->header_.uuid), + buf); continue; } } } if (!m->n) { ofctrl_add_flow(flow_table, ptable, lflow->priority, - lflow->header_.uuid.parts[0], &m->match, &ofpacts); + lflow->header_.uuid.parts[0], &m->match, &ofpacts, + &lflow->header_.uuid); } else { uint64_t conj_stubs[64 / 8]; struct ofpbuf conj; @@ -353,7 +455,7 @@ consider_logical_flow(struct controller_ctx *ctx, dst->n_clauses = src->n_clauses; } ofctrl_add_flow(flow_table, ptable, lflow->priority, 0, &m->match, - &conj); + &conj, &lflow->header_.uuid); ofpbuf_uninit(&conj); } } @@ -361,7 +463,7 @@ consider_logical_flow(struct controller_ctx *ctx, /* Clean up. */ expr_matches_destroy(&matches); ofpbuf_uninit(&ofpacts); - *conj_id_ofs += n_conjs; + return update_conj_id_ofs(conj_id_ofs, n_conjs); } static void @@ -377,9 +479,9 @@ put_load(const uint8_t *data, size_t len, } static void -consider_neighbor_flow(struct controller_ctx *ctx, - const struct sbrec_mac_binding *b, - struct hmap *flow_table) +consider_neighbor_flow(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, + const struct sbrec_mac_binding *b) { const struct sbrec_port_binding *pb = lport_lookup_by_name(ctx->ovnsb_idl, b->logical_port); @@ -421,26 +523,28 @@ consider_neighbor_flow(struct controller_ctx *ctx, uint64_t stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); put_load(mac.ea, sizeof mac.ea, MFF_ETH_DST, 0, 48, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, 0, &match, &ofpacts); + ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, 0, &match, &ofpacts, + &b->header_.uuid); ofpbuf_uninit(&ofpacts); } /* Adds an OpenFlow flow to flow tables for each MAC binding in the OVN * southbound database. */ static void -add_neighbor_flows(struct controller_ctx *ctx, - struct hmap *flow_table) +add_neighbor_flows(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx) { const struct sbrec_mac_binding *b; SBREC_MAC_BINDING_FOR_EACH (b, ctx->ovnsb_idl) { - consider_neighbor_flow(ctx, b, flow_table); + consider_neighbor_flow(flow_table, ctx, b); } } /* Translates logical flows in the Logical_Flow table in the OVN_SB database * into OpenFlow flows. See ovn-architecture(7) for more information. */ void -lflow_run(struct controller_ctx *ctx, +lflow_run(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, const struct sbrec_chassis *chassis, const struct chassis_index *chassis_index, const struct hmap *local_datapaths, @@ -448,17 +552,17 @@ lflow_run(struct controller_ctx *ctx, struct ovn_extend_table *meter_table, const struct shash *addr_sets, const struct shash *port_groups, - struct hmap *flow_table, struct sset *active_tunnels, - struct sset *local_lport_ids) + struct sset *local_lport_ids, + uint32_t *conj_id_ofs) { COVERAGE_INC(lflow_run); - add_logical_flows(ctx, chassis_index, local_datapaths, + add_logical_flows(flow_table, ctx, chassis_index, local_datapaths, group_table, meter_table, chassis, addr_sets, - port_groups, flow_table, active_tunnels, - local_lport_ids); - add_neighbor_flows(ctx, flow_table); + port_groups, active_tunnels, local_lport_ids, + conj_id_ofs); + add_neighbor_flows(flow_table, ctx); } void diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h index dcf2fe7..d407c2c 100644 --- a/ovn/controller/lflow.h +++ b/ovn/controller/lflow.h @@ -38,6 +38,7 @@ struct chassis_index; struct controller_ctx; struct ovn_extend_table; +struct ovn_desired_flow_table; struct hmap; struct sbrec_chassis; struct simap; @@ -62,7 +63,8 @@ struct uuid; #define LOG_PIPELINE_LEN 24 void lflow_init(void); -void lflow_run(struct controller_ctx *, +void lflow_run(struct ovn_desired_flow_table *, + struct controller_ctx *, const struct sbrec_chassis *chassis, const struct chassis_index *, const struct hmap *local_datapaths, @@ -70,9 +72,21 @@ void lflow_run(struct controller_ctx *, struct ovn_extend_table *meter_table, const struct shash *addr_sets, const struct shash *port_groups, - struct hmap *flow_table, struct sset *active_tunnels, - struct sset *local_lport_ids); + struct sset *local_lport_ids, + uint32_t *conj_id_ofs); +bool lflow_handle_changed_flows(struct ovn_desired_flow_table *, + struct controller_ctx *ctx, + const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + const struct hmap *local_datapaths, + struct ovn_extend_table *group_table, + struct ovn_extend_table *extend_table, + const struct shash *addr_sets, + const struct shash *port_groups, + struct sset *active_tunnels, + struct sset *local_lport_ids, + uint32_t *conj_id_ofs); void lflow_destroy(void); #endif /* ovn/lflow.h */ diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 134f0e5..dda486d 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -20,6 +20,7 @@ #include "dp-packet.h" #include "flow.h" #include "hash.h" +#include "hindex.h" #include "lflow.h" #include "ofctrl.h" #include "openflow/openflow.h" @@ -52,7 +53,8 @@ VLOG_DEFINE_THIS_MODULE(ofctrl); /* An OpenFlow flow. */ struct ovn_flow { - struct hmap_node hmap_node; /* For match based hashing. */ + struct hmap_node match_hmap_node; /* For match based hashing. */ + struct hindex_node uuid_hindex_node; /* For uuid based hashing. */ struct ovs_list list_node; /* For handling lists of flows. */ /* Key. */ @@ -61,14 +63,16 @@ struct ovn_flow { struct minimatch match; /* Data. */ + struct uuid sb_uuid; struct ofpact *ofpacts; size_t ofpacts_len; uint64_t cookie; }; -static uint32_t ovn_flow_hash(const struct ovn_flow *); +static uint32_t ovn_flow_match_hash(const struct ovn_flow *); static struct ovn_flow *ovn_flow_lookup(struct hmap *flow_table, - const struct ovn_flow *target); + const struct ovn_flow *target, + bool cmp_sb_uuid); static char *ovn_flow_to_string(const struct ovn_flow *); static void ovn_flow_log(const struct ovn_flow *, const char *action); static void ovn_flow_destroy(struct ovn_flow *); @@ -146,6 +150,10 @@ static struct ovn_extend_table *meters; * S_CLEAR_FLOWS or S_UPDATE_FLOWS, this is really the option we have. */ static enum mf_field_id mff_ovn_geneve; +/* Indicates if flows need to be reinstalled for scenarios when ovs + * is restarted, even if there is no change in the desired flow table. */ +static bool need_reinstall_flows; + static ovs_be32 queue_msg(struct ofpbuf *); static struct ofpbuf *encode_flow_mod(struct ofputil_flow_mod *); @@ -154,8 +162,8 @@ static struct ofpbuf *encode_group_mod(const struct ofputil_group_mod *); static struct ofpbuf *encode_meter_mod(const struct ofputil_meter_mod *); -static void ovn_flow_table_clear(struct hmap *flow_table); -static void ovn_flow_table_destroy(struct hmap *flow_table); +static void ovn_installed_flow_table_clear(void); +static void ovn_installed_flow_table_destroy(void); static void ofctrl_recv(const struct ofp_header *, enum ofptype); @@ -375,6 +383,7 @@ run_S_CLEAR_FLOWS(void) { VLOG_DBG("clearing all flows"); + need_reinstall_flows = true; /* Send a flow_mod to delete all flows. */ struct ofputil_flow_mod fm = { .table_id = OFPTT_ALL, @@ -384,9 +393,6 @@ run_S_CLEAR_FLOWS(void) queue_msg(encode_flow_mod(&fm)); minimatch_destroy(&fm.match); - /* Clear installed_flows, to match the state of the switch. */ - ovn_flow_table_clear(&installed_flows); - /* Send a group_mod to delete all groups. */ struct ofputil_group_mod gm; memset(&gm, 0, sizeof gm); @@ -397,6 +403,9 @@ run_S_CLEAR_FLOWS(void) queue_msg(encode_group_mod(&gm)); ofputil_uninit_group_mod(&gm); + /* Clear installed_flows, to match the state of the switch. */ + ovn_installed_flow_table_clear(); + /* Clear existing groups, to match the state of the switch. */ if (groups) { ovn_extend_table_clear(groups, true); @@ -580,7 +589,7 @@ void ofctrl_destroy(void) { rconn_destroy(swconn); - ovn_flow_table_destroy(&installed_flows); + ovn_installed_flow_table_destroy(); rconn_packet_counter_destroy(tx_counter); expr_symtab_destroy(&symtab); shash_destroy(&symtab); @@ -632,14 +641,17 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type) * the OpenFlow table numbered 'table_id' with the given 'priority' and * OpenFlow 'cookie'. The caller retains ownership of 'match' and 'actions'. * + * The flow is also added to a hash index based on sb_uuid. + * * This just assembles the desired flow table in memory. Nothing is actually * sent to the switch until a later call to ofctrl_put(). * * The caller should initialize its own hmap to hold the flows. */ void -ofctrl_add_flow(struct hmap *desired_flows, +ofctrl_add_flow(struct ovn_desired_flow_table *flow_table, uint8_t table_id, uint16_t priority, uint64_t cookie, - const struct match *match, const struct ofpbuf *actions) + const struct match *match, const struct ofpbuf *actions, + const struct uuid *sb_uuid) { struct ovn_flow *f = xmalloc(sizeof *f); f->table_id = table_id; @@ -647,10 +659,14 @@ ofctrl_add_flow(struct hmap *desired_flows, minimatch_init(&f->match, match); f->ofpacts = xmemdup(actions->data, actions->size); f->ofpacts_len = actions->size; - f->hmap_node.hash = ovn_flow_hash(f); + f->sb_uuid = *sb_uuid; + f->match_hmap_node.hash = ovn_flow_match_hash(f); + f->uuid_hindex_node.hash = uuid_hash(&f->sb_uuid); f->cookie = cookie; - if (ovn_flow_lookup(desired_flows, f)) { + ovn_flow_log(f, "ofctrl_add_flow"); + + if (ovn_flow_lookup(&flow_table->match_flow_table, f, true)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); if (!VLOG_DROP_DBG(&rl)) { char *s = ovn_flow_to_string(f); @@ -662,19 +678,44 @@ ofctrl_add_flow(struct hmap *desired_flows, return; } - hmap_insert(desired_flows, &f->hmap_node, f->hmap_node.hash); + hmap_insert(&flow_table->match_flow_table, &f->match_hmap_node, + f->match_hmap_node.hash); + hindex_insert(&flow_table->uuid_flow_table, &f->uuid_hindex_node, + f->uuid_hindex_node.hash); +} + +/* Removes a bundles of flows from the flow table. */ +void +ofctrl_remove_flows(struct ovn_desired_flow_table *flow_table, + const struct uuid *sb_uuid) +{ + struct ovn_flow *f, *next; + HINDEX_FOR_EACH_WITH_HASH_SAFE (f, next, uuid_hindex_node, + uuid_hash(sb_uuid), + &flow_table->uuid_flow_table) { + if (uuid_equals(&f->sb_uuid, sb_uuid)) { + ovn_flow_log(f, "ofctrl_remove_flow"); + hmap_remove(&flow_table->match_flow_table, + &f->match_hmap_node); + hindex_remove(&flow_table->uuid_flow_table, &f->uuid_hindex_node); + ovn_flow_destroy(f); + } + } + + /* remove any related group and meter info */ + ovn_extend_table_remove_desired(groups, sb_uuid); + ovn_extend_table_remove_desired(meters, sb_uuid); } /* ovn_flow. */ -/* Returns a hash of the key in 'f'. */ +/* Returns a hash of the match key in 'f'. */ static uint32_t -ovn_flow_hash(const struct ovn_flow *f) +ovn_flow_match_hash(const struct ovn_flow *f) { return hash_2words((f->table_id << 16) | f->priority, minimatch_hash(&f->match, 0)); - } /* Duplicate an ovn_flow structure. */ @@ -687,23 +728,28 @@ ofctrl_dup_flow(struct ovn_flow *src) minimatch_clone(&dst->match, &src->match); dst->ofpacts = xmemdup(src->ofpacts, src->ofpacts_len); dst->ofpacts_len = src->ofpacts_len; - dst->hmap_node.hash = ovn_flow_hash(dst); + dst->sb_uuid = src->sb_uuid; + dst->match_hmap_node.hash = ovn_flow_match_hash(dst); + dst->uuid_hindex_node.hash = uuid_hash(&src->sb_uuid); return dst; } /* Finds and returns an ovn_flow in 'flow_table' whose key is identical to * 'target''s key, or NULL if there is none. */ static struct ovn_flow * -ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target) +ovn_flow_lookup(struct hmap *flow_table, const struct ovn_flow *target, + bool cmp_sb_uuid) { struct ovn_flow *f; - HMAP_FOR_EACH_WITH_HASH (f, hmap_node, target->hmap_node.hash, + HMAP_FOR_EACH_WITH_HASH (f, match_hmap_node, target->match_hmap_node.hash, flow_table) { if (f->table_id == target->table_id && f->priority == target->priority && minimatch_equal(&f->match, &target->match)) { - return f; + if (!cmp_sb_uuid || uuid_equals(&target->sb_uuid, &f->sb_uuid)) { + return f; + } } } return NULL; @@ -713,6 +759,7 @@ static char * ovn_flow_to_string(const struct ovn_flow *f) { struct ds s = DS_EMPTY_INITIALIZER; + ds_put_format(&s, "sb_uuid="UUID_FMT", ", UUID_ARGS(&f->sb_uuid)); ds_put_format(&s, "table_id=%"PRIu8", ", f->table_id); ds_put_format(&s, "priority=%"PRIu16", ", f->priority); minimatch_format(&f->match, NULL, NULL, &s, OFP_DEFAULT_PRIORITY); @@ -743,22 +790,48 @@ ovn_flow_destroy(struct ovn_flow *f) } /* Flow tables of struct ovn_flow. */ +void +ovn_desired_flow_table_init(struct ovn_desired_flow_table *flow_table) +{ + hmap_init(&flow_table->match_flow_table); + hindex_init(&flow_table->uuid_flow_table); +} + +void +ovn_desired_flow_table_clear(struct ovn_desired_flow_table *flow_table) +{ + struct ovn_flow *f, *next; + HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, + &flow_table->match_flow_table) { + hmap_remove(&flow_table->match_flow_table, &f->match_hmap_node); + hindex_remove(&flow_table->uuid_flow_table, &f->uuid_hindex_node); + ovn_flow_destroy(f); + } +} + +void +ovn_desired_flow_table_destroy(struct ovn_desired_flow_table *flow_table) +{ + ovn_desired_flow_table_clear(flow_table); + hmap_destroy(&flow_table->match_flow_table); + hindex_destroy(&flow_table->uuid_flow_table); +} static void -ovn_flow_table_clear(struct hmap *flow_table) +ovn_installed_flow_table_clear(void) { struct ovn_flow *f, *next; - HMAP_FOR_EACH_SAFE (f, next, hmap_node, flow_table) { - hmap_remove(flow_table, &f->hmap_node); + HMAP_FOR_EACH_SAFE (f, next, match_hmap_node, &installed_flows) { + hmap_remove(&installed_flows, &f->match_hmap_node); ovn_flow_destroy(f); } } static void -ovn_flow_table_destroy(struct hmap *flow_table) +ovn_installed_flow_table_destroy(void) { - ovn_flow_table_clear(flow_table); - hmap_destroy(flow_table); + ovn_installed_flow_table_clear(); + hmap_destroy(&installed_flows); } /* Flow table update. */ @@ -823,7 +896,7 @@ add_ct_flush_zone(uint16_t zone_id, struct ovs_list *msgs) * in the correct state and not backlogged with existing flow_mods. (Our * criteria for being backlogged appear very conservative, but the socket * between ovn-controller and OVS provides some buffering.) */ -bool +static bool ofctrl_can_put(void) { if (state != S_UPDATE_FLOWS @@ -838,9 +911,7 @@ ofctrl_can_put(void) * with ofctrl_add_flow(). * * Replaces the group table and meter table on the switch, if possible, by the - * contents of 'groups->desired'. Regardless of whether the group table - * is updated, this deletes all the groups from the 'groups->desired' and frees - * them. (The hmap itself isn't destroyed.) + * contents of 'desired'. * * Sends conntrack flush messages to each zone in 'pending_ct_zones' that * is in the CT_ZONE_OF_QUEUED state and then moves the zone into the @@ -848,16 +919,42 @@ ofctrl_can_put(void) * * This should be called after ofctrl_run() within the main loop. */ void -ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, - int64_t nb_cfg) +ofctrl_put(struct ovn_desired_flow_table *flow_table, + struct shash *pending_ct_zones, + int64_t nb_cfg, + bool flow_changed) { + static bool skipped_last_time = false; + static int64_t old_nb_cfg = 0; + bool need_put = false; + if (flow_changed || skipped_last_time || need_reinstall_flows) { + need_put = true; + } else if (nb_cfg != old_nb_cfg) { + /* nb_cfg changed since last ofctrl_put() call */ + if (cur_cfg == old_nb_cfg) { + /* we were up-to-date already, so just update with the + * new nb_cfg */ + cur_cfg = nb_cfg; + } else { + need_put = true; + } + } + + old_nb_cfg = nb_cfg; + + if (!need_put) { + VLOG_DBG("ofctrl_put not needed"); + return; + } if (!ofctrl_can_put()) { - ovn_flow_table_clear(flow_table); - ovn_extend_table_clear(groups, false); - ovn_extend_table_clear(meters, false); + VLOG_DBG("ofctrl_put can't be performed"); + skipped_last_time = true; return; } + skipped_last_time = false; + need_reinstall_flows = false; + /* OpenFlow messages to send to the switch to bring it up-to-date. */ struct ovs_list msgs = OVS_LIST_INITIALIZER(&msgs); @@ -921,8 +1018,9 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, * longer desired, delete them; if any of them should have different * actions, update them. */ struct ovn_flow *i, *next; - HMAP_FOR_EACH_SAFE (i, next, hmap_node, &installed_flows) { - struct ovn_flow *d = ovn_flow_lookup(flow_table, i); + HMAP_FOR_EACH_SAFE (i, next, match_hmap_node, &installed_flows) { + struct ovn_flow *d = ovn_flow_lookup(&flow_table->match_flow_table, + i, false); if (!d) { /* Installed flow is no longer desirable. Delete it from the * switch and from installed_flows. */ @@ -935,9 +1033,13 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, add_flow_mod(&fm, &msgs); ovn_flow_log(i, "removing installed"); - hmap_remove(&installed_flows, &i->hmap_node); + hmap_remove(&installed_flows, &i->match_hmap_node); ovn_flow_destroy(i); } else { + if (!uuid_equals(&i->sb_uuid, &d->sb_uuid)) { + /* Update installed flow's UUID. */ + i->sb_uuid = d->sb_uuid; + } if (!ofpacts_equal(i->ofpacts, i->ofpacts_len, d->ofpacts, d->ofpacts_len)) { /* Update actions in installed flow. */ @@ -954,38 +1056,37 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, /* Replace 'i''s actions by 'd''s. */ free(i->ofpacts); - i->ofpacts = d->ofpacts; + i->ofpacts = xmemdup(d->ofpacts, d->ofpacts_len); i->ofpacts_len = d->ofpacts_len; - d->ofpacts = NULL; - d->ofpacts_len = 0; } - hmap_remove(flow_table, &d->hmap_node); - ovn_flow_destroy(d); } } - /* The previous loop removed from 'flow_table' all of the flows that are - * already installed. Thus, any flows remaining in 'flow_table' need to - * be added to the flow table. */ + /* Iterate through the desired flows and add those that aren't found + * in the installed flow table. */ struct ovn_flow *d; - HMAP_FOR_EACH_SAFE (d, next, hmap_node, flow_table) { - /* Send flow_mod to add flow. */ - struct ofputil_flow_mod fm = { - .match = d->match, - .priority = d->priority, - .table_id = d->table_id, - .ofpacts = d->ofpacts, - .ofpacts_len = d->ofpacts_len, - .new_cookie = htonll(d->cookie), - .command = OFPFC_ADD, - }; - add_flow_mod(&fm, &msgs); - ovn_flow_log(d, "adding installed"); - - /* Move 'd' from 'flow_table' to installed_flows. */ - hmap_remove(flow_table, &d->hmap_node); - hmap_insert(&installed_flows, &d->hmap_node, d->hmap_node.hash); + HMAP_FOR_EACH (d, match_hmap_node, &flow_table->match_flow_table) { + i = ovn_flow_lookup(&installed_flows, d, false); + if (!i) { + /* Send flow_mod to add flow. */ + struct ofputil_flow_mod fm = { + .match = d->match, + .priority = d->priority, + .table_id = d->table_id, + .ofpacts = d->ofpacts, + .ofpacts_len = d->ofpacts_len, + .new_cookie = htonll(d->cookie), + .command = OFPFC_ADD, + }; + add_flow_mod(&fm, &msgs); + ovn_flow_log(d, "adding installed"); + + /* Copy 'd' from 'flow_table' to installed_flows. */ + struct ovn_flow *new_node = ofctrl_dup_flow(d); + hmap_insert(&installed_flows, &new_node->match_hmap_node, + new_node->match_hmap_node.hash); + } } /* Iterate through the installed groups from previous runs. If they @@ -1010,11 +1111,11 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, } free(group_string); ofputil_uninit_group_mod(&gm); - ovn_extend_table_remove(groups, installed); + ovn_extend_table_remove_existing(groups, installed); } - /* Move the contents of groups->desired to groups->existing. */ - ovn_extend_table_move(groups); + /* Sync the contents of groups->desired to groups->existing. */ + ovn_extend_table_sync(groups); /* Iterate through the installed meters from previous runs. If they * are not needed delete them. */ @@ -1037,11 +1138,11 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, free(error); } free(meter_string); - ovn_extend_table_remove(meters, m_installed); + ovn_extend_table_remove_existing(meters, m_installed); } - /* Move the contents of meters->desired to meters->existing. */ - ovn_extend_table_move(meters); + /* Sync the contents of meters->desired to meters->existing. */ + ovn_extend_table_sync(meters); if (!ovs_list_is_empty(&msgs)) { /* Add a barrier to the list of messages. */ diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h index 45081e5..587eca5 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -21,6 +21,7 @@ #include "openvswitch/meta-flow.h" #include "ovsdb-idl.h" +#include "hindex.h" struct controller_ctx; struct ovn_extend_table; @@ -30,15 +31,24 @@ struct ofpbuf; struct ovsrec_bridge; struct shash; +struct ovn_desired_flow_table { + /* Hash map flow table using flow match conditions as hash key.*/ + struct hmap match_flow_table; + + /* SB uuid index for the nodes in match_flow_table.*/ + struct hindex uuid_flow_table; +}; + /* Interface for OVN main loop. */ void ofctrl_init(struct ovn_extend_table *group_table, struct ovn_extend_table *meter_table); void ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones); enum mf_field_id ofctrl_get_mf_field_id(void); -bool ofctrl_can_put(void); -void ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, - int64_t nb_cfg); +void ofctrl_put(struct ovn_desired_flow_table *, + struct shash *pending_ct_zones, + int64_t nb_cfg, + bool flow_changed); void ofctrl_wait(void); void ofctrl_destroy(void); int64_t ofctrl_get_cur_cfg(void); @@ -52,8 +62,15 @@ char *ofctrl_inject_pkt(const struct ovsrec_bridge *br_int, const struct shash *port_groups); /* Flow table interfaces to the rest of ovn-controller. */ -void ofctrl_add_flow(struct hmap *desired_flows, uint8_t table_id, +void ofctrl_add_flow(struct ovn_desired_flow_table *, uint8_t table_id, uint16_t priority, uint64_t cookie, - const struct match *, const struct ofpbuf *ofpacts); + const struct match *, const struct ofpbuf *ofpacts, + const struct uuid *); + +void ofctrl_remove_flows(struct ovn_desired_flow_table *, const struct uuid *); + +void ovn_desired_flow_table_init(struct ovn_desired_flow_table *); +void ovn_desired_flow_table_clear(struct ovn_desired_flow_table *); +void ovn_desired_flow_table_destroy(struct ovn_desired_flow_table *); #endif /* ovn/ofctrl.h */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index e390afd..7f81c93 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -747,11 +747,13 @@ en_runtime_data_run(struct engine_node *node) struct ed_type_flow_output { /* desired flows */ - struct hmap flow_table; + struct ovn_desired_flow_table flow_table; /* group ids for load balancing */ struct ovn_extend_table group_table; /* meter ids for QoS */ struct ovn_extend_table meter_table; + /* conjunction id offset */ + uint32_t conj_id_ofs; }; static void @@ -759,9 +761,10 @@ en_flow_output_init(struct engine_node *node) { struct ed_type_flow_output *data = (struct ed_type_flow_output *)node->data; - hmap_init(&data->flow_table); + ovn_desired_flow_table_init(&data->flow_table); ovn_extend_table_init(&data->group_table); ovn_extend_table_init(&data->meter_table); + data->conj_id_ofs = 1; } static void @@ -769,7 +772,7 @@ en_flow_output_cleanup(struct engine_node *node) { struct ed_type_flow_output *data = (struct ed_type_flow_output *)node->data; - hmap_destroy(&data->flow_table); + ovn_desired_flow_table_destroy(&data->flow_table); ovn_extend_table_destroy(&data->group_table); ovn_extend_table_destroy(&data->meter_table); } @@ -803,29 +806,75 @@ en_flow_output_run(struct engine_node *node) struct ed_type_flow_output *fo = (struct ed_type_flow_output *)node->data; - struct hmap *flow_table = &fo->flow_table; + struct ovn_desired_flow_table *flow_table = &fo->flow_table; struct ovn_extend_table *group_table = &fo->group_table; struct ovn_extend_table *meter_table = &fo->meter_table; + uint32_t *conj_id_ofs = &fo->conj_id_ofs; static bool first_run = true; if (first_run) { first_run = false; } else { - hmap_clear(flow_table); + ovn_desired_flow_table_clear(flow_table); + ovn_extend_table_clear(group_table, false /* desired */); + ovn_extend_table_clear(meter_table, false /* desired */); } - lflow_run(ctx, chassis, + *conj_id_ofs = 1; + lflow_run(flow_table, ctx, chassis, chassis_index, local_datapaths, group_table, - meter_table, addr_sets, port_groups, flow_table, - active_tunnels, local_lport_ids); + meter_table, addr_sets, port_groups, active_tunnels, + local_lport_ids, conj_id_ofs); enum mf_field_id mff_ovn_geneve = ofctrl_get_mf_field_id(); - physical_run(ctx, mff_ovn_geneve, + physical_run(flow_table, ctx, mff_ovn_geneve, br_int, chassis, ct_zones, - flow_table, local_datapaths, local_lports, + local_datapaths, local_lports, chassis_index, active_tunnels); + + node->changed = true; +} + +static bool +flow_output_sb_logical_flow_handler(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)engine_get_input( + "runtime_data", node)->data; + struct hmap *local_datapaths = &data->local_datapaths; + struct sset *local_lport_ids = &data->local_lport_ids; + struct sset *active_tunnels = &data->active_tunnels; + struct chassis_index *chassis_index = &data->chassis_index; + struct shash *addr_sets = &data->addr_sets; + struct shash *port_groups = &data->port_groups; + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + + + const struct sbrec_chassis *chassis = NULL; + if (chassis_id) { + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + } + + ovs_assert(br_int && chassis); + + struct ed_type_flow_output *fo = + (struct ed_type_flow_output *)node->data; + struct ovn_desired_flow_table *flow_table = &fo->flow_table; + struct ovn_extend_table *group_table = &fo->group_table; + struct ovn_extend_table *meter_table = &fo->meter_table; + uint32_t *conj_id_ofs = &fo->conj_id_ofs; + + bool handled = lflow_handle_changed_flows(flow_table, ctx, chassis, + chassis_index, local_datapaths, group_table, meter_table, + addr_sets, port_groups, active_tunnels, local_lport_ids, + conj_id_ofs); + node->changed = true; + return handled; } int @@ -911,13 +960,11 @@ main(int argc, char *argv[]) engine_add_input(&en_flow_output, &en_sb_chassis, NULL); engine_add_input(&en_flow_output, &en_sb_encap, NULL); - engine_add_input(&en_flow_output, &en_sb_address_set, NULL); - engine_add_input(&en_flow_output, &en_sb_port_group, NULL); engine_add_input(&en_flow_output, &en_sb_multicast_group, NULL); engine_add_input(&en_flow_output, &en_sb_datapath_binding, NULL); engine_add_input(&en_flow_output, &en_sb_port_binding, NULL); engine_add_input(&en_flow_output, &en_sb_mac_binding, NULL); - engine_add_input(&en_flow_output, &en_sb_logical_flow, NULL); + engine_add_input(&en_flow_output, &en_sb_logical_flow, flow_output_sb_logical_flow_handler); engine_add_input(&en_flow_output, &en_sb_dhcp_options, NULL); engine_add_input(&en_flow_output, &en_sb_dhcpv6_options, NULL); engine_add_input(&en_flow_output, &en_sb_dns, NULL); @@ -928,6 +975,7 @@ main(int argc, char *argv[]) engine_add_input(&en_runtime_data, &en_sb_chassis, NULL); engine_add_input(&en_runtime_data, &en_sb_address_set, NULL); + engine_add_input(&en_runtime_data, &en_sb_port_group, NULL); engine_add_input(&en_runtime_data, &en_sb_datapath_binding, NULL); engine_add_input(&en_runtime_data, &en_sb_port_binding, NULL); engine_add_input(&en_runtime_data, &en_sb_gateway_chassis, NULL); @@ -945,6 +993,7 @@ main(int argc, char *argv[]) uint64_t engine_run_id = 0; uint64_t old_engine_run_id = 0; + /* Main loop. */ exiting = false; while (!exiting) { @@ -981,33 +1030,30 @@ main(int argc, char *argv[]) patch_run(&ctx, br_int, chassis); encaps_run(&ctx, br_int, chassis_id); - if (ofctrl_can_put()) { - stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, - time_msec()); - engine_run(&en_flow_output, ++engine_run_id); - stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME, - time_msec()); - - if (ctx.ovs_idl_txn) { - commit_ct_zones(br_int, &ed_runtime_data.pending_ct_zones); - bfd_run(&ctx, br_int, chassis, - &ed_runtime_data.local_datapaths, - &ed_runtime_data.chassis_index); - } - if (en_flow_output.changed) { - ofctrl_put(&ed_flow_output.flow_table, - &ed_runtime_data.pending_ct_zones, - get_nb_cfg(ctx.ovnsb_idl)); - } + stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, + time_msec()); + engine_run(&en_flow_output, ++engine_run_id); + stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME, + time_msec()); + if (ctx.ovs_idl_txn) { + commit_ct_zones(br_int, &ed_runtime_data.pending_ct_zones); + bfd_run(&ctx, br_int, chassis, + &ed_runtime_data.local_datapaths, + &ed_runtime_data.chassis_index); } - + ofctrl_put(&ed_flow_output.flow_table, + &ed_runtime_data.pending_ct_zones, + get_nb_cfg(ctx.ovnsb_idl), + en_flow_output.changed); pinctrl_run(&ctx, br_int, chassis, &ed_runtime_data.chassis_index, &ed_runtime_data.local_datapaths, &ed_runtime_data.active_tunnels); - update_sb_monitors(ctx.ovnsb_idl, chassis, - &ed_runtime_data.local_lports, - &ed_runtime_data.local_datapaths); + if (en_runtime_data.changed) { + update_sb_monitors(ctx.ovnsb_idl, chassis, + &ed_runtime_data.local_lports, + &ed_runtime_data.local_datapaths); + } } if (old_engine_run_id == engine_run_id) { diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index b3aa27a..8ae14cd 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -44,6 +44,9 @@ VLOG_DEFINE_THIS_MODULE(physical); +/* UUID to identify OF flows not associated with ovsdb rows. */ +static struct uuid *hc_uuid = NULL; + void physical_register_ovs_idl(struct ovsdb_idl *ovs_idl) { @@ -188,9 +191,10 @@ get_zone_ids(const struct sbrec_port_binding *binding, } static void -put_local_common_flows(uint32_t dp_key, uint32_t port_key, +put_local_common_flows(struct ovn_desired_flow_table *flow_table, + uint32_t dp_key, uint32_t port_key, bool nested_container, const struct zone_ids *zone_ids, - struct ofpbuf *ofpacts_p, struct hmap *flow_table) + struct ofpbuf *ofpacts_p) { struct match match; @@ -224,7 +228,7 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, /* Resubmit to table 34. */ put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); /* Table 34, Priority 100. * ======================= @@ -239,7 +243,7 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, port_key); match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key); ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); /* Table 64, Priority 100. * ======================= @@ -263,7 +267,7 @@ put_local_common_flows(uint32_t dp_key, uint32_t port_key, put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p); put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p)); ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); } static void @@ -291,7 +295,8 @@ load_logical_ingress_metadata(const struct sbrec_port_binding *binding, } static void -consider_port_binding(struct controller_ctx *ctx, +consider_port_binding(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, const struct simap *ct_zones, const struct chassis_index *chassis_index, @@ -299,8 +304,7 @@ consider_port_binding(struct controller_ctx *ctx, struct hmap *local_datapaths, const struct sbrec_port_binding *binding, const struct sbrec_chassis *chassis, - struct ofpbuf *ofpacts_p, - struct hmap *flow_table) + struct ofpbuf *ofpacts_p) { uint32_t dp_key = binding->datapath->tunnel_key; uint32_t port_key = binding->tunnel_key; @@ -328,8 +332,8 @@ consider_port_binding(struct controller_ctx *ctx, } struct zone_ids binding_zones = get_zone_ids(binding, ct_zones); - put_local_common_flows(dp_key, port_key, false, &binding_zones, - ofpacts_p, flow_table); + put_local_common_flows(flow_table, dp_key, port_key, false, + &binding_zones, ofpacts_p); match_init_catchall(&match); ofpbuf_clear(ofpacts_p); @@ -356,7 +360,7 @@ consider_port_binding(struct controller_ctx *ctx, ofpact_finish_CLONE(ofpacts_p, &clone); ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); return; } @@ -424,7 +428,7 @@ consider_port_binding(struct controller_ctx *ctx, } ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); goto out; } @@ -522,8 +526,8 @@ consider_port_binding(struct controller_ctx *ctx, */ struct zone_ids zone_ids = get_zone_ids(binding, ct_zones); - put_local_common_flows(dp_key, port_key, nested_container, &zone_ids, - ofpacts_p, flow_table); + put_local_common_flows(flow_table, dp_key, port_key, nested_container, + &zone_ids, ofpacts_p); /* Table 0, Priority 150 and 100. * ============================== @@ -567,7 +571,7 @@ consider_port_binding(struct controller_ctx *ctx, /* Resubmit to first logical ingress pipeline table. */ put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p); ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, - tag ? 150 : 100, 0, &match, ofpacts_p); + tag ? 150 : 100, 0, &match, ofpacts_p, hc_uuid); if (!tag && (!strcmp(binding->type, "localnet") || !strcmp(binding->type, "l2gateway"))) { @@ -577,7 +581,7 @@ consider_port_binding(struct controller_ctx *ctx, * action. */ ofpbuf_pull(ofpacts_p, ofpacts_orig_size); match_set_dl_tci_masked(&match, 0, htons(VLAN_CFI)); - ofctrl_add_flow(flow_table, 0, 100, 0, &match, ofpacts_p); + ofctrl_add_flow(flow_table, 0, 100, 0, &match, ofpacts_p, hc_uuid); } /* Table 65, Priority 100. @@ -605,7 +609,7 @@ consider_port_binding(struct controller_ctx *ctx, ofpact_put_STRIP_VLAN(ofpacts_p); } ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); } else if (!tun && !is_ha_remote) { /* Remote port connected by localnet port */ /* Table 33, priority 100. @@ -628,7 +632,7 @@ consider_port_binding(struct controller_ctx *ctx, /* Resubmit to table 33. */ put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p); ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); } else { /* Remote port connected by tunnel */ @@ -719,7 +723,7 @@ consider_port_binding(struct controller_ctx *ctx, ofpact_finish_BUNDLE(ofpacts_p, &bundle); } ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); } out: if (gateway_chassis) { @@ -728,14 +732,14 @@ out: } static void -consider_mc_group(enum mf_field_id mff_ovn_geneve, +consider_mc_group(struct ovn_desired_flow_table *flow_table, + enum mf_field_id mff_ovn_geneve, const struct simap *ct_zones, struct hmap *local_datapaths, const struct sbrec_chassis *chassis, const struct sbrec_multicast_group *mc, struct ofpbuf *ofpacts_p, - struct ofpbuf *remote_ofpacts_p, - struct hmap *flow_table) + struct ofpbuf *remote_ofpacts_p) { uint32_t dp_key = mc->datapath->tunnel_key; if (!get_local_datapath(local_datapaths, dp_key)) { @@ -811,7 +815,7 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p); + &match, ofpacts_p, hc_uuid); } /* Table 32, priority 100. @@ -849,7 +853,7 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, put_resubmit(OFTABLE_LOCAL_OUTPUT, remote_ofpacts_p); } ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0, - &match, remote_ofpacts_p); + &match, remote_ofpacts_p, hc_uuid); } } sset_destroy(&remote_chassis); @@ -867,16 +871,22 @@ update_ofports(struct simap *old, struct simap *new) } void -physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, +physical_run(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct simap *ct_zones, - struct hmap *flow_table, struct hmap *local_datapaths, + struct hmap *local_datapaths, const struct sset *local_lports, struct chassis_index *chassis_index, struct sset *active_tunnels) { + if (!hc_uuid) { + hc_uuid = xmalloc(sizeof(struct uuid)); + uuid_generate(hc_uuid); + } + /* This bool tracks physical mapping changes. */ bool physical_map_changed = false; @@ -995,10 +1005,10 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, * 64 for logical-to-physical translation. */ const struct sbrec_port_binding *binding; SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) { - consider_port_binding(ctx, mff_ovn_geneve, ct_zones, + consider_port_binding(flow_table, ctx, mff_ovn_geneve, ct_zones, chassis_index, active_tunnels, local_datapaths, binding, chassis, - &ofpacts, flow_table); + &ofpacts); } /* Handle output to multicast groups, in tables 32 and 33. */ @@ -1006,8 +1016,9 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, struct ofpbuf remote_ofpacts; ofpbuf_init(&remote_ofpacts, 0); SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) { - consider_mc_group(mff_ovn_geneve, ct_zones, local_datapaths, chassis, - mc, &ofpacts, &remote_ofpacts, flow_table); + consider_mc_group(flow_table, mff_ovn_geneve, ct_zones, + local_datapaths, chassis, mc, &ofpacts, + &remote_ofpacts); } ofpbuf_uninit(&remote_ofpacts); @@ -1048,7 +1059,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, 0, &match, - &ofpacts); + &ofpacts, hc_uuid); } /* Add flows for VXLAN encapsulations. Due to the limited amount of @@ -1081,7 +1092,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, &ofpacts); ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 100, 0, &match, - &ofpacts); + &ofpacts, hc_uuid); } } @@ -1102,7 +1113,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, - &match, &ofpacts); + &match, &ofpacts, hc_uuid); /* Table 32, priority 150. * ======================= @@ -1116,7 +1127,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, - &match, &ofpacts); + &match, &ofpacts, hc_uuid); /* Table 32, priority 150. * ======================= @@ -1139,7 +1150,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, pb->tunnel_key); match_set_metadata(&match, htonll(pb->datapath->tunnel_key)); ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, - &match, &ofpacts); + &match, &ofpacts, hc_uuid); } } @@ -1151,7 +1162,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, match_init_catchall(&match); ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOCAL_OUTPUT, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 0, 0, &match, &ofpacts); + ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 0, 0, &match, &ofpacts, + hc_uuid); /* Table 34, Priority 0. * ======================= @@ -1166,7 +1178,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, } put_resubmit(OFTABLE_LOG_EGRESS_PIPELINE, &ofpacts); ofctrl_add_flow(flow_table, OFTABLE_CHECK_LOOPBACK, 0, 0, &match, - &ofpacts); + &ofpacts, hc_uuid); /* Table 64, Priority 0. * ======================= @@ -1176,7 +1188,8 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, match_init_catchall(&match); ofpbuf_clear(&ofpacts); put_resubmit(OFTABLE_LOG_TO_PHY, &ofpacts); - ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, 0, 0, &match, &ofpacts); + ofctrl_add_flow(flow_table, OFTABLE_SAVE_INPORT, 0, 0, &match, &ofpacts, + hc_uuid); ofpbuf_uninit(&ofpacts); diff --git a/ovn/controller/physical.h b/ovn/controller/physical.h index f8dbb49..7274825 100644 --- a/ovn/controller/physical.h +++ b/ovn/controller/physical.h @@ -43,11 +43,12 @@ struct chassis_index; #define OVN_GENEVE_LEN 4 void physical_register_ovs_idl(struct ovsdb_idl *); -void physical_run(struct controller_ctx *, enum mf_field_id mff_ovn_geneve, +void physical_run(struct ovn_desired_flow_table *, + struct controller_ctx *, enum mf_field_id mff_ovn_geneve, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct simap *ct_zones, - struct hmap *flow_table, struct hmap *local_datapaths, + struct hmap *local_datapaths, const struct sset *local_lports, struct chassis_index *chassis_index, struct sset *active_tunnels); diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index 0669cc1..20c8267 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -1049,7 +1049,8 @@ encode_CT_LB(const struct ovnact_ct_lb *cl, recirc_table, zone_reg); } - table_id = ovn_extend_table_assign_id(ep->group_table, &ds); + table_id = ovn_extend_table_assign_id(ep->group_table, &ds, + ep->lflow_uuid); ds_destroy(&ds); if (table_id == EXT_TABLE_ID_INVALID) { return; @@ -2228,7 +2229,8 @@ encode_SET_METER(const struct ovnact_set_meter *cl, cl->rate); } - table_id = ovn_extend_table_assign_id(ep->meter_table, &ds); + table_id = ovn_extend_table_assign_id(ep->meter_table, &ds, + ep->lflow_uuid); if (table_id == EXT_TABLE_ID_INVALID) { ds_destroy(&ds); return; diff --git a/ovn/lib/extend-table.c b/ovn/lib/extend-table.c index e18713b..e4dd52a 100644 --- a/ovn/lib/extend-table.c +++ b/ovn/lib/extend-table.c @@ -17,6 +17,7 @@ #include #include "bitmap.h" #include "hash.h" +#include "lib/uuid.h" #include "openvswitch/vlog.h" #include "ovn/lib/extend-table.h" @@ -89,9 +90,10 @@ ovn_extend_table_clear(struct ovn_extend_table *table, bool existing) } } +/* Remove an entry from existing table */ void -ovn_extend_table_remove(struct ovn_extend_table *table, - struct ovn_extend_table_info *existing) +ovn_extend_table_remove_existing(struct ovn_extend_table *table, + struct ovn_extend_table_info *existing) { /* Remove 'existing' from 'groups->existing' */ hmap_remove(&table->existing, &existing->hmap_node); @@ -102,21 +104,50 @@ ovn_extend_table_remove(struct ovn_extend_table *table, free(existing); } +/* Remove entries in desired table that are created by the lflow_uuid */ void -ovn_extend_table_move(struct ovn_extend_table *table) +ovn_extend_table_remove_desired(struct ovn_extend_table *table, + const struct uuid *lflow_uuid) +{ + struct ovn_extend_table_info *e, *next_e; + HMAP_FOR_EACH_SAFE (e, next_e, hmap_node, &table->desired) { + if (uuid_equals(&e->lflow_uuid, lflow_uuid)) { + hmap_remove(&table->desired, &e->hmap_node); + ds_destroy(&e->info); + if (e->new_table_id) { + bitmap_set0(table->table_ids, e->table_id); + } + free(e); + } + } + +} + +static struct ovn_extend_table_info* +ovn_extend_info_clone(struct ovn_extend_table_info *source) +{ + struct ovn_extend_table_info *clone = xmalloc(sizeof *clone); + ds_clone(&clone->info, &source->info); + clone->table_id = source->table_id; + clone->new_table_id = source->new_table_id; + clone->hmap_node.hash = source->hmap_node.hash; + clone->lflow_uuid = source->lflow_uuid; + return clone; +} + +void +ovn_extend_table_sync(struct ovn_extend_table *table) { struct ovn_extend_table_info *desired, *next; - /* Move the contents of desired to existing. */ + /* Copy the contents of desired to existing. */ HMAP_FOR_EACH_SAFE (desired, next, hmap_node, &table->desired) { - hmap_remove(&table->desired, &desired->hmap_node); - if (!ovn_extend_table_lookup(&table->existing, desired)) { - hmap_insert(&table->existing, &desired->hmap_node, - desired->hmap_node.hash); - } else { - ds_destroy(&desired->info); - free(desired); + desired->new_table_id = false; + struct ovn_extend_table_info *clone = + ovn_extend_info_clone(desired); + hmap_insert(&table->existing, &clone->hmap_node, + clone->hmap_node.hash); } } } @@ -124,7 +155,8 @@ ovn_extend_table_move(struct ovn_extend_table *table) /* Assign a new table ID for the table information from the bitmap. * If it already exists, return the old ID. */ uint32_t -ovn_extend_table_assign_id(struct ovn_extend_table *table, struct ds *ds) +ovn_extend_table_assign_id(struct ovn_extend_table *table, struct ds *ds, + struct uuid lflow_uuid) { uint32_t table_id = 0, hash; struct ovn_extend_table_info *table_info; @@ -133,7 +165,8 @@ ovn_extend_table_assign_id(struct ovn_extend_table *table, struct ds *ds) /* Check whether we have non installed but allocated group_id. */ HMAP_FOR_EACH_WITH_HASH (table_info, hmap_node, hash, &table->desired) { - if (!strcmp(ds_cstr(&table_info->info), ds_cstr(ds))) { + if (!strcmp(ds_cstr(&table_info->info), ds_cstr(ds)) && + table_info->new_table_id) { return table_info->table_id; } } @@ -165,6 +198,7 @@ ovn_extend_table_assign_id(struct ovn_extend_table *table, struct ds *ds) table_info->table_id = table_id; table_info->hmap_node.hash = hash; table_info->new_table_id = new_table_id; + table_info->lflow_uuid = lflow_uuid; hmap_insert(&table->desired, &table_info->hmap_node, table_info->hmap_node.hash); diff --git a/ovn/lib/extend-table.h b/ovn/lib/extend-table.h index d9ae549..7473d4a 100644 --- a/ovn/lib/extend-table.h +++ b/ovn/lib/extend-table.h @@ -23,6 +23,7 @@ #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" +#include "openvswitch/uuid.h" /* Used to manage expansion tables associated with Flow table, * such as the Group Table or Meter Table. */ @@ -37,6 +38,7 @@ struct ovn_extend_table { struct ovn_extend_table_info { struct hmap_node hmap_node; struct ds info; /* Details string for the table entity. */ + struct uuid lflow_uuid; uint32_t table_id; bool new_table_id; /* 'True' if 'table_id' was reserved from * ovn_extend_table's 'table_ids' bitmap. */ @@ -51,14 +53,18 @@ struct ovn_extend_table_info *ovn_extend_table_lookup( void ovn_extend_table_clear(struct ovn_extend_table *, bool); -void ovn_extend_table_remove(struct ovn_extend_table *, - struct ovn_extend_table_info *); +void ovn_extend_table_remove_existing(struct ovn_extend_table *, + struct ovn_extend_table_info *); -/* Move the contents of desired to existing. */ -void ovn_extend_table_move(struct ovn_extend_table *); +void ovn_extend_table_remove_desired(struct ovn_extend_table *, + const struct uuid *lflow_uuid); + +/* Copy the contents of desired to existing. */ +void ovn_extend_table_sync(struct ovn_extend_table *); uint32_t ovn_extend_table_assign_id(struct ovn_extend_table *, - struct ds *); + struct ds *, + struct uuid lflow_uuid); /* Iterates 'DESIRED' through all of the 'ovn_extend_table_info's in * 'TABLE'->desired that are not in 'TABLE'->existing. (The loop body From patchwork Thu May 24 22:10:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920132 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="shHkMjzC"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNv44jrfz9s0q for ; Fri, 25 May 2018 08:13:36 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id BAFC2D91; Thu, 24 May 2018 22:10:28 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 9E720D67 for ; Thu, 24 May 2018 22:10:24 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f41.google.com (mail-pg0-f41.google.com [74.125.83.41]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 131EE6D3 for ; Thu, 24 May 2018 22:10:24 +0000 (UTC) Received: by mail-pg0-f41.google.com with SMTP id 15-v6so1056317pge.2 for ; Thu, 24 May 2018 15:10:23 -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; bh=H00atMnAqaRst0t72BZmvSBov+5nwsFXXQrmhtaAQ98=; b=shHkMjzCC/XX/2e1EPm4xyz/YIBvNQA+le+5hllwHH44GVBVPZ2Q2vRTs3mVyoo2b4 TVB+v9Er54UJCMOujF2qTme1NXfOVBbo/mxPLXXWU/uB3eZYgUf3YldpNrEWs+H8XuHO N9tQC0Jr4e7i5Vm5ci8ZyB79GVLr+VtwNrcWiT+O2XAtd64LTnHAy8JG9fPG2+/AqnlQ JF1fvGt6pI3RxhHb/TNWu1fjsWJmfZ1S5EUhmf5LU3gbmGKVy9Aq1D62nMR6JQvmWtQq MHkuiSD1OzFu3TWZgKQ1gKljteFpf2+UK3AH/OdR8wQ+9uY9gB2K4XUl5ptgex8pc5HU xDCQ== 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; bh=H00atMnAqaRst0t72BZmvSBov+5nwsFXXQrmhtaAQ98=; b=EWdD7Q3FBdscDJUY/q9dDC9VBP3zmdotJzsB5yTorcjobLvyc2cJiVCm/ASXE83MIU FpkLxzwtUZARMrqEAVZ7i4bmKGVf4OfPiwoTI4A9Ho1VqTeo0xLTFDdMtf49zCHO9JgA qbAq5U+vbWgtIj0Jxz+KCRW0Beq54E/ZhRisseiX5j2NKspaNrhRE3Gk0knmNuja329L eospWEf8UwXX04oXJd4+fWfo/Uw+Uag8Gnk+kGuJNsT/GgWC6a9pSQon0uvyWM0EG7Ek ylt6mk5QhcywGBZZSY3GtWS+iJn2vfw7CgJtUmYVmIaor7UkTs6XMvLiDvX5LU6QUvlM SvBQ== X-Gm-Message-State: ALKqPwdn1hm6J9NeWN83IVLDK9Be1UGKnW89MrW6r5ECFxBdZSU37FmF Nee63YOEw+JvbOBYt7RElxUHkA== X-Google-Smtp-Source: AB8JxZolMrzRCMGrHnOQocqYalvKZqx/h6Bh1yzEw4aiacHhEse330DjuAQ4iIz/V13n3GmZ5RgCiA== X-Received: by 2002:a63:79ce:: with SMTP id u197-v6mr7299349pgc.284.1527199823400; Thu, 24 May 2018 15:10:23 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:22 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:48 -0700 Message-Id: <1527199851-107563-8-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 07/10] ovn-controller: runtime_data change handler for SB port-binding X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Evaluates change for SB port-binding in runtime_data node. If the port-binding change has no impact for the runtime_data it will not trigger runtime_data change. Signed-off-by: Han Zhou --- ovn/controller/binding.c | 92 +++++++++++++++++++++++++++++++++++++++++ ovn/controller/binding.h | 4 ++ ovn/controller/ovn-controller.c | 28 ++++++++++++- 3 files changed, 123 insertions(+), 1 deletion(-) diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c index 84ff4d6..0c5b47b 100644 --- a/ovn/controller/binding.c +++ b/ovn/controller/binding.c @@ -580,6 +580,98 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, hmap_destroy(&qos_map); } +static bool +is_our_chassis(const struct chassis_index *chassis_index, + struct sset *active_tunnels, + const struct sbrec_chassis *chassis_rec, + const struct sbrec_port_binding *binding_rec, + struct shash *lport_to_iface, + struct sset *local_lports) +{ + const struct ovsrec_interface *iface_rec + = shash_find_data(lport_to_iface, binding_rec->logical_port); + struct ovs_list *gateway_chassis = NULL; + + bool our_chassis = false; + if (iface_rec + || (binding_rec->parent_port && binding_rec->parent_port[0] && + sset_contains(local_lports, binding_rec->parent_port))) { + /* This port is in our chassis unless it is a localport. */ + if (strcmp(binding_rec->type, "localport")) { + our_chassis = true; + } + } else if (!strcmp(binding_rec->type, "l2gateway")) { + const char *chassis_id = smap_get(&binding_rec->options, + "l2gateway-chassis"); + our_chassis = chassis_id && !strcmp(chassis_id, chassis_rec->name); + } else if (!strcmp(binding_rec->type, "chassisredirect")) { + gateway_chassis = gateway_chassis_get_ordered(binding_rec, + chassis_index); + if (gateway_chassis && + gateway_chassis_contains(gateway_chassis, chassis_rec)) { + + our_chassis = gateway_chassis_is_active( + gateway_chassis, chassis_rec, active_tunnels); + + } + gateway_chassis_destroy(gateway_chassis); + } else if (!strcmp(binding_rec->type, "l3gateway")) { + const char *chassis_id = smap_get(&binding_rec->options, + "l3gateway-chassis"); + our_chassis = chassis_id && !strcmp(chassis_id, chassis_rec->name); + } else if (!strcmp(binding_rec->type, "localnet")) { + our_chassis = false; + } + + return our_chassis; +} + +/* Returns true if port-binding changes potentially require flow changes on + * the current chassis. Returns false if we are sure there is no impact. */ +bool +binding_evaluate_port_binding_changes( + struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, + const struct sbrec_chassis *chassis_rec, + const struct chassis_index *chassis_index, + struct sset *active_tunnels, + struct sset *local_lports) +{ + if (!chassis_rec) { + return true; + } + + const struct sbrec_port_binding *binding_rec; + struct shash lport_to_iface = SHASH_INITIALIZER(&lport_to_iface); + struct sset egress_ifaces = SSET_INITIALIZER(&egress_ifaces); + if (br_int) { + get_local_iface_ids(br_int, &lport_to_iface, local_lports, + &egress_ifaces); + } + SBREC_PORT_BINDING_FOR_EACH_TRACKED (binding_rec, ctx->ovnsb_idl) { + /* XXX: currently OVSDB change tracking doesn't support getting old + * data when the operation is update, so if a port-binding moved from + * this chassis to another, we would not know it with this check. + * However, if the port is unbound from this chassis, the local ovsdb + * interface table will be updated, which will trigger recompute. + * If the port is still bound on this chassis, then below check + * is_our_chassis() will take care that case. */ + if (binding_rec->chassis == chassis_rec) { + return true; + } + if (is_our_chassis(chassis_index, + active_tunnels, chassis_rec, binding_rec, + &lport_to_iface, + local_lports) + || !strcmp(binding_rec->type, "patch") + || !strcmp(binding_rec->type, "localport") + || !strcmp(binding_rec->type, "vtep") + || !strcmp(binding_rec->type, "localnet")) { + return true; + } + } + return false; +} + /* Returns true if the database is all cleaned up, false if more work is * required. */ bool diff --git a/ovn/controller/binding.h b/ovn/controller/binding.h index 89fc2ec..ea4fb81 100644 --- a/ovn/controller/binding.h +++ b/ovn/controller/binding.h @@ -34,5 +34,9 @@ void binding_run(struct controller_ctx *, const struct ovsrec_bridge *br_int, struct sset *active_tunnels, struct hmap *local_datapaths, struct sset *local_lports, struct sset *local_lport_ids); bool binding_cleanup(struct controller_ctx *, const struct sbrec_chassis *); +bool binding_evaluate_port_binding_changes( + struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, + const struct sbrec_chassis *, const struct chassis_index *, + struct sset *active_tunnels, struct sset *local_lports); #endif /* ovn/binding.h */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 7f81c93..215146b 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -745,6 +745,32 @@ en_runtime_data_run(struct engine_node *node) node->changed = true; } +static bool +runtime_data_sb_port_binding_handler(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)node->data; + struct sset *local_lports = &data->local_lports; + struct sset *active_tunnels = &data->active_tunnels; + struct chassis_index *chassis_index = &data->chassis_index; + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + ovs_assert(br_int && chassis_id); + const struct sbrec_chassis *chassis = NULL; + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + ovs_assert(chassis); + + bool changed = binding_evaluate_port_binding_changes( + ctx, br_int, chassis, + chassis_index, active_tunnels, + local_lports); + + return !changed; +} + struct ed_type_flow_output { /* desired flows */ struct ovn_desired_flow_table flow_table; @@ -977,7 +1003,7 @@ main(int argc, char *argv[]) engine_add_input(&en_runtime_data, &en_sb_address_set, NULL); engine_add_input(&en_runtime_data, &en_sb_port_group, NULL); engine_add_input(&en_runtime_data, &en_sb_datapath_binding, NULL); - engine_add_input(&en_runtime_data, &en_sb_port_binding, NULL); + engine_add_input(&en_runtime_data, &en_sb_port_binding, runtime_data_sb_port_binding_handler); engine_add_input(&en_runtime_data, &en_sb_gateway_chassis, NULL); engine_init(&en_flow_output); From patchwork Thu May 24 22:10:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920135 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Xdq5uccQ"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNwh2Yt5z9s0q for ; Fri, 25 May 2018 08:15:00 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C6D5BD98; Thu, 24 May 2018 22:10:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 44103D4A for ; Thu, 24 May 2018 22:10:27 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f47.google.com (mail-pl0-f47.google.com [209.85.160.47]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 03E206C1 for ; Thu, 24 May 2018 22:10:24 +0000 (UTC) Received: by mail-pl0-f47.google.com with SMTP id m24-v6so1861170pls.11 for ; Thu, 24 May 2018 15:10:24 -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; bh=xeNco84uWmBqWx03Qh9Tzz42Vu0XMgSLTchkGYPv1os=; b=Xdq5uccQXMyo1LQwxO6dCBC6sRMkRqWU3BHR1/viQCFlOxkEc4jLGdc6kfMaUu+vk1 IOLO9RvUp0eEGLKVU8nWCubWlcrgwv3R5T7/5f/G+NczFjMSBdllsoaivB6fS8WEMAT+ GaC8h57axiEMK3T7zZRrEGVXPtZTN+BlftOHwaZAjZOwMkAEphU4LKOxDtOP+YAcnmya r6LrQeef+7IKj+ZFzQKiGxJKppYlmrTYITCUd4jCcmlP36BMRiJPVsJbP6Z2JOPM0Gfg vWLdnR0wFui5cCh+oBMcY9pnQMUONnMk0IkDVnry0PQ7UYTJ7FDad0jkjUN8Kaa0taLW pzIg== 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; bh=xeNco84uWmBqWx03Qh9Tzz42Vu0XMgSLTchkGYPv1os=; b=k17SSCPzJEw4FbjQRcXY1BAWa/MFU4Xgpbf1HxG8sfbiqj9kW10JM58rs+JzNTIZba R3zVSx6ArIi7oTiQx90eazANvRI5ijsLtCpuYEQbVl6TG5l6boBGFNe1EErk7irB/RTn 9XMdMP8QmA5QlNwIfXk1GJ4GMbIv6vG3HyrHZbGODcawBB4zvdP29jKjiLkC7TN3RmMA BV9QIO4dOGp4QoCDB3rEWB5h/ylPiBpZc60xQfOq8M/OmHZlp6E2VfoZUyicLQuhJUIu e8OPMCDLmmFVRYAGra/EI0eOQyHR3iIh5TngZTJLDpJOo+Q0LiTWy1MSsnKeMncOFIoS 0b/A== X-Gm-Message-State: ALKqPwef8yoa6kjAXDBYtYQKq4qNA5URVURPUFw+LY0jykpqB9OZCsXF wr6DjJRSP470z/it2wTlKbflUA== X-Google-Smtp-Source: AB8JxZpLVhF4986oBJE+AURBeWGzki6QG895bgSZwnPas3phVhfUaWTsC30DHynDX0k3Na9I6KVgvQ== X-Received: by 2002:a17:902:b409:: with SMTP id x9-v6mr9343155plr.180.1527199824199; Thu, 24 May 2018 15:10:24 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:23 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:49 -0700 Message-Id: <1527199851-107563-9-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 08/10] ovn-controller: port-binding incremental processing for physical flows X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch implements change handler for port-binding in flow_output for physical flows computing, so that physical flow computing will be incremental. This patch together with previous incremental processing engine related changes supports incremental processing for lflow changes and port-binding changes of lports on other HVs, which are the most common scenarios in a cloud where workloads come up and down. In ovn-scale-test env [1], the total execution time of creating and binding 10k ports on 1k HVs with 40 lswitches and 8 lrouters (5 lswitches/lrouter), decreased from 3h40m to 1h50m because of the less CPU on HVs. The CPU time of ovn-controller for additional 500 lports creating and binding (on top of already existed 10k lports) decreased 90% comparing with master. Latency for end-to-end operations of one extra port on top of the 10k lports, start from port-creation until all flows installation on all related HVs is also improved significantly from 20.6s to 7.3s. [1] https://github.com/openvswitch/ovn-scale-test Signed-off-by: Han Zhou --- ovn/controller/ovn-controller.c | 76 ++++++++++++++++++++++- ovn/controller/physical.c | 129 +++++++++++++++++++++++++++++----------- ovn/controller/physical.h | 8 +++ 3 files changed, 178 insertions(+), 35 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 215146b..e939d03 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -903,6 +903,80 @@ flow_output_sb_logical_flow_handler(struct engine_node *node) return handled; } +static bool +flow_output_sb_port_binding_handler(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)engine_get_input( + "runtime_data", node)->data; + struct hmap *local_datapaths = &data->local_datapaths; + struct sset *active_tunnels = &data->active_tunnels; + struct chassis_index *chassis_index = &data->chassis_index; + struct simap *ct_zones = &data->ct_zones; + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + + + const struct sbrec_chassis *chassis = NULL; + if (chassis_id) { + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + } + + ovs_assert(br_int && chassis); + + struct ed_type_flow_output *fo = + (struct ed_type_flow_output *)node->data; + struct ovn_desired_flow_table *flow_table = &fo->flow_table; + + /* XXX: now we handles port-binding changes for physical flow processing + * only, but port-binding change can have impact to logical flow + * processing, too, in below circumstances: + * + * - When a port-binding for a lport is inserted/deleted but the lflow + * using that lport doesn't change. + * + * This is likely to happen only when the lport name is used by ACL + * match condition, which is specified by user. Even in that case, when + * port is actually bound on the chassis it will trigger recompute on + * that chassis since ovs interface is updated. So the only situation + * this would have real impact is when user defines an ACL that includes + * lport that is not the ingress/egress lport, e.g.: + * + * to-lport 1000 'outport=="A" && inport=="B"' allow-related + * + * If "B" is created and bound after the ACL is created, the ACL may not + * take effect on the chassis where "A" is bound, until a recompute is + * triggered there later. + * + * - When is_chassis_resident is used in lflow. In this case the port + * binding is patch type, since this condition is used only for lrouter + * ports. In current "runtime_data" handling, port-binding changes of + * patch ports always trigger recomputing. So it is fine even if we do + * not handle it here. + * + * - When a mac-binding doesn't change but the port-binding related to + * that mac-binding is deleted. In this case the neighbor flow generated + * for the mac-binding should be deleted. This would not cause any real + * issue for now, since mac-binding change triggers recomputing. + * + * To address the above issues, we will need to maintain a mapping between + * lport names and the lflows that uses them, and reprocess the related + * lflows when a port-binding corresponding to a lport name changes. + */ + + enum mf_field_id mff_ovn_geneve = ofctrl_get_mf_field_id(); + physical_handle_port_binding_changes(flow_table, + ctx, mff_ovn_geneve, + chassis, ct_zones, + local_datapaths, + chassis_index, active_tunnels); + + node->changed = true; + return true; +} + int main(int argc, char *argv[]) { @@ -988,7 +1062,7 @@ main(int argc, char *argv[]) engine_add_input(&en_flow_output, &en_sb_encap, NULL); engine_add_input(&en_flow_output, &en_sb_multicast_group, NULL); engine_add_input(&en_flow_output, &en_sb_datapath_binding, NULL); - engine_add_input(&en_flow_output, &en_sb_port_binding, NULL); + engine_add_input(&en_flow_output, &en_sb_port_binding, flow_output_sb_port_binding_handler); engine_add_input(&en_flow_output, &en_sb_mac_binding, NULL); engine_add_input(&en_flow_output, &en_sb_logical_flow, flow_output_sb_logical_flow_handler); engine_add_input(&en_flow_output, &en_sb_dhcp_options, NULL); diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index 8ae14cd..d860686 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -360,7 +360,7 @@ consider_port_binding(struct ovn_desired_flow_table *flow_table, ofpact_finish_CLONE(ofpacts_p, &clone); ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, - &match, ofpacts_p, hc_uuid); + &match, ofpacts_p, &binding->header_.uuid); return; } @@ -428,7 +428,7 @@ consider_port_binding(struct ovn_desired_flow_table *flow_table, } ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p, hc_uuid); + &match, ofpacts_p, &binding->header_.uuid); goto out; } @@ -571,7 +571,8 @@ consider_port_binding(struct ovn_desired_flow_table *flow_table, /* Resubmit to first logical ingress pipeline table. */ put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p); ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, - tag ? 150 : 100, 0, &match, ofpacts_p, hc_uuid); + tag ? 150 : 100, 0, &match, ofpacts_p, + &binding->header_.uuid); if (!tag && (!strcmp(binding->type, "localnet") || !strcmp(binding->type, "l2gateway"))) { @@ -581,7 +582,8 @@ consider_port_binding(struct ovn_desired_flow_table *flow_table, * action. */ ofpbuf_pull(ofpacts_p, ofpacts_orig_size); match_set_dl_tci_masked(&match, 0, htons(VLAN_CFI)); - ofctrl_add_flow(flow_table, 0, 100, 0, &match, ofpacts_p, hc_uuid); + ofctrl_add_flow(flow_table, 0, 100, 0, &match, ofpacts_p, + &binding->header_.uuid); } /* Table 65, Priority 100. @@ -609,7 +611,7 @@ consider_port_binding(struct ovn_desired_flow_table *flow_table, ofpact_put_STRIP_VLAN(ofpacts_p); } ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, - &match, ofpacts_p, hc_uuid); + &match, ofpacts_p, &binding->header_.uuid); } else if (!tun && !is_ha_remote) { /* Remote port connected by localnet port */ /* Table 33, priority 100. @@ -632,7 +634,7 @@ consider_port_binding(struct ovn_desired_flow_table *flow_table, /* Resubmit to table 33. */ put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p); ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p, hc_uuid); + &match, ofpacts_p, &binding->header_.uuid); } else { /* Remote port connected by tunnel */ @@ -723,7 +725,7 @@ consider_port_binding(struct ovn_desired_flow_table *flow_table, ofpact_finish_BUNDLE(ofpacts_p, &bundle); } ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0, - &match, ofpacts_p, hc_uuid); + &match, ofpacts_p, &binding->header_.uuid); } out: if (gateway_chassis) { @@ -737,9 +739,7 @@ consider_mc_group(struct ovn_desired_flow_table *flow_table, const struct simap *ct_zones, struct hmap *local_datapaths, const struct sbrec_chassis *chassis, - const struct sbrec_multicast_group *mc, - struct ofpbuf *ofpacts_p, - struct ofpbuf *remote_ofpacts_p) + const struct sbrec_multicast_group *mc) { uint32_t dp_key = mc->datapath->tunnel_key; if (!get_local_datapath(local_datapaths, dp_key)) { @@ -765,8 +765,10 @@ consider_mc_group(struct ovn_desired_flow_table *flow_table, * would happen on every hypervisor in the multicast group, * effectively duplicating the packet.) */ - ofpbuf_clear(ofpacts_p); - ofpbuf_clear(remote_ofpacts_p); + struct ofpbuf ofpacts; + ofpbuf_init(&ofpacts, 0); + struct ofpbuf remote_ofpacts; + ofpbuf_init(&remote_ofpacts, 0); for (size_t i = 0; i < mc->n_ports; i++) { struct sbrec_port_binding *port = mc->ports[i]; @@ -780,20 +782,20 @@ consider_mc_group(struct ovn_desired_flow_table *flow_table, int zone_id = simap_get(ct_zones, port->logical_port); if (zone_id) { - put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p); + put_load(zone_id, MFF_LOG_CT_ZONE, 0, 32, &ofpacts); } if (!strcmp(port->type, "patch")) { put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, - remote_ofpacts_p); - put_resubmit(OFTABLE_CHECK_LOOPBACK, remote_ofpacts_p); + &remote_ofpacts); + put_resubmit(OFTABLE_CHECK_LOOPBACK, &remote_ofpacts); } else if (simap_contains(&localvif_to_ofport, (port->parent_port && *port->parent_port) ? port->parent_port : port->logical_port) || (!strcmp(port->type, "l3gateway") && port->chassis == chassis)) { - put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); - put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); + put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts); + put_resubmit(OFTABLE_CHECK_LOOPBACK, &ofpacts); } else if (port->chassis && !get_localnet_port(local_datapaths, mc->datapath->tunnel_key)) { /* Add remote chassis only when localnet port not exist, @@ -808,14 +810,14 @@ consider_mc_group(struct ovn_desired_flow_table *flow_table, * * Handle output to the local logical ports in the multicast group, if * any. */ - bool local_ports = ofpacts_p->size > 0; + bool local_ports = ofpacts.size > 0; if (local_ports) { /* Following delivery to local logical ports, restore the multicast * group as the logical output port. */ - put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); + put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, &ofpacts); ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, - &match, ofpacts_p, hc_uuid); + &match, &ofpacts, &mc->header_.uuid); } /* Table 32, priority 100. @@ -823,12 +825,12 @@ consider_mc_group(struct ovn_desired_flow_table *flow_table, * * Handle output to the remote chassis in the multicast group, if * any. */ - if (!sset_is_empty(&remote_chassis) || remote_ofpacts_p->size > 0) { - if (remote_ofpacts_p->size > 0) { + if (!sset_is_empty(&remote_chassis) || remote_ofpacts.size > 0) { + if (remote_ofpacts.size > 0) { /* Following delivery to logical patch ports, restore the * multicast group as the logical output port. */ put_load(mc->tunnel_key, MFF_LOG_OUTPORT, 0, 32, - remote_ofpacts_p); + &remote_ofpacts); } const char *chassis_name; @@ -842,20 +844,22 @@ consider_mc_group(struct ovn_desired_flow_table *flow_table, if (!prev || tun->type != prev->type) { put_encapsulation(mff_ovn_geneve, tun, mc->datapath, - mc->tunnel_key, remote_ofpacts_p); + mc->tunnel_key, &remote_ofpacts); prev = tun; } - ofpact_put_OUTPUT(remote_ofpacts_p)->port = tun->ofport; + ofpact_put_OUTPUT(&remote_ofpacts)->port = tun->ofport; } - if (remote_ofpacts_p->size) { + if (remote_ofpacts.size) { if (local_ports) { - put_resubmit(OFTABLE_LOCAL_OUTPUT, remote_ofpacts_p); + put_resubmit(OFTABLE_LOCAL_OUTPUT, &remote_ofpacts); } ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100, 0, - &match, remote_ofpacts_p, hc_uuid); + &match, &remote_ofpacts, &mc->header_.uuid); } } + ofpbuf_uninit(&ofpacts); + ofpbuf_uninit(&remote_ofpacts); sset_destroy(&remote_chassis); } @@ -870,6 +874,68 @@ update_ofports(struct simap *old, struct simap *new) return changed; } +static void +reconsider_mc_group_for_pb(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, + const struct sbrec_port_binding *pb, + const char *mc_name, + enum mf_field_id mff_ovn_geneve, + const struct sbrec_chassis *chassis, + const struct simap *ct_zones, + struct hmap *local_datapaths) +{ + const struct sbrec_multicast_group *mc + = mcgroup_lookup_by_dp_name(ctx->ovnsb_idl, pb->datapath, mc_name); + if (mc) { + ofctrl_remove_flows(flow_table, &mc->header_.uuid); + + consider_mc_group(flow_table, mff_ovn_geneve, ct_zones, + local_datapaths, chassis, mc); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "MC group %s is not found in datapath: "UUID_FMT, + mc_name, UUID_ARGS(&pb->datapath->header_.uuid)); + } +} + +void +physical_handle_port_binding_changes(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, + enum mf_field_id mff_ovn_geneve, + const struct sbrec_chassis *chassis, + const struct simap *ct_zones, + struct hmap *local_datapaths, + struct chassis_index *chassis_index, + struct sset *active_tunnels) +{ + const struct sbrec_port_binding *binding; + struct ofpbuf ofpacts; + ofpbuf_init(&ofpacts, 0); + SBREC_PORT_BINDING_FOR_EACH_TRACKED (binding, ctx->ovnsb_idl) { + if (sbrec_port_binding_is_deleted(binding)) { + ofctrl_remove_flows(flow_table, &binding->header_.uuid); + } else { + if (!sbrec_port_binding_is_new(binding)) { + ofctrl_remove_flows(flow_table, &binding->header_.uuid); + + reconsider_mc_group_for_pb(flow_table, + ctx, binding, "_MC_flood", + mff_ovn_geneve, chassis, + ct_zones, local_datapaths); + reconsider_mc_group_for_pb(flow_table, + ctx, binding, "_MC_unknown", + mff_ovn_geneve, chassis, + ct_zones, local_datapaths); + } + consider_port_binding(flow_table, ctx, mff_ovn_geneve, ct_zones, + chassis_index, active_tunnels, + local_datapaths, binding, chassis, + &ofpacts); + } + } + +} + void physical_run(struct ovn_desired_flow_table *flow_table, struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, @@ -1013,16 +1079,11 @@ physical_run(struct ovn_desired_flow_table *flow_table, /* Handle output to multicast groups, in tables 32 and 33. */ const struct sbrec_multicast_group *mc; - struct ofpbuf remote_ofpacts; - ofpbuf_init(&remote_ofpacts, 0); SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) { consider_mc_group(flow_table, mff_ovn_geneve, ct_zones, - local_datapaths, chassis, mc, &ofpacts, - &remote_ofpacts); + local_datapaths, chassis, mc); } - ofpbuf_uninit(&remote_ofpacts); - /* Table 0, priority 100. * ====================== * diff --git a/ovn/controller/physical.h b/ovn/controller/physical.h index 7274825..88c5cda 100644 --- a/ovn/controller/physical.h +++ b/ovn/controller/physical.h @@ -52,5 +52,13 @@ void physical_run(struct ovn_desired_flow_table *, const struct sset *local_lports, struct chassis_index *chassis_index, struct sset *active_tunnels); +void physical_handle_port_binding_changes(struct ovn_desired_flow_table *, + struct controller_ctx *, + enum mf_field_id mff_ovn_geneve, + const struct sbrec_chassis *, + const struct simap *ct_zones, + struct hmap *local_datapaths, + struct chassis_index *, + struct sset *active_tunnels); #endif /* ovn/physical.h */ From patchwork Thu May 24 22:10:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920133 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hxHS+FdE"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNvc4gBJz9s0q for ; Fri, 25 May 2018 08:14:04 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CCB7DD9E; Thu, 24 May 2018 22:10:29 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 30F8BD3B for ; Thu, 24 May 2018 22:10:26 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f42.google.com (mail-pl0-f42.google.com [209.85.160.42]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id BAD456DA for ; Thu, 24 May 2018 22:10:25 +0000 (UTC) Received: by mail-pl0-f42.google.com with SMTP id 30-v6so1858396pld.13 for ; Thu, 24 May 2018 15:10:25 -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; bh=xcqerSd0tsC/tFKcTGh7LOOCM8rBjsujOAwcnvR7dJc=; b=hxHS+FdEqC+dRPULXUVw2MhTe18ixf5UdiH0T+UoSoex+boQbRX5WnkuWfrdBzc1rY bXVn6X3++ldMO6JciQLlQqJQySwFk4PwtkPBqXDtbfW/AJMbgRCl7mJFPrntFUwEYQ4S vFy6dV70ocXiEPGc9yF8aAjATAeIsUxvaaI590C15b+DOL6lAJ5obdKNARbpl20PaEHT VvvW8sYHu/4lx0t21wLERUZu2NKQWJcF4rOse96iKwkW5t5X1XiluhuurTAAlbBbN8SV YG8W/zb8ZufbnE/Y9DsED8cCaJ31ICgzVbg+C/+7nMvDvQrRJkwKRaIK/19ffoLmB5JI CP0w== 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; bh=xcqerSd0tsC/tFKcTGh7LOOCM8rBjsujOAwcnvR7dJc=; b=ZX2DL3hwnjHX7vLU+RcvTu1q5G86lMx28bncOuXoDBcnTaTedGaAWxWQM8hkfkwwOU wcaEE4C0O7sxgan9Xz2Fs2XDTeEht3EOrgKGr42dgJuL/55PuJ7DTliUPBtbhyePTkpO lF37S8b9CLNZHsX+ksyI60ewEDSaWtRc9IixlMfB6CRqa0qs9EA2n2SzCPFpElVPPtqm uDrMHTN+4vUqG6vqQpvZrm405BXTa3rKpHAOVUGMn3h0lCxNCZFkSuHA4vYCOQfKpT4s jxn/LxCYs7sfQA6Pnw3IkUeneODUCSBP/QcD8O02zZJGxGFCRihi96S8krZMqYZn8MvJ YsSw== X-Gm-Message-State: ALKqPwcqfjZxcyktYlHVORBU5SQMbB82sYx2Nz9KwT+LVY59Xs1ZUckM jDcMJQPbYkaqDxuwQ9m3cFP1Ug== X-Google-Smtp-Source: AB8JxZpC+iVi/NTZWzCBKZJf2U9PSf+J5NFYQo4QZA/3o03XbRRMf9rLDBKOxMd+qzuFPdEVQISkYw== X-Received: by 2002:a17:902:4101:: with SMTP id e1-v6mr9166073pld.205.1527199825112; Thu, 24 May 2018 15:10:25 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:24 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:50 -0700 Message-Id: <1527199851-107563-10-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 09/10] ovn-controller: Avoid forced recompute when not needed X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Signed-off-by: Han Zhou --- ovn/controller/ovn-controller.c | 13 +++++++++---- ovn/lib/inc-proc-eng.c | 20 ++++++++++++++++++++ ovn/lib/inc-proc-eng.h | 4 ++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index e939d03..e4506c2 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -1157,10 +1157,15 @@ main(int argc, char *argv[]) } if (old_engine_run_id == engine_run_id) { - VLOG_DBG("engine did not run, force recompute next time: " - "br_int %p, chassis %p", br_int, chassis); - engine_set_force_recompute(true); - poll_immediate_wake(); + if (engine_need_run(&en_flow_output)) { + VLOG_DBG("engine did not run, force recompute next time: " + "br_int %p, chassis %p", br_int, chassis); + engine_set_force_recompute(true); + poll_immediate_wake(); + } else { + VLOG_DBG("engine did not run, and it was not needed either: " + "br_int %p, chassis %p", br_int, chassis); + } } else { engine_set_force_recompute(false); } diff --git a/ovn/lib/inc-proc-eng.c b/ovn/lib/inc-proc-eng.c index 8006acd..08f152e 100644 --- a/ovn/lib/inc-proc-eng.c +++ b/ovn/lib/inc-proc-eng.c @@ -139,3 +139,23 @@ engine_run(struct engine_node *node, uint64_t run_id) VLOG_DBG("node: %s, changed: %d", node->name, node->changed); } + +bool +engine_need_run(struct engine_node *node) +{ + size_t i; + + if (!node->n_inputs) { + node->run(node); + VLOG_DBG("input node: %s, changed: %d", node->name, node->changed); + return node->changed; + } + + for (i = 0; i < node->n_inputs; i++) { + if (engine_need_run(node->inputs[i].node)) { + return true; + } + } + + return false; +} diff --git a/ovn/lib/inc-proc-eng.h b/ovn/lib/inc-proc-eng.h index 8399321..17006f1 100644 --- a/ovn/lib/inc-proc-eng.h +++ b/ovn/lib/inc-proc-eng.h @@ -126,6 +126,10 @@ void engine_run(struct engine_node *, uint64_t run_id); * terminates. */ void engine_cleanup(struct engine_node *); +/* Check if engine needs to run, i.e. any change to be processed. */ +bool +engine_need_run(struct engine_node *); + /* Get the input node with for */ struct engine_node * engine_get_input(const char *input_name, struct engine_node *); From patchwork Thu May 24 22:10:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920134 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="b2iv8aIK"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNw92clDz9s15 for ; Fri, 25 May 2018 08:14:33 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CDD8BD9A; Thu, 24 May 2018 22:10:30 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E9531D4D for ; Thu, 24 May 2018 22:10:26 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f54.google.com (mail-pg0-f54.google.com [74.125.83.54]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 881946DA for ; Thu, 24 May 2018 22:10:26 +0000 (UTC) Received: by mail-pg0-f54.google.com with SMTP id p8-v6so1372263pgq.10 for ; Thu, 24 May 2018 15:10:26 -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; bh=JiQ9z3IYDmVjSSeffF9sCPm9eqbkAQGlHhGlrgdcXRE=; b=b2iv8aIKCN8nrDzwnUZpyKJD0jMRD5/jUOiLXV9h/d33/RRXeg2gjpIF47kBvYB8m0 E5Wa2doSR+I60Llxs759gi40xI79LKQccTmdrrrO4VoVti7uaX4pTx+N4VKUfQH6mbNu Oq5izGG27LItWASgHJO1vSoKh8NwsFYc0fXa+sUgIzsN8v7kgKeQbjNzFf6uRDg8IpQn ARXqdIDcHJrPQJkCd85H/NpiPy9aXB6+vYcRWLnc0PQuYJ4RV+0n7WPD3H5DUCsKlEoR WrXvt96bvobDN1Nju8tcf2NlRjQKQJIHBx6+97e9gjrrqRaubQgLJt0PQMWhknvRWGpo 53Dg== 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; bh=JiQ9z3IYDmVjSSeffF9sCPm9eqbkAQGlHhGlrgdcXRE=; b=l6uCGr0/BOVqIUaB1sE6LTj2bhcam7GYdssfki0W38EDatfXKNvQt9ils9uJeHUYwH ZMLLNhFy9lS+4m6f3ptzgsexu0n89ycktOSfAxU9rcm22sATNFFmerWU2xLOR5MS7hRh 2mdzlD6IUh8xEFjDjUBxdQO+3OM9MadPZWV6Ow2nb2rPcqTQUKM3lMSlNlzgcVWIEOjd j2VcSxHfTe29TrPhgW9+9jsojZC1gNKd+iGiV/ZpSXmmuVHIoUCgsnOq3Pt2zvTsT2D3 dJvMiI0uJv9YWRpBbl2GaGrwmeGtFfMHmV/SU3Img2jv2sDUqOUcuw8fvZZkqYHaQFqu NwGA== X-Gm-Message-State: ALKqPwfkN09xiGCuP8u50qdIxRBwJSBljQU+fDCG/JgzbQX1uGmX7J6S +pu+AoOhOieM3+r9Wk04RlmFZg== X-Google-Smtp-Source: AB8JxZqli2WedkPqHNpGikKbg+pYq81ZfvRXiV4dNl9m+DLDgbcPkbl/NlZc06dBgz3zCVGAOtxIdA== X-Received: by 2002:a65:4e03:: with SMTP id r3-v6mr7443354pgt.121.1527199825826; Thu, 24 May 2018 15:10:25 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:25 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:51 -0700 Message-Id: <1527199851-107563-11-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 10/10] ovn-controller: incremental processing for multicast group changes X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Signed-off-by: Han Zhou --- ovn/controller/ovn-controller.c | 37 ++++++++++++++++++++++++++++++++++++- ovn/controller/physical.c | 23 +++++++++++++++++++++++ ovn/controller/physical.h | 7 ++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index e4506c2..56902ff 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -977,6 +977,41 @@ flow_output_sb_port_binding_handler(struct engine_node *node) return true; } +static bool +flow_output_sb_multicast_group_handler(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)engine_get_input( + "runtime_data", node)->data; + struct hmap *local_datapaths = &data->local_datapaths; + struct simap *ct_zones = &data->ct_zones; + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + + + const struct sbrec_chassis *chassis = NULL; + if (chassis_id) { + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + } + + ovs_assert(br_int && chassis); + + struct ed_type_flow_output *fo = + (struct ed_type_flow_output *)node->data; + struct ovn_desired_flow_table *flow_table = &fo->flow_table; + + enum mf_field_id mff_ovn_geneve = ofctrl_get_mf_field_id(); + physical_handle_mc_group_changes(flow_table, + ctx, mff_ovn_geneve, + chassis, ct_zones, + local_datapaths); + node->changed = true; + return true; + +} + int main(int argc, char *argv[]) { @@ -1060,7 +1095,7 @@ main(int argc, char *argv[]) engine_add_input(&en_flow_output, &en_sb_chassis, NULL); engine_add_input(&en_flow_output, &en_sb_encap, NULL); - engine_add_input(&en_flow_output, &en_sb_multicast_group, NULL); + engine_add_input(&en_flow_output, &en_sb_multicast_group, flow_output_sb_multicast_group_handler); engine_add_input(&en_flow_output, &en_sb_datapath_binding, NULL); engine_add_input(&en_flow_output, &en_sb_port_binding, flow_output_sb_port_binding_handler); engine_add_input(&en_flow_output, &en_sb_mac_binding, NULL); diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index d860686..de75f4a 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -937,6 +937,29 @@ physical_handle_port_binding_changes(struct ovn_desired_flow_table *flow_table, } void +physical_handle_mc_group_changes(struct ovn_desired_flow_table *flow_table, + struct controller_ctx *ctx, + enum mf_field_id mff_ovn_geneve, + const struct sbrec_chassis *chassis, + const struct simap *ct_zones, + struct hmap *local_datapaths) +{ + const struct sbrec_multicast_group *mc; + SBREC_MULTICAST_GROUP_FOR_EACH_TRACKED (mc, ctx->ovnsb_idl) { + if (sbrec_multicast_group_is_deleted(mc)) { + ofctrl_remove_flows(flow_table, &mc->header_.uuid); + } else { + if (!sbrec_multicast_group_is_new(mc)) { + ofctrl_remove_flows(flow_table, &mc->header_.uuid); + } + consider_mc_group(flow_table, mff_ovn_geneve, ct_zones, + local_datapaths, chassis, mc); + } + } +} + + +void physical_run(struct ovn_desired_flow_table *flow_table, struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, const struct ovsrec_bridge *br_int, diff --git a/ovn/controller/physical.h b/ovn/controller/physical.h index 88c5cda..eb3f8df 100644 --- a/ovn/controller/physical.h +++ b/ovn/controller/physical.h @@ -60,5 +60,10 @@ void physical_handle_port_binding_changes(struct ovn_desired_flow_table *, struct hmap *local_datapaths, struct chassis_index *, struct sset *active_tunnels); - +void physical_handle_mc_group_changes(struct ovn_desired_flow_table *, + struct controller_ctx *ctx, + enum mf_field_id mff_ovn_geneve, + const struct sbrec_chassis *, + const struct simap *ct_zones, + struct hmap *local_datapaths); #endif /* ovn/physical.h */