From patchwork Thu May 24 22:10:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 920129 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="iqaOo1uY"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40sNsH12Fcz9s0q for ; Fri, 25 May 2018 08:12:03 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 65659D4C; Thu, 24 May 2018 22:10:23 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id E6814D33 for ; Thu, 24 May 2018 22:10:21 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pf0-f171.google.com (mail-pf0-f171.google.com [209.85.192.171]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8F035674 for ; Thu, 24 May 2018 22:10:20 +0000 (UTC) Received: by mail-pf0-f171.google.com with SMTP id j20-v6so1542046pff.10 for ; Thu, 24 May 2018 15:10:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=edBKvjjQ+AtrUP73QXxTElElNp833Hf1573oOrBhtPw=; b=iqaOo1uY6GteQS+gGlkMxn3uqmPM/ZrXViS5a+olkBhg+MFL3D0+rrrj2ENMer690W xN4AS0NiLBwL+VnYpWs5COsR8RbPy1CU22ydnFRrG535wAP8IOtfqzXZGSfmlF26zhw3 1HpLdudESrS1JweJMPOGc9UYndRsrU24zM239l5so/5t40M1UByXmmF2F9466UOiVzSI SNE8K8yzh/8lxURg6ZGD3zzssJowLOrJ5xbhOQvjk2ClvU2milh8QrVbjcLC8LPb8LEB LeR1aZYT8RAA7UIejkN15ILC5J43ysZRHM2rLFN/KZfysEm07TbIT65/fqKM+Q132HIE 9nQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=edBKvjjQ+AtrUP73QXxTElElNp833Hf1573oOrBhtPw=; b=lf+8lTdd3TB2/AJ0Kb+ic5q6J6rXGzIMWk7W3uL0FxrjKhMC4G1audqIpBPJTLDM2/ m0/MffTlnZVsRMe8VDDcJWaTM83d7B2gABJq8TkVDTYPSwciwqZsnA/kYwAl78r+xpRT HRDBZuzmxUQuOy135aqdAGIdRYlu+sdw8JL3eKxcdzHfu5jxDN/ULZZJM9ncUojLEgPo oE8erRD/8dbABJPIXWcVvv/UtODy/cAAgFS+OOHjXTNkykSgDlQV3A7NI9uSuVGefh1K 5kSQQ29+0vjji6JkReWsnkvJ3lNNKr/Ma64/fjxV+ZJ1txENQsBvJwpvB2578/yp1yZ1 1ahg== X-Gm-Message-State: ALKqPwcDfmlvtwaNbzX4T1HceIqdP21soj7+m8MyURbo92z1djuan9ee AVP754RlqMFN+hjCOdgYfQpdiQ== X-Google-Smtp-Source: AB8JxZoXpC7Sx0C4Yv9Awu1agWmeztVWKDArPYpH7sI/iwjq/mLs1QefYgsZTl6JJGQNKfy6UOg8jg== X-Received: by 2002:a62:104a:: with SMTP id y71-v6mr8957758pfi.188.1527199819570; Thu, 24 May 2018 15:10:19 -0700 (PDT) Received: from localhost.localdomain.localdomain ([216.113.160.70]) by smtp.gmail.com with ESMTPSA id y18-v6sm47493651pfi.104.2018.05.24.15.10.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 May 2018 15:10:18 -0700 (PDT) From: Han Zhou X-Google-Original-From: Han Zhou To: dev@openvswitch.org Date: Thu, 24 May 2018 15:10:44 -0700 Message-Id: <1527199851-107563-4-git-send-email-hzhou8@ebay.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> References: <1527199851-107563-1-git-send-email-hzhou8@ebay.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 03/10] ovn-controller: Initial use of incremental engine in main X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Incremental proccessing engine is used to compute flows. In this patch we only create 2 engine nodes with simple dependency: runtime_data -> flow_output In each iteration everything is still recomputed. Signed-off-by: Han Zhou --- ovn/controller/ofctrl.c | 21 +- ovn/controller/ofctrl.h | 5 +- ovn/controller/ovn-controller.c | 481 ++++++++++++++++++++++++++-------------- 3 files changed, 337 insertions(+), 170 deletions(-) diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 349de3a..134f0e5 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -477,11 +477,21 @@ recv_S_UPDATE_FLOWS(const struct ofp_header *oh, enum ofptype type, } } + +enum mf_field_id +ofctrl_get_mf_field_id(void) +{ + if (!rconn_is_connected(swconn)) { + return 0; + } + return (state == S_CLEAR_FLOWS || state == S_UPDATE_FLOWS + ? mff_ovn_geneve : 0); +} + /* Runs the OpenFlow state machine against 'br_int', which is local to the * hypervisor on which we are running. Attempts to negotiate a Geneve option - * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. If successful, - * returns the MFF_* field ID for the option, otherwise returns 0. */ -enum mf_field_id + * field for class OVN_GENEVE_CLASS, type OVN_GENEVE_TYPE. */ +void ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones) { char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name); @@ -494,7 +504,7 @@ ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones) rconn_run(swconn); if (!rconn_is_connected(swconn)) { - return 0; + return; } if (seqno != rconn_get_connection_seqno(swconn)) { seqno = rconn_get_connection_seqno(swconn); @@ -557,9 +567,6 @@ ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones) * point, so ensure that we come back again without waiting. */ poll_immediate_wake(); } - - return (state == S_CLEAR_FLOWS || state == S_UPDATE_FLOWS - ? mff_ovn_geneve : 0); } void diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h index a8b3afc..45081e5 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -33,8 +33,9 @@ struct shash; /* Interface for OVN main loop. */ void ofctrl_init(struct ovn_extend_table *group_table, struct ovn_extend_table *meter_table); -enum mf_field_id ofctrl_run(const struct ovsrec_bridge *br_int, - struct shash *pending_ct_zones); +void ofctrl_run(const struct ovsrec_bridge *br_int, + struct shash *pending_ct_zones); +enum mf_field_id ofctrl_get_mf_field_id(void); bool ofctrl_can_put(void); void ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, int64_t nb_cfg); diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index d4cc69f..91e0293 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -60,6 +60,7 @@ #include "timeval.h" #include "timer.h" #include "stopwatch.h" +#include "ovn/lib/inc-proc-eng.h" VLOG_DEFINE_THIS_MODULE(main); @@ -208,15 +209,26 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, ovsdb_idl_condition_destroy(&dns); } +static const char * +br_int_name(const struct ovsrec_open_vswitch *cfg) +{ + return smap_get_def(&cfg->external_ids, "ovn-bridge", DEFAULT_BRIDGE_NAME); +} + static const struct ovsrec_bridge * -create_br_int(struct controller_ctx *ctx, - const struct ovsrec_open_vswitch *cfg, - const char *bridge_name) +create_br_int(struct controller_ctx *ctx) { if (!ctx->ovs_idl_txn) { return NULL; } + const struct ovsrec_open_vswitch *cfg; + cfg = ovsrec_open_vswitch_first(ctx->ovs_idl); + if (!cfg) { + return NULL; + } + const char *bridge_name = br_int_name(cfg); + ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn, "ovn-controller: creating integration bridge '%s'", bridge_name); @@ -259,15 +271,7 @@ get_br_int(struct controller_ctx *ctx) return NULL; } - const char *br_int_name = smap_get_def(&cfg->external_ids, "ovn-bridge", - DEFAULT_BRIDGE_NAME); - - const struct ovsrec_bridge *br; - br = get_bridge(ctx->ovs_idl, br_int_name); - if (!br) { - return create_br_int(ctx, cfg, br_int_name); - } - return br; + return get_bridge(ctx->ovs_idl, br_int_name(cfg)); } static const char * @@ -476,11 +480,8 @@ restore_ct_zones(struct ovsdb_idl *ovs_idl, return; } - const char *br_int_name = smap_get_def(&cfg->external_ids, "ovn-bridge", - DEFAULT_BRIDGE_NAME); - const struct ovsrec_bridge *br_int; - br_int = get_bridge(ovs_idl, br_int_name); + br_int = get_bridge(ovs_idl, br_int_name(cfg)); if (!br_int) { /* If the integration bridge hasn't been defined, assume that * any existing ct-zone definitions aren't valid. */ @@ -588,6 +589,227 @@ create_ovnsb_indexes(struct ovsdb_idl *ovnsb_idl) OVSDB_INDEX_ASC, NULL); } +struct ed_type_runtime_data { + struct chassis_index chassis_index; + + /* Contains "struct local_datapath" nodes. */ + struct hmap local_datapaths; + + /* Contains the name of each logical port resident on the local + * hypervisor. These logical ports include the VIFs (and their child + * logical ports, if any) that belong to VMs running on the hypervisor, + * l2gateway ports for which options:l2gateway-chassis designates the + * local hypervisor, and localnet ports. */ + struct sset local_lports; + + /* Contains the same ports as local_lports, but in the format: + * _ */ + struct sset local_lport_ids; + struct sset active_tunnels; + struct shash addr_sets; + struct shash port_groups; + + /* connection tracking zones. */ + unsigned long ct_zone_bitmap[BITMAP_N_LONGS(MAX_CT_ZONES)]; + struct shash pending_ct_zones; + struct simap ct_zones; +}; + +static void +en_runtime_data_init(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)node->data; + hmap_init(&data->local_datapaths); + sset_init(&data->local_lports); + sset_init(&data->local_lport_ids); + sset_init(&data->active_tunnels); + shash_init(&data->addr_sets); + shash_init(&data->port_groups); + shash_init(&data->pending_ct_zones); + simap_init(&data->ct_zones); + + /* Initialize connection tracking zones. */ + memset(data->ct_zone_bitmap, 0, sizeof data->ct_zone_bitmap); + bitmap_set1(data->ct_zone_bitmap, 0); /* Zone 0 is reserved. */ + restore_ct_zones(ctx->ovs_idl, &data->ct_zones, data->ct_zone_bitmap); +} + +static void +en_runtime_data_cleanup(struct engine_node *node) +{ + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)node->data; + + expr_const_sets_destroy(&data->addr_sets); + shash_destroy(&data->addr_sets); + expr_const_sets_destroy(&data->port_groups); + shash_destroy(&data->port_groups); + + chassis_index_destroy(&data->chassis_index); + + sset_destroy(&data->local_lports); + sset_destroy(&data->local_lport_ids); + sset_destroy(&data->active_tunnels); + struct local_datapath *cur_node, *next_node; + HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, + &data->local_datapaths) { + free(cur_node->peer_dps); + hmap_remove(&data->local_datapaths, &cur_node->hmap_node); + free(cur_node); + } + hmap_destroy(&data->local_datapaths); + + simap_destroy(&data->ct_zones); + shash_destroy(&data->pending_ct_zones); +} + +static void +en_runtime_data_run(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *data = + (struct ed_type_runtime_data *)node->data; + struct hmap *local_datapaths = &data->local_datapaths; + struct sset *local_lports = &data->local_lports; + struct sset *local_lport_ids = &data->local_lport_ids; + struct sset *active_tunnels = &data->active_tunnels; + struct chassis_index *chassis_index = &data->chassis_index; + struct shash *addr_sets = &data->addr_sets; + struct shash *port_groups = &data->port_groups; + unsigned long *ct_zone_bitmap = data->ct_zone_bitmap; + struct shash *pending_ct_zones = &data->pending_ct_zones; + struct simap *ct_zones = &data->ct_zones; + + static bool first_run = true; + if (first_run) { + /* don't cleanup since there is no data yet */ + first_run = false; + } else { + struct local_datapath *cur_node, *next_node; + HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, local_datapaths) { + free(cur_node->peer_dps); + hmap_remove(local_datapaths, &cur_node->hmap_node); + free(cur_node); + } + hmap_clear(local_datapaths); + sset_destroy(local_lports); + sset_destroy(local_lport_ids); + sset_destroy(active_tunnels); + chassis_index_destroy(chassis_index); + expr_const_sets_destroy(addr_sets); + expr_const_sets_destroy(port_groups); + sset_init(local_lports); + sset_init(local_lport_ids); + sset_init(active_tunnels); + } + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + ovs_assert(br_int && chassis_id); + const struct sbrec_chassis *chassis = NULL; + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + ovs_assert(chassis); + + chassis_index_init(chassis_index, ctx->ovnsb_idl); + bfd_calculate_active_tunnels(br_int, active_tunnels); + binding_run(ctx, br_int, chassis, + chassis_index, active_tunnels, local_datapaths, + local_lports, local_lport_ids); + + addr_sets_init(ctx, addr_sets); + port_groups_init(ctx, port_groups); + update_ct_zones(local_lports, local_datapaths, ct_zones, + ct_zone_bitmap, pending_ct_zones); + + node->changed = true; +} + +struct ed_type_flow_output { + /* desired flows */ + struct hmap flow_table; + /* group ids for load balancing */ + struct ovn_extend_table group_table; + /* meter ids for QoS */ + struct ovn_extend_table meter_table; +}; + +static void +en_flow_output_init(struct engine_node *node) +{ + struct ed_type_flow_output *data = + (struct ed_type_flow_output *)node->data; + hmap_init(&data->flow_table); + ovn_extend_table_init(&data->group_table); + ovn_extend_table_init(&data->meter_table); +} + +static void +en_flow_output_cleanup(struct engine_node *node) +{ + struct ed_type_flow_output *data = + (struct ed_type_flow_output *)node->data; + hmap_destroy(&data->flow_table); + ovn_extend_table_destroy(&data->group_table); + ovn_extend_table_destroy(&data->meter_table); +} + +static void +en_flow_output_run(struct engine_node *node) +{ + struct controller_ctx *ctx = (struct controller_ctx *)node->context; + struct ed_type_runtime_data *rt_data = + (struct ed_type_runtime_data *)engine_get_input( + "runtime_data", node)->data; + struct hmap *local_datapaths = &rt_data->local_datapaths; + struct sset *local_lports = &rt_data->local_lports; + struct sset *local_lport_ids = &rt_data->local_lport_ids; + struct sset *active_tunnels = &rt_data->active_tunnels; + struct chassis_index *chassis_index = &rt_data->chassis_index; + struct shash *addr_sets = &rt_data->addr_sets; + struct shash *port_groups = &rt_data->port_groups; + struct simap *ct_zones = &rt_data->ct_zones; + + const struct ovsrec_bridge *br_int = get_br_int(ctx); + + const char *chassis_id = get_chassis_id(ctx->ovs_idl); + + const struct sbrec_chassis *chassis = NULL; + if (chassis_id) { + chassis = get_chassis(ctx->ovnsb_idl, chassis_id); + } + + ovs_assert(br_int && chassis); + + struct ed_type_flow_output *fo = + (struct ed_type_flow_output *)node->data; + struct hmap *flow_table = &fo->flow_table; + struct ovn_extend_table *group_table = &fo->group_table; + struct ovn_extend_table *meter_table = &fo->meter_table; + + static bool first_run = true; + if (first_run) { + first_run = false; + } else { + hmap_clear(flow_table); + } + + lflow_run(ctx, chassis, + chassis_index, local_datapaths, group_table, + meter_table, addr_sets, port_groups, flow_table, + active_tunnels, local_lport_ids); + + enum mf_field_id mff_ovn_geneve = ofctrl_get_mf_field_id(); + + physical_run(ctx, mff_ovn_geneve, + br_int, chassis, ct_zones, + flow_table, local_datapaths, local_lports, + chassis_index, active_tunnels); + node->changed = true; +} + int main(int argc, char *argv[]) { @@ -609,17 +831,9 @@ main(int argc, char *argv[]) } unixctl_command_register("exit", "", 0, 0, ovn_controller_exit, &exiting); - /* Initialize group ids for loadbalancing. */ - struct ovn_extend_table group_table; - ovn_extend_table_init(&group_table); - - /* Initialize meter ids for QoS. */ - struct ovn_extend_table meter_table; - ovn_extend_table_init(&meter_table); daemonize_complete(); - ofctrl_init(&group_table, &meter_table); pinctrl_init(); lflow_init(); @@ -643,21 +857,32 @@ main(int argc, char *argv[]) update_sb_monitors(ovnsb_idl_loop.idl, NULL, NULL, NULL); ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl); - /* Initialize connection tracking zones. */ - struct simap ct_zones = SIMAP_INITIALIZER(&ct_zones); - struct shash pending_ct_zones = SHASH_INITIALIZER(&pending_ct_zones); - unsigned long ct_zone_bitmap[BITMAP_N_LONGS(MAX_CT_ZONES)]; - memset(ct_zone_bitmap, 0, sizeof ct_zone_bitmap); - bitmap_set1(ct_zone_bitmap, 0); /* Zone 0 is reserved. */ - restore_ct_zones(ovs_idl_loop.idl, &ct_zones, ct_zone_bitmap); + + stopwatch_create(CONTROLLER_LOOP_STOPWATCH_NAME, SW_MS); + + struct controller_ctx ctx = { + .ovs_idl = ovs_idl_loop.idl, + .ovnsb_idl = ovnsb_idl_loop.idl + }; + struct ed_type_runtime_data ed_runtime_data; + struct ed_type_flow_output ed_flow_output; + + ENGINE_NODE(runtime_data, "runtime_data", &ctx); + ENGINE_NODE(flow_output, "flow_output", &ctx); + + engine_add_input(&en_flow_output, &en_runtime_data, NULL); + engine_init(&en_flow_output); + + ofctrl_init(&ed_flow_output.group_table, + &ed_flow_output.meter_table); unixctl_command_register("ct-zone-list", "", 0, 0, - ct_zone_list, &ct_zones); + ct_zone_list, &ed_runtime_data.ct_zones); struct pending_pkt pending_pkt = { .conn = NULL }; unixctl_command_register("inject-pkt", "MICROFLOW", 1, 1, inject_pkt, &pending_pkt); - stopwatch_create(CONTROLLER_LOOP_STOPWATCH_NAME, SW_MS); + uint64_t engine_run_id = 0; /* Main loop. */ exiting = false; while (!exiting) { @@ -671,145 +896,82 @@ main(int argc, char *argv[]) free(new_ovnsb_remote); } - struct controller_ctx ctx = { - .ovs_idl = ovs_idl_loop.idl, - .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop), - .ovnsb_idl = ovnsb_idl_loop.idl, - .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop), - }; + ctx.ovs_idl = ovs_idl_loop.idl; + ctx.ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop); + ctx.ovnsb_idl = ovnsb_idl_loop.idl; + ctx.ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop); update_probe_interval(&ctx, ovnsb_remote); update_ssl_config(ctx.ovs_idl); - /* Contains "struct local_datapath" nodes. */ - struct hmap local_datapaths = HMAP_INITIALIZER(&local_datapaths); - - /* Contains the name of each logical port resident on the local - * hypervisor. These logical ports include the VIFs (and their child - * logical ports, if any) that belong to VMs running on the hypervisor, - * l2gateway ports for which options:l2gateway-chassis designates the - * local hypervisor, and localnet ports. */ - struct sset local_lports = SSET_INITIALIZER(&local_lports); - /* Contains the same ports as local_lports, but in the format: - * _ */ - struct sset local_lport_ids = SSET_INITIALIZER(&local_lport_ids); - struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels); - const struct ovsrec_bridge *br_int = get_br_int(&ctx); + if (!br_int) { + br_int = create_br_int(&ctx); + } const char *chassis_id = get_chassis_id(ctx.ovs_idl); + const struct sbrec_chassis *chassis + = chassis_id ? chassis_run(&ctx, chassis_id, br_int) : NULL; - struct chassis_index chassis_index; - - chassis_index_init(&chassis_index, ctx.ovnsb_idl); - - const struct sbrec_chassis *chassis = NULL; - if (chassis_id) { - chassis = chassis_run(&ctx, chassis_id, br_int); - encaps_run(&ctx, br_int, chassis_id); - bfd_calculate_active_tunnels(br_int, &active_tunnels); - binding_run(&ctx, br_int, chassis, - &chassis_index, &active_tunnels, &local_datapaths, - &local_lports, &local_lport_ids); - } if (br_int && chassis) { - struct shash addr_sets = SHASH_INITIALIZER(&addr_sets); - addr_sets_init(&ctx, &addr_sets); - struct shash port_groups = SHASH_INITIALIZER(&port_groups); - port_groups_init(&ctx, &port_groups); - + ofctrl_run(br_int, &ed_runtime_data.pending_ct_zones); patch_run(&ctx, br_int, chassis); + encaps_run(&ctx, br_int, chassis_id); - enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int, - &pending_ct_zones); - - pinctrl_run(&ctx, br_int, chassis, &chassis_index, - &local_datapaths, &active_tunnels); - update_ct_zones(&local_lports, &local_datapaths, &ct_zones, - ct_zone_bitmap, &pending_ct_zones); - if (ctx.ovs_idl_txn) { - if (ofctrl_can_put()) { - stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, - time_msec()); - - commit_ct_zones(br_int, &pending_ct_zones); - - struct hmap flow_table = HMAP_INITIALIZER(&flow_table); - lflow_run(&ctx, chassis, - &chassis_index, &local_datapaths, &group_table, - &meter_table, &addr_sets, &port_groups, - &flow_table, &active_tunnels, &local_lport_ids); - - if (chassis_id) { - bfd_run(&ctx, br_int, chassis, &local_datapaths, - &chassis_index); - } - physical_run(&ctx, mff_ovn_geneve, - br_int, chassis, &ct_zones, - &flow_table, &local_datapaths, &local_lports, - &chassis_index, &active_tunnels); - - stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME, - time_msec()); - - ofctrl_put(&flow_table, &pending_ct_zones, - get_nb_cfg(ctx.ovnsb_idl)); - - hmap_destroy(&flow_table); - } - if (ctx.ovnsb_idl_txn) { - int64_t cur_cfg = ofctrl_get_cur_cfg(); - if (cur_cfg && cur_cfg != chassis->nb_cfg) { - sbrec_chassis_set_nb_cfg(chassis, cur_cfg); - } + if (ofctrl_can_put()) { + stopwatch_start(CONTROLLER_LOOP_STOPWATCH_NAME, + time_msec()); + engine_run(&en_flow_output, ++engine_run_id); + stopwatch_stop(CONTROLLER_LOOP_STOPWATCH_NAME, + time_msec()); + + if (ctx.ovs_idl_txn) { + commit_ct_zones(br_int, &ed_runtime_data.pending_ct_zones); + bfd_run(&ctx, br_int, chassis, + &ed_runtime_data.local_datapaths, + &ed_runtime_data.chassis_index); } + ofctrl_put(&ed_flow_output.flow_table, + &ed_runtime_data.pending_ct_zones, + get_nb_cfg(ctx.ovnsb_idl)); + } + pinctrl_run(&ctx, br_int, chassis, &ed_runtime_data.chassis_index, + &ed_runtime_data.local_datapaths, + &ed_runtime_data.active_tunnels); + + update_sb_monitors(ctx.ovnsb_idl, chassis, + &ed_runtime_data.local_lports, + &ed_runtime_data.local_datapaths); + + } + + if (ctx.ovnsb_idl_txn) { + int64_t cur_cfg = ofctrl_get_cur_cfg(); + if (cur_cfg && cur_cfg != chassis->nb_cfg) { + sbrec_chassis_set_nb_cfg(chassis, cur_cfg); } + } - if (pending_pkt.conn) { + + if (pending_pkt.conn) { + if (br_int && chassis) { char *error = ofctrl_inject_pkt(br_int, pending_pkt.flow_s, - &port_groups, &addr_sets); + &ed_runtime_data.port_groups, + &ed_runtime_data.addr_sets); if (error) { unixctl_command_reply_error(pending_pkt.conn, error); free(error); } else { unixctl_command_reply(pending_pkt.conn, NULL); } - pending_pkt.conn = NULL; - free(pending_pkt.flow_s); + } else { + unixctl_command_reply_error(pending_pkt.conn, + "ovn-controller not ready."); } - - update_sb_monitors(ctx.ovnsb_idl, chassis, - &local_lports, &local_datapaths); - - expr_const_sets_destroy(&addr_sets); - shash_destroy(&addr_sets); - expr_const_sets_destroy(&port_groups); - shash_destroy(&port_groups); - } - - /* If we haven't handled the pending packet insertion - * request, the system is not ready. */ - if (pending_pkt.conn) { - unixctl_command_reply_error(pending_pkt.conn, - "ovn-controller not ready."); pending_pkt.conn = NULL; free(pending_pkt.flow_s); } - chassis_index_destroy(&chassis_index); - - sset_destroy(&local_lports); - sset_destroy(&local_lport_ids); - sset_destroy(&active_tunnels); - - struct local_datapath *cur_node, *next_node; - HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, &local_datapaths) { - free(cur_node->peer_dps); - hmap_remove(&local_datapaths, &cur_node->hmap_node); - free(cur_node); - } - hmap_destroy(&local_datapaths); - unixctl_server_run(unixctl); unixctl_server_wait(unixctl); @@ -826,10 +988,11 @@ main(int argc, char *argv[]) if (ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop) == 1) { struct shash_node *iter, *iter_next; - SHASH_FOR_EACH_SAFE(iter, iter_next, &pending_ct_zones) { + SHASH_FOR_EACH_SAFE (iter, iter_next, + &ed_runtime_data.pending_ct_zones) { struct ct_zone_pending_entry *ctzpe = iter->data; if (ctzpe->state == CT_ZONE_DB_SENT) { - shash_delete(&pending_ct_zones, iter); + shash_delete(&ed_runtime_data.pending_ct_zones, iter); free(ctzpe); } } @@ -843,26 +1006,28 @@ main(int argc, char *argv[]) } } + engine_cleanup(&en_flow_output); + /* It's time to exit. Clean up the databases. */ bool done = false; while (!done) { - struct controller_ctx ctx = { + struct controller_ctx ctx_ = { .ovs_idl = ovs_idl_loop.idl, .ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop), .ovnsb_idl = ovnsb_idl_loop.idl, .ovnsb_idl_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop), }; - const struct ovsrec_bridge *br_int = get_br_int(&ctx); - const char *chassis_id = get_chassis_id(ctx.ovs_idl); + const struct ovsrec_bridge *br_int = get_br_int(&ctx_); + const char *chassis_id = get_chassis_id(ctx_.ovs_idl); const struct sbrec_chassis *chassis - = chassis_id ? get_chassis(ctx.ovnsb_idl, chassis_id) : NULL; + = chassis_id ? get_chassis(ctx_.ovnsb_idl, chassis_id) : NULL; /* Run all of the cleanup functions, even if one of them returns false. * We're done if all of them return true. */ - done = binding_cleanup(&ctx, chassis); - done = chassis_cleanup(&ctx, chassis) && done; - done = encaps_cleanup(&ctx, br_int) && done; + done = binding_cleanup(&ctx_, chassis); + done = chassis_cleanup(&ctx_, chassis) && done; + done = encaps_cleanup(&ctx_, br_int) && done; if (done) { poll_immediate_wake(); } @@ -877,12 +1042,6 @@ main(int argc, char *argv[]) ofctrl_destroy(); pinctrl_destroy(); - simap_destroy(&ct_zones); - shash_destroy(&pending_ct_zones); - - ovn_extend_table_destroy(&group_table); - ovn_extend_table_destroy(&meter_table); - ovsdb_idl_loop_destroy(&ovs_idl_loop); ovsdb_idl_loop_destroy(&ovnsb_idl_loop);