From patchwork Mon Apr 16 20:14:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898911 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="O+vPO0zf"; 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 40Q04L0mwBz9s19 for ; Tue, 17 Apr 2018 06:15:30 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 55359DCE; Mon, 16 Apr 2018 20:15:11 +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 26ED3DC6 for ; Mon, 16 Apr 2018 20:15:10 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f176.google.com (mail-pf0-f176.google.com [209.85.192.176]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id E1EA5625 for ; Mon, 16 Apr 2018 20:15:08 +0000 (UTC) Received: by mail-pf0-f176.google.com with SMTP id h69so11046687pfe.13 for ; Mon, 16 Apr 2018 13:15:08 -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=TQJC7PlwAIyWgRpSWEACldKl75R0vpadDlJVIvdO7u0=; b=O+vPO0zf3kYPwtI6pi5IHDgPyzrx+YPD5QqecRMMk7w6ip2wnunSIk5HG71WGrbQeJ gzZP8//GGrK4l3YV34ywXxxUFKZ9NiypeHTCe53W5S19UYZTlksHPuM19dMkLBYYtCOP Z52SDRe0pyZywX7z8yQObPzUFekWrektVtvqA5ihHSqXWpBFTmYgmfSxpPBx3pbYoW3w PWMWPp5tT83rkPuYA75SZrxvoMicezWEVSpvXHiQefFdQdYBB1A9IEu7oxLNHJli2wNV ORw+i49YfRiBEPa12UV4lHBJAmrYK2KjJbF00g6TKMAR3b4t6y35hDDE2iQekd2tnS/8 MYXA== 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=TQJC7PlwAIyWgRpSWEACldKl75R0vpadDlJVIvdO7u0=; b=fsQm62cijVyip8Sa46i34sHLb/LE+k5ELj0TNAfiKOEjvX7xYAI4ElYbO69L6fpA1A LdVWNW4D6PzSxsRIV436k14+OXCtNWAj0bLiNIqjY+bV7uZT13i/CZDdv/+2qy1GLSaK MzyxN3Ozl0BLlJEf+EmV37b2hCsqjQM2eZs8b1pVbSEWEUfbvbfaz3KH3kOBYL6SZufN OOcuxggsKcWKeCnU5tMcYgWksZB3yzxYjlDXl5rm4aE+vYgmLARtmGA/tm/N/JxcxxVR OZz7mhxUhdZH3WhnxwYKbKse6xEcOE1IrwgSVVLoGQY9Dj9j4q/q0hvHwy2rZP7vn/Q5 R29Q== X-Gm-Message-State: ALQs6tBVCis9GV2tyWGFDtAdb1+jZWYaRCprOOT+YKVxLTrbWFIvUG2j yM1jOTP7gw7zPDQOsAXfb8d+AA== X-Google-Smtp-Source: AIpwx4+dY0G0WrJ42nUStG1YgUDfBXOaW9dJeTwqVobmu81Xx2eKuDcYsgTXnp3f8ZMnz677JMeoQg== X-Received: by 10.98.220.86 with SMTP id t83mr22791913pfg.60.1523909708020; Mon, 16 Apr 2018 13:15:08 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:07 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:16 -0700 Message-Id: <1523909665-27961-2-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 125 +++++++++++++++++++++++++++ ovn/lib/inc-proc-eng.h | 224 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 352 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..54c7fd6 --- /dev/null +++ b/ovn/lib/inc-proc-eng.c @@ -0,0 +1,125 @@ +/* + * 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); + } +} + +void +engine_run(struct engine_node *node, uint64_t run_id) +{ + if (node->run_id == run_id) { + return; + } + node->run_id = run_id; + + if (node->changed) { + node->changed = false; + } + if (!node->n_inputs) { + node->run(node); + VLOG_DBG("node: %s, changed: %d", node->name, node->changed); + return; + } + + size_t i; + + for (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 (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 (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..3e0ec16 --- /dev/null +++ b/ovn/lib/inc-proc-eng.h @@ -0,0 +1,224 @@ +/* + * 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 straighforward + * 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 straighforward 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 interations. 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 is 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 *node); + + /* Method to clean up data. It may be NULL. */ + void (*cleanup)(struct engine_node *node); + + /* Fully processing all inputs of this node and regenerate the data + * of this node */ + void (*run)(struct engine_node *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 *node); + +/* Execute the processing recursively, which should be called in the main + * loop. */ +void +engine_run(struct engine_node *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 *node); + +/* Get the input node with for */ +static inline 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; +} + +/* 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 */ +static inline void +engine_add_input(struct engine_node *node, struct engine_node *input, + bool (*change_handler)(struct engine_node *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 ++; +} + +/* 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 = NAME##_init, \ + .run = NAME##_run, \ + .cleanup = 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 \ +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 (*DB_NAME##_##TBL_NAME##_init)(struct engine_node *node) \ + = NULL; \ +static void (*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 Mon Apr 16 20:14:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898914 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="HwlK5Or0"; 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 40Q0701R63z9s1B for ; Tue, 17 Apr 2018 06:17:48 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CAEC9F09; Mon, 16 Apr 2018 20:15:17 +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 05D7DF2C for ; Mon, 16 Apr 2018 20:15:13 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id C8B0B573 for ; Mon, 16 Apr 2018 20:15:09 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id p6so11058998pfn.4 for ; Mon, 16 Apr 2018 13:15:09 -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=N/fd1ftRSaWCfwu2TCx32w6T3PUJ9co3zxcpVqsLW0E=; b=HwlK5Or02uAmXYe7CSL33F0uSpPzCZUEeV5+lEda3UonUAePAflJf89VySovxI6oO2 QXvqUuQ07nw4rqFYUJg5WGmeGFUW5Mggw/D9sYOcj54dY5Q4a8FgHW/bRRp5pNfldEWq RYnWhrV44e9DB/vG3YLNWKgxwcvWBtwuLFvK+I39LlZpKUXxhZvY8H4twzJTjj+YSPdH 6p0qW9rTDmFp8Z26Kupi9dnUrB982d+JP0AWA2ob4b0/y2v4xHr9lD2W3YrNPur4WXwW CI/V1rVFZkT9UBuVl0BRXVqiuR2Y78FKODFe/FI1PonUVF0Ge9DvjBWI0PXshwqobpNs NBGQ== 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=N/fd1ftRSaWCfwu2TCx32w6T3PUJ9co3zxcpVqsLW0E=; b=Gl3DjWC3n4pDHNrd4+ojdZzsjWtfpSdms9LfWMurTHcJbwzZPVYZBmJE5hHhOIQj5W 66o5VvQa/i0mxBt4SbwvL6hfyTgTwNH/QhYjA3DThUBRZ3MH52KAOkGdgSPyOcKLEsWr 5bHdED3x0fwSCWoUoSEYeNpSSMXlGozPNTLK6bbQ0fdvuX1KHVxl3a22OBnGaB484Rmy YWY5GrvgnAz+xSEZdux3UoPDaa+fKqPEjE+FwkklKN9+aBDk0xlHoBf+Iq+B9V+YBsUz dBvA6Gw1/Jj2cfq5GUwtv7ApXTn0LOm91vlcv556HuVdif77x81Pjb6Vpo7uV6t6IYl2 qYZg== X-Gm-Message-State: ALQs6tDoTDTarLs8nbvK4ku10f2WdjP5I0ThHcB29OdHQ9EeHO8LwDSk 9s+EqUrTn79JJzPWQjFE5seNIw== X-Google-Smtp-Source: AIpwx4/B/ZINTtC/bcBjlDocO2PajhXVx/XbZOXfWk6IPvRkYos+q4bN0E8DMfWlDGh/MYa73uWsPw== X-Received: by 10.101.68.72 with SMTP id e8mr7522610pgq.56.1523909709054; Mon, 16 Apr 2018 13:15:09 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:08 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:17 -0700 Message-Id: <1523909665-27961-3-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 24 +++++++++++++++--------- ovn/controller/physical.c | 12 ++++++------ 5 files changed, 37 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 27a092d..e629328 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -522,16 +522,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); @@ -640,6 +640,9 @@ 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(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg); + ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg); 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); @@ -835,6 +838,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 8c92c1d..fc418e7 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 Mon Apr 16 20:14:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898913 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="ANmG6a4K"; 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 40Q06N0TK4z9s19 for ; Tue, 17 Apr 2018 06:17:16 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CBA5BF76; Mon, 16 Apr 2018 20:15:16 +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 A004BE93 for ; Mon, 16 Apr 2018 20:15:12 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 2B2CE477 for ; Mon, 16 Apr 2018 20:15:11 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id t12so4332595pgp.13 for ; Mon, 16 Apr 2018 13:15:11 -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=Z+FWJi6Va1mG5eNZX1Rdax1OCRF7Fwctx7ZytC0GVzA=; b=ANmG6a4KQpF/icCUiWBeMZkgBoEiFUVjBiobKOmBCy4BkdX2VNdUjySrUI6/LIKQiJ PGzNM5OCnktpVm7uNbfNkVu3lQJrhr4MoesDAukmxl5C9M203YtYiX+OjKq4DTMcsmiW rczbuejHvQCaiTGsscYUQDbxPa9ko44kNvCmtU9CgGf0a7Zc+8ZctnQDIN4MFpE6ieyz 3rvzmBG4+yv8wg+HlZ8Xxjp5zJZHpHjdUfb1YU1+RMQ0kJyMPYStu8eHw7EyDLbUgtmE 58thjDdD4iP1d82TChC39M3kUrKIQAbZSVZHHcNqo/wlC/dSD6+nzdUVAIDXBuRnrDx9 wxBA== 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=Z+FWJi6Va1mG5eNZX1Rdax1OCRF7Fwctx7ZytC0GVzA=; b=ZO2xclhzbSiO7mPoHGHsX9bNp8noGnNxXkuCSv49OMHLuBOx/QQrFnUkycbB+ThmbJ 0oRUeChS3kxkmO7hyHWYrOvz+v3L6IincRXkbm6KDo9IEJrdz14piP/ENdHFwj5csICP 05d9gnJgprXzRhqGa9EqgWzh4ISEXfW+ND1qu6sVkHzqEDTPSdX0Skmry36BmOZSa3in 8yRFHxuYQX0UU2bz+U33MJDUFZFl1UBlNdKw6raTQ+EFEupkeNSM/A4af0nnwVXbwHm5 aN0HFrZApbLczN13ccsqm5Ja/UR+cNL+fGcxuAR7xksjXFc+/qg5IVQL7Qi0R5ZntMPH kXaA== X-Gm-Message-State: ALQs6tDi+k9juNM2jGdfI1eGGnc8GwJfahjLJiR60LZtzn/RZITuLaXX Mroph9AqK5eR3L4IZ5Rb4hJHLg== X-Google-Smtp-Source: AIpwx48d7tTSVzopN2LUlrPOfkOQf4Jqa/ohS5NLfQtcEUto3p5RVCyBW4jVJsOuxG2WjoN8ia57UA== X-Received: by 10.99.0.200 with SMTP id 191mr14065203pga.33.1523909710077; Mon, 16 Apr 2018 13:15:10 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:09 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:18 -0700 Message-Id: <1523909665-27961-4-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 479 ++++++++++++++++++++++++++-------------- 3 files changed, 335 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 e629328..9579870 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); @@ -210,15 +211,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); @@ -261,15 +273,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 * @@ -478,11 +482,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. */ @@ -590,6 +591,225 @@ 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 +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 +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 +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); + shash_destroy(addr_sets); + expr_const_sets_destroy(port_groups); + shash_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 +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 +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 +flow_output_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 *)engine_get_input( + "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; + 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 *fod = + (struct ed_type_flow_output *)node->data; + struct hmap *flow_table = &fod->flow_table; + struct ovn_extend_table *group_table = &fod->group_table; + struct ovn_extend_table *meter_table = &fod->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[]) { @@ -611,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(); @@ -647,21 +859,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) { @@ -675,145 +898,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); @@ -830,10 +990,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); } } @@ -847,26 +1008,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(); } @@ -881,12 +1044,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 Mon Apr 16 20:14:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898912 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="LCefAHP+"; 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 40Q05l28Qsz9s19 for ; Tue, 17 Apr 2018 06:16:43 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C7349EEB; Mon, 16 Apr 2018 20:15:15 +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 147B0DC6 for ; Mon, 16 Apr 2018 20:15:12 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A47B766F for ; Mon, 16 Apr 2018 20:15:11 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id e9so3234481pgr.7 for ; Mon, 16 Apr 2018 13:15:11 -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=V/Ko/D8QuC28Lga6b6v9ChtKYK6flsGIggKn8UN7Kqg=; b=LCefAHP+56mVGAfABYTJCxbJe6Clbz+Y47OTf50sPaORl0dRAlnYETamQE08wUht15 J0lPN4LTxXgFlAudrL5TJiWGUGoiupiB1y2jPoe+eYjZCXJc/D1EYolRl++ebpmZWJi7 w+dGsFHO7HWQSH9gMl3K8aSSEeeISbi94ivonygVynb5/MJzGvoO8SwvZ+VmpQ5Jr6WK 34HeNb0F53/CrmCAdTk20XEUKLLlikWyJB5J1NO5jkiXDd+KBFGMlbCVuYiWy/lG7K5N 4VYSxHYOTsTN1E1B6SPipljDeSuoSRRZSxqlDH5gsMAdad/2EnVovnzacRVlxDA0gKbg RA1g== 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=V/Ko/D8QuC28Lga6b6v9ChtKYK6flsGIggKn8UN7Kqg=; b=iBFjQk1wzXzuJLAq83ZE0ldO3H81H/mD+9X3fzuszZqMYKJnPNUCzUVHjGyBFie5/K 0HcFiJaauYWLps7VUfGwWPTAWY/KS6w2oBWOx0K4QNbheMt53xwmurvKmLfYmIh76cYp E2zXpZ/1EWWH0bd6rVK/ZDP8ivPjjuo6TyQWAapcLugS3ml353E4+JZfBlkb/jrkAYxT SDkMbUETvIUECgBhuZFKdNy6SJny0rAMPR5cj8e31Ns4ny8GNpQGJJh5xqzpBzoNlylp uEkutr6CkaA70iPz5u8OZp2GIc9UL6GS6h062goXCMrh0aRjHMucsdXoeeI3vkmUG3qJ F5UA== X-Gm-Message-State: ALQs6tCIqDaQMCyCR5JbRSVNwt5DlwkMcGeNptsd/3d5r9MTdtivuG+g BV2DznFf7TKo1heJnvUmA2kcXA== X-Google-Smtp-Source: AIpwx49p+r50p17WgHIBNHEFimJA7fYxRbr3auih2iKXegyAo7G63qi3uO0zyX/DuZ0R2rBhqhU6rQ== X-Received: by 10.99.103.6 with SMTP id b6mr14119912pgc.214.1523909711004; Mon, 16 Apr 2018 13:15:11 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:10 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:19 -0700 Message-Id: <1523909665-27961-5-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 9579870..847a3aa 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -591,6 +591,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; @@ -869,10 +883,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 Mon Apr 16 20:14:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898915 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="BuLjhdKY"; 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 40Q07V6qJlz9s19 for ; Tue, 17 Apr 2018 06:18:14 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id A630CF80; Mon, 16 Apr 2018 20:15:18 +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 2262CE93 for ; Mon, 16 Apr 2018 20:15:14 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f68.google.com (mail-pl0-f68.google.com [209.85.160.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7E2F3672 for ; Mon, 16 Apr 2018 20:15:12 +0000 (UTC) Received: by mail-pl0-f68.google.com with SMTP id c7-v6so10652337plr.5 for ; Mon, 16 Apr 2018 13:15:12 -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=YeQKzGDhuA5KmFqxgCbG9fDsxcjm/hCCG5MTEyseSHQ=; b=BuLjhdKYb1jqdTtK38ST1ufAshIsP88vjD2JUWINJGQqpXYLpk4x6FoGvFTIf3uf7n /Lj+7MgfQNCceUcBOB/iY9okRLglTfwcs9zfwHk8/Y48d2gHwZPw4sm2teRcUCi80lfk PJ8v7OJ3TuOqYTnG/aIV2pQrqtT45zsLQEpoUkkn0izQnf7MQbOK2ViwcQeahVeaWwnd JlKWNbSVIqi2C3DQy1gMDEL4DGhW13qqw8s1Icd2xib1g1wZE6FSlM/GfVdsjQqWLz4N /vREHw9ESQM7Y9zpIOTP/5e20wcA/Wyh3ii/QQmvm/QoYzwT5qhJeY1YcrysGWm/MAGe m5Zg== 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=YeQKzGDhuA5KmFqxgCbG9fDsxcjm/hCCG5MTEyseSHQ=; b=sr+hedgNcMD0T6uu4olgrvo3qCDAmEuNfaEuFnhY6QX9W00nApKfOkEgwJ5z6ZagiE c8U8nBH48qK7uVXvxooJMyc7OgwXBz1I1mFf3CdzaQ0VfqomrqjXN5zQHo2RNgr2xjmp jLuXtTFyHBqRgVXDw+D3JE9TSmEHBD+G20c+2WcJ9/HJXsKPhNHLLlC88YmnWTHkWNOE xcDQ/00Lc3RYpq+9Msd0PZxQue9zgliTTaXG3HP7T3iLXLTXwHmSMvFKbGScHFV8Iqna Tg4NLQtWDCd19a/Z+wHY7E7aFbBwi9aMUvDqZ4PGtBzIXzCa+l0yQENIr1yhabh474fT V07A== X-Gm-Message-State: ALQs6tAsMFQzvjAr/uObyVbpoqLZqRiJzw9OF5GEDlWaz7YPATlsICZM MvkK7dfmWkv5UzWU3Kn/lVIpPQ== X-Google-Smtp-Source: AIpwx48HpUg06Ghq5Yy7U6la2yKzogrq1VPRe1lAsk6zKdxnNSRYgNJkvW78PhULR7yMxktDENuc0w== X-Received: by 2002:a17:902:bd8d:: with SMTP id q13-v6mr16917508pls.330.1523909711826; Mon, 16 Apr 2018 13:15:11 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:11 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:20 -0700 Message-Id: <1523909665-27961-6-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 847a3aa..1f8ae05 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -605,6 +605,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 @@ 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); @@ -897,6 +901,9 @@ 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); @@ -915,6 +922,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, @@ -927,9 +943,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)) { @@ -975,10 +993,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); @@ -988,6 +1009,14 @@ main(int argc, char *argv[]) &ed_runtime_data.local_datapaths); } + if (old_engine_run_id == engine_run_id || + !ctx.ovnsb_idl_txn || !ctx.ovs_idl_txn) { + VLOG_DBG("engine did not run, force recompute next time: " + "br_int %p, chassis %p", br_int, chassis); + engine_set_force_recompute(true); + } else { + engine_set_force_recompute(false); + } if (ctx.ovnsb_idl_txn) { int64_t cur_cfg = ofctrl_get_cur_cfg(); From patchwork Mon Apr 16 20:14:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898920 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="Vsy4VwUW"; 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 40Q0BY1f5tz9s19 for ; Tue, 17 Apr 2018 06:20:53 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 176E0FA3; Mon, 16 Apr 2018 20:15: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 78C67D4F for ; Mon, 16 Apr 2018 20:15:21 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f52.google.com (mail-pl0-f52.google.com [209.85.160.52]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 98C78628 for ; Mon, 16 Apr 2018 20:15:14 +0000 (UTC) Received: by mail-pl0-f52.google.com with SMTP id 59-v6so10636303plc.13 for ; Mon, 16 Apr 2018 13:15:14 -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=yb1cQ8odDlHp5sHgO86Z5abAcj4JOHbBUbGytx/IyvA=; b=Vsy4VwUW42auqGBFj4iaIdPLR1rTCZuO0DD1LYFUMS7IV979oBk5RCcd0APfA9a92C c17BOGkorgjPxbE8XDYbADwacbwDBpTUkNNxHX7wq5es1gVaEXOZtrvABaw024M2zkX2 J5dAfMBnFFby4vx+c0dhNACjYtJaBFDbaRlg6RDQAQmpawmheYNX88t0MA3xm/NIo0ay IfvrlpuQS4oFdjmE+94N+CKtx6fPwm3TB3NbYZRks6STXmWcpMLRwQbIj37N3xcq2rEh aLHKft4uNnjCuCggZSG0BnDsOJ0vGQmVHNDhwr3yxiYUWts5iEMGZpXGp9gXPxzflxAa dTCw== 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=yb1cQ8odDlHp5sHgO86Z5abAcj4JOHbBUbGytx/IyvA=; b=Dptbil2UDXVRkUIf/1ms+5bq+OuVRZQAt5SegBZdHVwjALpyytigWLD6a3jDkWgXj4 zUqx2ocmN43ORcjTypJWI5xCHpz7MNv9DIUxGUXkf/xXic0ZJ9X3Qo1+g1ZDOJ6QExdN OjUnEc3ISkU9lFkLNM2kUw3c9mrpmx82UHnLYDK/j9l4tfbNRWkPOnMFxrKzlr4Dhd4z 6iQWPbV+PRb1SSTq6yrtiyI4w1tISP3PvohDq8hArNxEXjBUWYs/gxirXWrl2S6ByAvV NI1GnRtZj6D+yqEHcJm0sr/C2wrefe4r2LLahFI/dqUnEySAnBfgbwL2UJr7WJC3CRHb sp5A== X-Gm-Message-State: ALQs6tB7VOQhWwCwHCxpFa+lhdvqLQqXtvPzgNqnugsK7IbBfKCjNlcR R9/gBP2AyiiPY5qYtSRGrHt0rQ== X-Google-Smtp-Source: AIpwx48cPEeh42vNSGj6E5YmLTWf6mgeq8UpZqGYyCW+wLKEgVRpvQ9UkEljh9SqkExa+p6e1cf8pw== X-Received: by 2002:a17:902:4001:: with SMTP id b1-v6mr16312133pld.273.1523909712715; Mon, 16 Apr 2018 13:15:12 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:12 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:21 -0700 Message-Id: <1523909665-27961-7-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 29 ++++- ovn/controller/ovn-controller.c | 116 +++++++++++++------ ovn/controller/physical.c | 86 +++++++------- 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, 550 insertions(+), 210 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index fb8f515..b6014a2 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -513,6 +513,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 f022aa3..d75e03f 100644 --- a/ovn/controller/lflow.c +++ b/ovn/controller/lflow.c @@ -58,7 +58,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, @@ -71,7 +72,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); @@ -134,7 +134,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, @@ -142,11 +143,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); @@ -168,12 +168,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); @@ -181,8 +185,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, @@ -195,7 +286,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) { @@ -204,10 +294,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. */ @@ -245,7 +339,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. */ @@ -269,7 +363,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 = { @@ -285,10 +379,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. */ @@ -300,6 +396,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, @@ -328,13 +425,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; @@ -350,7 +452,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); } } @@ -358,7 +460,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 @@ -374,9 +476,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); @@ -418,26 +520,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, @@ -445,15 +549,15 @@ 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) { - 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..4e96d50 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 *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 *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..f251cd6 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..f05f8e6 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 *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,17 @@ 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 *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 *lflow_uuid); + +void ofctrl_remove_flows(struct ovn_desired_flow_table *flow_table, + const struct uuid *lflow_uuid); + +void ovn_desired_flow_table_init(struct ovn_desired_flow_table *flow_table); +void ovn_desired_flow_table_clear(struct ovn_desired_flow_table *flow_table); +void ovn_desired_flow_table_destroy(struct ovn_desired_flow_table *flow_table); #endif /* ovn/ofctrl.h */ diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 1f8ae05..240a2da 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -747,11 +747,13 @@ 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 @@ 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 @@ 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 @@ flow_output_run(struct engine_node *node) struct ed_type_flow_output *fod = (struct ed_type_flow_output *)node->data; - struct hmap *flow_table = &fod->flow_table; + struct ovn_desired_flow_table *flow_table = &fod->flow_table; struct ovn_extend_table *group_table = &fod->group_table; struct ovn_extend_table *meter_table = &fod->meter_table; + uint32_t *conj_id_ofs = &fod->conj_id_ofs; static bool first_run = true; if (first_run) { first_run = false; } else { - hmap_clear(flow_table); + ovn_desired_flow_table_clear(&fod->flow_table); + ovn_extend_table_clear(&fod->group_table, false /* desired */); + ovn_extend_table_clear(&fod->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 *fod = + (struct ed_type_flow_output *)node->data; + struct ovn_desired_flow_table *flow_table = &fod->flow_table; + struct ovn_extend_table *group_table = &fod->group_table; + struct ovn_extend_table *meter_table = &fod->meter_table; + uint32_t *conj_id_ofs = &fod->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 @@ -910,13 +959,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); @@ -927,6 +974,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); @@ -944,6 +992,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) { @@ -980,33 +1029,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 fc418e7..513d986 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. */ @@ -1019,10 +1029,10 @@ 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); + &ofpacts, hc_uuid); - 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); @@ -1063,7 +1073,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 @@ -1096,7 +1106,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); } } @@ -1117,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. * ======================= @@ -1140,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); } } @@ -1152,7 +1162,7 @@ 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. * ======================= @@ -1167,7 +1177,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. * ======================= @@ -1177,7 +1187,7 @@ 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..ac2da2a 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 *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 a694581..655085d 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; @@ -2208,7 +2209,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..f0b8fd9 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 *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 Mon Apr 16 20:14:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898916 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="WjG6DnJZ"; 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 40Q0892bHwz9s19 for ; Tue, 17 Apr 2018 06:18:49 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D65D1F91; Mon, 16 Apr 2018 20:15: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 AB72BF73 for ; Mon, 16 Apr 2018 20:15:16 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 23C65466 for ; Mon, 16 Apr 2018 20:15:14 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id o16so11046166pfk.9 for ; Mon, 16 Apr 2018 13:15:14 -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=rskEzXIXiSELQ8YiOweOnGsto95Y4wLeJxoNZxPl++k=; b=WjG6DnJZF+WaBMOrwcQF19uFL9JgSStN3k370i4GShxgFsSUdakf28SET2qntpqlaN JTHoMMkDlsVp1n1GX6eUe/f+63+01GvpuCwKmtQhnwc8k6kZJudWZ1IsmI7MMoXyo4vp wv77b5FOwk4X74L4k2AgkDuJqRfF5m3ab95Q6J5HbOm0mzWKHb7L3dL30Y5d3hgvfiap fFbXXrcG6VFWzf/E+aL6ZSwYulTuJBOw7XsmZlJEvp791Az7V9sh6/JasUqcWNGm+LA4 sUxWZWGNUm4+G1vvtdzDd2e7bcaOCsAXmh+YjcsHXz7LQbGTAdsrVTAyW2lP+RnUx6vi b7mQ== 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=rskEzXIXiSELQ8YiOweOnGsto95Y4wLeJxoNZxPl++k=; b=Sl3CGpmPf08bz9GD0fBBtu3B3OQ7eL+hZYBt8hurF8+Cri9rPvCYNYwbOVBV8UWlIy f527DqA0fg95m34ojrl9aHW3BJT3Kj9z4r8T6aqYsymhdAozjGnemCzyFhcxiBBDJB4i 7+k0mKmT2zHUk8i6dR1xAlyH30dActkMwF5ADtUotBrI9cnvc+qlEa0SNvmlPQrzFShb Hb63QRhoohom92oeVoWm3mm9EJqvTOTub+7o3xPkzsHDdpOUtu5mMqNJHY7Wp6r0lK9N MUYgWKKzNPpmqqCWL3fNg9SK0aPBqJESOjcNPhbAdHUt4IRScTpzfy+Ie1xZpGXCZMhI 9tbg== X-Gm-Message-State: ALQs6tCmD2L0xu8Z6YNWWVpAsa95etPOtr++4HuOxyHkPNS9se/hkR5N 7dGQhsvRejuo/LbFiD+iPlU5tg== X-Google-Smtp-Source: AIpwx48qRBF5DupbqpIbeRKkVMAWltdEz17O56oStvzqYASC8WgFmugyAWKfpKSvuc/FafFm/lZIiA== X-Received: by 10.101.69.198 with SMTP id m6mr14107429pgr.244.1523909713470; Mon, 16 Apr 2018 13:15:13 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:13 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:22 -0700 Message-Id: <1523909665-27961-8-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 85 +++++++++++++++++++++++++++++++++++++++++ ovn/controller/binding.h | 6 +++ ovn/controller/ovn-controller.c | 28 +++++++++++++- 3 files changed, 118 insertions(+), 1 deletion(-) diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c index 84ff4d6..fbac822 100644 --- a/ovn/controller/binding.c +++ b/ovn/controller/binding.c @@ -580,6 +580,91 @@ 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; +} + +/* Check if port_binding changes are impacting */ +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) { + // TODO: how to find out old record from track? + 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..db8685d 100644 --- a/ovn/controller/binding.h +++ b/ovn/controller/binding.h @@ -34,5 +34,11 @@ 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 *chassis_rec, + const struct chassis_index *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 240a2da..8855296 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -745,6 +745,32 @@ 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; @@ -976,7 +1002,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 Mon Apr 16 20:14:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898917 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="T+7dSz4M"; 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 40Q08h2jCsz9s19 for ; Tue, 17 Apr 2018 06:19:16 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EF856F95; Mon, 16 Apr 2018 20:15: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 E3FE1F78 for ; Mon, 16 Apr 2018 20:15:16 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f194.google.com (mail-pf0-f194.google.com [209.85.192.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 15E10636 for ; Mon, 16 Apr 2018 20:15:15 +0000 (UTC) Received: by mail-pf0-f194.google.com with SMTP id o16so11046185pfk.9 for ; Mon, 16 Apr 2018 13:15:15 -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=2eohX1iVvIbQS6jbs8UkDLbZi/vuQ5G0QJRfDi9QEEM=; b=T+7dSz4MvPEYkwKX23sqi1a8LY/+mIYv1Lci0r2WkAgsVCcjmZLAjM1MIdH+Gkngym QhbH4cHkbIHhG1gy3petfci2sCBog/1o5HNuqXqegLyWuwHSKSNjZQPnAGnkz9VvvcBz LIKXqQJ+QmKQZr/S3nZkyxD3SPSWXv03psO/clcuZNFmPobbBovb5smUoTeHqzDZZBYn PKZmV0hAmJ/8Ek4xkCnQuffElM9EQO1SRpLB7rAbhXz4YMyPNGkxz1D5vUjcRw2y7roL dQU1rEH0oK4MDnlGJkVZFNg4mifkoPpIF6xVtDHqKZJIMES5rZCUhQ9OnZ7HZsFUn7iA Oc9Q== 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=2eohX1iVvIbQS6jbs8UkDLbZi/vuQ5G0QJRfDi9QEEM=; b=YkSPnVfwNna7wE214T0/p/W4wMut96C4AiLGiGEa1isbRwz+Nhz2XFHe1j4M99RlID MEXfR3Do1EwRL96a7+pTV74ONeVnuk2EHed9es2oT8DZLlaM6TYmZeFrVT3oOLiD2HlP caqRImIzYglmT7YBiVp8JDppWiXDBmj9Ihbuu1agyZwY1hYDPr/qhMauXRk4281G2MqS pNYWMpjQfJYrtMcySnfFHczfkpSwgOu6bj7iQfY6cpHFkGqvVm0RmBqzom8JEMAf5ssZ S/v/I5Lzy6oZhe6+TvDwDxQ3eCAnQJXoHuiLvyLoxyiavZtv7N6M/1f1yqJqGWB/gt25 zVIQ== X-Gm-Message-State: ALQs6tA4/Jqoug6F/AUs+LEjS/SPq6bVN9/x9BTlbVuvylyA8MAMx8P/ OjETSNWEDI0W/xbzVZ5ANU/5Gw== X-Google-Smtp-Source: AIpwx48/3JnYnORPJAc0rohuh9YA6DrDaNWJhzpHw+uodmVDepb19iiKBc0LVzvwRs8MDIO26kb9Qg== X-Received: by 10.99.51.137 with SMTP id z131mr14152091pgz.386.1523909714349; Mon, 16 Apr 2018 13:15:14 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:13 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:23 -0700 Message-Id: <1523909665-27961-9-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 42 ++++++++++++- ovn/controller/physical.c | 131 +++++++++++++++++++++++++++++----------- ovn/controller/physical.h | 9 +++ 3 files changed, 147 insertions(+), 35 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 8855296..c9598f3 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -903,6 +903,46 @@ 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); + + // TODO: handle port-binding for lflow processing + + struct ed_type_flow_output *fod = + (struct ed_type_flow_output *)node->data; + struct ovn_desired_flow_table *flow_table = &fod->flow_table; + + 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[]) { @@ -987,7 +1027,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 513d986..9fbcac0 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, @@ -993,6 +1059,7 @@ physical_run(struct ovn_desired_flow_table *flow_table, /* Capture changed or removed openflow ports. */ physical_map_changed |= update_ofports(&localvif_to_ofport, &new_localvif_to_ofport); + // TODO: maybe this is not needed any more? if (physical_map_changed) { /* Reprocess logical flow table immediately. */ poll_immediate_wake(); @@ -1013,8 +1080,6 @@ 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) { /* Table 32, priority 150. * ======================= @@ -1031,12 +1096,10 @@ physical_run(struct ovn_desired_flow_table *flow_table, ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 150, 0, &match, &ofpacts, hc_uuid); - consider_mc_group(flow_table, mff_ovn_geneve, ct_zones, local_datapaths, chassis, - mc, &ofpacts, &remote_ofpacts); + consider_mc_group(flow_table, mff_ovn_geneve, ct_zones, + 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 ac2da2a..cb55d94 100644 --- a/ovn/controller/physical.h +++ b/ovn/controller/physical.h @@ -52,5 +52,14 @@ void physical_run(struct ovn_desired_flow_table *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 *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); #endif /* ovn/physical.h */ From patchwork Mon Apr 16 20:14:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898918 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="rmvqZx+S"; 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 40Q09F3Gcnz9s1B for ; Tue, 17 Apr 2018 06:19:45 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id F1839F99; Mon, 16 Apr 2018 20:15:22 +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 1C4B2F73 for ; Mon, 16 Apr 2018 20:15:17 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 47A6C676 for ; Mon, 16 Apr 2018 20:15:16 +0000 (UTC) Received: by mail-pf0-f193.google.com with SMTP id q9so11064445pff.1 for ; Mon, 16 Apr 2018 13:15:16 -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=v8Hv32Xi5a9BmyhFRJ/VEtSy5UgrvSTtD6Ms6qUg4Kg=; b=rmvqZx+SicZyUXhT7XTpHo8+XWoEej9O5a7dbldUusnDUwyGolUjDttx5aVOoB7JR1 bQ8PGh391JfdL2oCqruph1yJoxOR+MxRIgmW4lsxVqxLmX4VAYhgqoToCWsf7fhfxffI Qs2IlwsM6nE2r6hlluhn162qoKwShmDSHRxJSshwx+g0vC+KasNOvolqZQGayqFZLtBb rUnCjCRl7qjpIs3Ern+JVbYMdQe1PD2b/PfbB6SRlHEMxoJtVtqXMOm2Y0Au9NfhOFBH 1DTqksECZJg88/E3b9c3WCtPkSXbEcUWdNqpsmhaVBC0WeusEn4S5uuNMKZ/Wi33lwP8 7/MA== 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=v8Hv32Xi5a9BmyhFRJ/VEtSy5UgrvSTtD6Ms6qUg4Kg=; b=uOOhpNAPHF+o06caAWQaQ63UyMkpxspV0AfgqTrWSO+AWzSsT3Pjq6+h1mjewihT0e aInq7GRcglwpWzl1nPTmGjdhMYk/4fDC2fvbTI0MOyyneB4ya4YWgssIMCHISyB8Aqh3 UDY3zvbG2p1CwJjr3ZIyxqmX6vGN7yW6pM155ND6sYEoFBZ4R8dqxNiiBRX5gSJz/wpj 9pEDjPBxFeMeqCuxp6wWLEbxqHuKrP5zi26oKdWi65uk5DesnroQs2b2uDdnRwkSltMx fM/B76rkIMbWEL9i71pJAJzPAp5accEmiWz+GiZGRzT51Re04hxlJ3lsfY0ysOuaIBFQ tS3w== X-Gm-Message-State: ALQs6tD+ordpDF71xENE7v2ZThc+c2IVktX1N8ToXexdLH3Ej2EdfzGF WhjkQUeuj51Rp6h7G7R1M7surg== X-Google-Smtp-Source: AIpwx49e7NDrYRC5Q6zBHG8oA+eDdP5N6ALvT8mPHARMKPpH+JcMmAAwSVwSemT88h6ECvUJYjAsLw== X-Received: by 10.98.56.144 with SMTP id f138mr6113286pfa.173.1523909715514; Mon, 16 Apr 2018 13:15:15 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:15 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:24 -0700 Message-Id: <1523909665-27961-10-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 11 ++++++++--- ovn/lib/inc-proc-eng.c | 19 +++++++++++++++++++ ovn/lib/inc-proc-eng.h | 4 ++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index c9598f3..1b0bfda 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -1123,9 +1123,14 @@ main(int argc, char *argv[]) } if (old_engine_run_id == engine_run_id || !ctx.ovnsb_idl_txn || !ctx.ovs_idl_txn) { - VLOG_DBG("engine did not run, force recompute next time: " - "br_int %p, chassis %p", br_int, chassis); - engine_set_force_recompute(true); + 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); + } 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 54c7fd6..2e5e907 100644 --- a/ovn/lib/inc-proc-eng.c +++ b/ovn/lib/inc-proc-eng.c @@ -123,3 +123,22 @@ engine_run(struct engine_node *node, uint64_t run_id) } +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 3e0ec16..c5deaa5 100644 --- a/ovn/lib/inc-proc-eng.h +++ b/ovn/lib/inc-proc-eng.h @@ -131,6 +131,10 @@ engine_run(struct engine_node *node, uint64_t run_id); void engine_cleanup(struct engine_node *node); +/* Check if engine needs to run, i.e. any change to be processed */ +bool +engine_need_run(struct engine_node *node); + /* Get the input node with for */ static inline struct engine_node * engine_get_input(const char *input_name, struct engine_node *node) From patchwork Mon Apr 16 20:14:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 898919 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="qY3tVigH"; 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 40Q09q1fDLz9s19 for ; Tue, 17 Apr 2018 06:20:15 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EF933F9B; Mon, 16 Apr 2018 20:15: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 E8B57F83 for ; Mon, 16 Apr 2018 20:15:18 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f196.google.com (mail-pf0-f196.google.com [209.85.192.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 61D5C3CC for ; Mon, 16 Apr 2018 20:15:17 +0000 (UTC) Received: by mail-pf0-f196.google.com with SMTP id q9so11064462pff.1 for ; Mon, 16 Apr 2018 13:15:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7F7IgGA7IVlfUveHNeiTbPlBbcHvliIaBt7AJW0x2Uo=; b=qY3tVigHCjKynH7Q7DbBsx+/g5vv2e5ZcBKNsLjV6UwSsmCtf2nMuWtDEK/rXku3Xs u32jZTEYEeCdlowu+pfQnEeCJWUKIth5QomvCjjwhf6UScNRsTgu3ofTARMu0HozAfxI zGOoYxSgoI52y2IywKImZHDlAppCYtqbSsNp+su3oTd38kNCPF1wx5II0m1cuFntd/6U E86bizmT3YqsYR0ctgo6SjfFRzV5RY7QIDTWBcpwRipRFJw1mZThUbD/Hlgtga5aF1V7 bGmXNyJiU8VsVFHFOd5hMUNw4JvRDG/qNDj2AgXFJU47/BgdQecfM9wlGTg7TVoN+5/s 0/yw== 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=7F7IgGA7IVlfUveHNeiTbPlBbcHvliIaBt7AJW0x2Uo=; b=md8k08C+HlbYZKa1L2WrrcZjNiDq40jCfEQh/sHHvSEK5/tmzBMBuxVeRmbxoWWyzc DsxPo3bicgnXXefDUwq/WswlbxP3rT1YB/BgCrStGe2Q6d6eQMl0Dg3ble6EXRaiXXwf gbv9HdJM7wNS6sfPpD3HPG9rxxL0tHFc1vBOPYFb+OYKF6bnkuneI3SQhZqzFNtpDjix OfF/bi7fHKgTXMYrgoXJRQWuK9j43l+06EfOx/EmEfSMm0AIVwHqfs+z1+0LOdUcaeS2 rLZhlwhcng0ZFniFOO1g0HJKJpwmjypeo89O0NnzZ82qjD8Pz29IbTgowAFPufY2W9O8 SGQw== X-Gm-Message-State: ALQs6tDN/A8LLL8EOIqgJzXzTixRzgLawq1IVZEkhXE5vK12Ujh/LSuV M9g/bkitDsHGLY1w1176tpsqQA== X-Google-Smtp-Source: AIpwx4/KusQj8bhyy+igjS5SpvpSUsx01bXzVWjFhA5BkKiNkSeJkfyKVPdbli+d1yOKel+nXHCNlA== X-Received: by 10.98.161.10 with SMTP id b10mr13983493pff.214.1523909716758; Mon, 16 Apr 2018 13:15:16 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.71]) by smtp.gmail.com with ESMTPSA id m7sm2306746pga.46.2018.04.16.13.15.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 13:15:16 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Mon, 16 Apr 2018 13:14:25 -0700 Message-Id: <1523909665-27961-11-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1523909665-27961-1-git-send-email-hzhou8@ebay.com> References: <1523909665-27961-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] [RFC v3 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 | 8 +++++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 1b0bfda..ddf6a95 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -943,6 +943,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 *fod = + (struct ed_type_flow_output *)node->data; + struct ovn_desired_flow_table *flow_table = &fod->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[]) { @@ -1025,7 +1060,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 9fbcac0..5a55df7 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 cb55d94..50c1879 100644 --- a/ovn/controller/physical.h +++ b/ovn/controller/physical.h @@ -61,5 +61,11 @@ void physical_handle_port_binding_changes( struct hmap *local_datapaths, struct chassis_index *chassis_index, struct sset *active_tunnels); - +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); #endif /* ovn/physical.h */