From patchwork Tue Mar 21 06:02:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Han Zhou X-Patchwork-Id: 1759302 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PggyM4BBNz2476 for ; Tue, 21 Mar 2023 17:03:23 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id C98D361100; Tue, 21 Mar 2023 06:03:17 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org C98D361100 X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dUiOl98orCxA; Tue, 21 Mar 2023 06:03:10 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp3.osuosl.org (Postfix) with ESMTPS id 4EBE5610FD; Tue, 21 Mar 2023 06:03:09 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 4EBE5610FD Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 218A3C0091; Tue, 21 Mar 2023 06:03:08 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1DFC6C0032 for ; Tue, 21 Mar 2023 06:03:03 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id D90754182D for ; Tue, 21 Mar 2023 06:03:02 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org D90754182D X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DOGBtHQe8uW6 for ; Tue, 21 Mar 2023 06:03:00 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 5133D417D0 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::224]) by smtp4.osuosl.org (Postfix) with ESMTPS id 5133D417D0 for ; Tue, 21 Mar 2023 06:02:59 +0000 (UTC) Received: (Authenticated sender: hzhou@ovn.org) by mail.gandi.net (Postfix) with ESMTPSA id 9E93CE0003; Tue, 21 Mar 2023 06:02:56 +0000 (UTC) From: Han Zhou To: dev@openvswitch.org Date: Mon, 20 Mar 2023 23:02:32 -0700 Message-Id: <20230321060235.2256118-5-hzhou@ovn.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230321060235.2256118-1-hzhou@ovn.org> References: <20230321060235.2256118-1-hzhou@ovn.org> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn 4/7] northd: Split switch and router datapaths. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Similar to the previous commit that splits switch ports and router ports, this patch splits the two types of datapaths in different hmap tables. This is also mainly to help for future incremental processing implementation. As a byproduct, the recompute performance is improved slightly. (Together with the previous commit that splits ports, scale test shows around ~4% improvment) Note: This patch didn't change the ovn_datapath structure, which is used by both switches and routers. It may be a followup improvement in the future if necessary, e.g. to reduce memory footprint. Signed-off-by: Han Zhou --- lib/lb.c | 15 +- lib/lb.h | 6 +- northd/en-lflow.c | 3 +- northd/en-sync-sb.c | 2 +- northd/mac-binding-aging.c | 2 +- northd/northd.c | 946 ++++++++++++++++++++----------------- northd/northd.h | 6 +- 7 files changed, 543 insertions(+), 437 deletions(-) diff --git a/lib/lb.c b/lib/lb.c index 66c8152750a1..37e05c31f918 100644 --- a/lib/lb.c +++ b/lib/lb.c @@ -521,7 +521,7 @@ ovn_lb_get_health_check(const struct nbrec_load_balancer *nbrec_lb, struct ovn_northd_lb * ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb, - size_t n_datapaths) + size_t n_ls_datapaths, size_t n_lr_datapaths) { bool template = smap_get_bool(&nbrec_lb->options, "template", false); bool is_udp = nullable_string_is_equal(nbrec_lb->protocol, "udp"); @@ -560,8 +560,8 @@ ovn_northd_lb_create(const struct nbrec_load_balancer *nbrec_lb, } lb->affinity_timeout = affinity_timeout; - lb->nb_ls_map = bitmap_allocate(n_datapaths); - lb->nb_lr_map = bitmap_allocate(n_datapaths); + lb->nb_ls_map = bitmap_allocate(n_ls_datapaths); + lb->nb_lr_map = bitmap_allocate(n_lr_datapaths); sset_init(&lb->ips_v4); sset_init(&lb->ips_v6); @@ -687,12 +687,13 @@ ovn_northd_lb_destroy(struct ovn_northd_lb *lb) /* Constructs a new 'struct ovn_lb_group' object from the Nb LB Group record * and a hash map of all existing 'struct ovn_northd_lb' objects. Space will - * be allocated for 'max_datapaths' logical switches and the same amount of + * be allocated for 'max_ls_datapaths' logical switches and 'max_lr_datapaths' * logical routers to which this LB Group is applied. Can be filled later * with ovn_lb_group_add_ls() and ovn_lb_group_add_lr() respectively. */ struct ovn_lb_group * ovn_lb_group_create(const struct nbrec_load_balancer_group *nbrec_lb_group, - const struct hmap *lbs, size_t max_datapaths) + const struct hmap *lbs, size_t max_ls_datapaths, + size_t max_lr_datapaths) { struct ovn_lb_group *lb_group; @@ -700,8 +701,8 @@ ovn_lb_group_create(const struct nbrec_load_balancer_group *nbrec_lb_group, lb_group->uuid = nbrec_lb_group->header_.uuid; lb_group->n_lbs = nbrec_lb_group->n_load_balancer; lb_group->lbs = xmalloc(lb_group->n_lbs * sizeof *lb_group->lbs); - lb_group->ls = xmalloc(max_datapaths * sizeof *lb_group->ls); - lb_group->lr = xmalloc(max_datapaths * sizeof *lb_group->lr); + lb_group->ls = xmalloc(max_ls_datapaths * sizeof *lb_group->ls); + lb_group->lr = xmalloc(max_lr_datapaths * sizeof *lb_group->lr); lb_group->lb_ips = ovn_lb_ip_set_create(); for (size_t i = 0; i < nbrec_lb_group->n_load_balancer; i++) { diff --git a/lib/lb.h b/lib/lb.h index ddd41703da44..ba48a0dac4f0 100644 --- a/lib/lb.h +++ b/lib/lb.h @@ -130,7 +130,8 @@ struct ovn_northd_lb_backend { }; struct ovn_northd_lb *ovn_northd_lb_create(const struct nbrec_load_balancer *, - size_t n_datapaths); + size_t n_ls_datapaths, + size_t n_lr_datapaths); struct ovn_northd_lb *ovn_northd_lb_find(const struct hmap *, const struct uuid *); const struct smap *ovn_northd_lb_get_vips(const struct ovn_northd_lb *); @@ -157,7 +158,8 @@ struct ovn_lb_group { struct ovn_lb_group *ovn_lb_group_create( const struct nbrec_load_balancer_group *, const struct hmap *lbs, - size_t max_datapaths); + size_t max_ls_datapaths, + size_t max_lr_datapaths); void ovn_lb_group_destroy(struct ovn_lb_group *lb_group); struct ovn_lb_group *ovn_lb_group_find(const struct hmap *lb_groups, const struct uuid *); diff --git a/northd/en-lflow.c b/northd/en-lflow.c index 9e7a2145e520..995c7cc10e33 100644 --- a/northd/en-lflow.c +++ b/northd/en-lflow.c @@ -54,7 +54,8 @@ void en_lflow_run(struct engine_node *node, void *data OVS_UNUSED) engine_get_input("SB_multicast_group", node), "sbrec_mcast_group_by_name"); - lflow_input.datapaths = &northd_data->datapaths; + lflow_input.ls_datapaths = &northd_data->ls_datapaths; + lflow_input.lr_datapaths = &northd_data->lr_datapaths; lflow_input.ls_ports = &northd_data->ls_ports; lflow_input.lr_ports = &northd_data->lr_ports; lflow_input.port_groups = &northd_data->port_groups; diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c index 6e33901a8a29..d4f4e60eabd6 100644 --- a/northd/en-sync-sb.c +++ b/northd/en-sync-sb.c @@ -91,7 +91,7 @@ en_sync_to_sb_addr_set_run(struct engine_node *node, void *data OVS_UNUSED) sync_addr_sets(nb_address_set_table, nb_port_group_table, sb_address_set_table, eng_ctx->ovnsb_idl_txn, - &northd_data->datapaths); + &northd_data->lr_datapaths); engine_set_node_state(node, EN_UPDATED); } diff --git a/northd/mac-binding-aging.c b/northd/mac-binding-aging.c index 1c30e979e1ac..3bdf1c2ea8d9 100644 --- a/northd/mac-binding-aging.c +++ b/northd/mac-binding-aging.c @@ -109,7 +109,7 @@ en_mac_binding_aging_run(struct engine_node *node, void *data OVS_UNUSED) "sbrec_mac_binding_by_datapath"); struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, &northd_data->datapaths) { + HMAP_FOR_EACH (od, key_node, &northd_data->lr_datapaths) { if (od->sb && od->nbr) { mac_binding_aging_run_for_datapath(od->sb, od->nbr, sbrec_mac_binding_by_datapath, diff --git a/northd/northd.c b/northd/northd.c index 10b16e685adf..baee1786469a 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -947,16 +947,24 @@ ovn_datapath_is_stale(const struct ovn_datapath *od) } static struct ovn_datapath * -ovn_datapath_from_sbrec(const struct hmap *datapaths, +ovn_datapath_from_sbrec(const struct hmap *ls_datapaths, + const struct hmap *lr_datapaths, const struct sbrec_datapath_binding *sb) { struct uuid key; + const struct hmap *dps; - if (!smap_get_uuid(&sb->external_ids, "logical-switch", &key) && - !smap_get_uuid(&sb->external_ids, "logical-router", &key)) { + if (smap_get_uuid(&sb->external_ids, "logical-switch", &key)) { + dps = ls_datapaths; + } else if (smap_get_uuid(&sb->external_ids, "logical-router", &key)) { + dps = lr_datapaths; + } else { + return NULL; + } + if (!dps) { return NULL; } - struct ovn_datapath *od = ovn_datapath_find(datapaths, &key); + struct ovn_datapath *od = ovn_datapath_find(dps, &key); if (od && (od->sb == sb)) { return od; } @@ -1375,9 +1383,15 @@ ovn_datapath_assign_requested_tnl_id(struct northd_input *input_data, } } -/* Array of all datapaths, with 'od->index' being their index in the array. */ -static struct ovn_datapath **datapaths_array = NULL; -static size_t n_datapaths = 0; /* Size of the 'datapaths_array'. */ +/* Array of ls datapaths, with 'od->index' being their index in the array. */ +static struct ovn_datapath **ls_datapaths_array = NULL; +/* Size of the 'ls_datapaths_array'. */ +static size_t n_ls_datapaths = 0; + +/* Array of lr datapaths, with 'od->index' being their index in the array. */ +static struct ovn_datapath **lr_datapaths_array = NULL; +/* Size of the 'lr_datapaths_array'. */ +static size_t n_lr_datapaths = 0; /* Updates the southbound Datapath_Binding table so that it contains the * logical switches and routers specified by the northbound database. @@ -1387,11 +1401,13 @@ static size_t n_datapaths = 0; /* Size of the 'datapaths_array'. */ static void build_datapaths(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, - struct hmap *datapaths, + struct hmap *ls_datapaths, + struct hmap *lr_datapaths, struct ovs_list *lr_list) { struct ovs_list sb_only, nb_only, both; + struct hmap *datapaths = ls_datapaths; join_datapaths(input_data, ovnsb_txn, datapaths, &sb_only, &nb_only, &both, lr_list); @@ -1444,17 +1460,37 @@ build_datapaths(struct northd_input *input_data, ovn_datapath_destroy(datapaths, od); } + /* Move lr datapaths to lr_datapaths, and ls datapaths will + * remain in datapaths/ls_datapaths. */ + HMAP_FOR_EACH_SAFE (od, key_node, datapaths) { + if (!od->nbr) { + ovs_assert(od->nbs); + continue; + } + hmap_remove(datapaths, &od->key_node); + hmap_insert(lr_datapaths, &od->key_node, od->key_node.hash); + } + /* Assign unique sequential indexes to all datapaths. These are not * visible outside of the northd loop, so, unlike the tunnel keys, it * doesn't matter if they are different on every iteration. */ size_t index = 0; - n_datapaths = hmap_count(datapaths); - datapaths_array = xrealloc(datapaths_array, - n_datapaths * sizeof *datapaths_array); - HMAP_FOR_EACH (od, key_node, datapaths) { + n_ls_datapaths = hmap_count(ls_datapaths); + ls_datapaths_array = xrealloc(ls_datapaths_array, + n_ls_datapaths * sizeof *ls_datapaths_array); + HMAP_FOR_EACH (od, key_node, ls_datapaths) { + od->index = index; + ls_datapaths_array[index++] = od; + } + + index = 0; + n_lr_datapaths = hmap_count(lr_datapaths); + lr_datapaths_array = xrealloc(lr_datapaths_array, + n_lr_datapaths * sizeof *lr_datapaths_array); + HMAP_FOR_EACH (od, key_node, lr_datapaths) { od->index = index; - datapaths_array[index++] = od; + lr_datapaths_array[index++] = od; } } @@ -2243,7 +2279,7 @@ update_dynamic_addresses(struct dynamic_address_update *update) } static void -build_ipam(struct hmap *datapaths, struct hmap *ls_ports) +build_ipam(struct hmap *ls_datapaths, struct hmap *ls_ports) { /* IPAM generally stands for IP address management. In non-virtualized * world, MAC addresses come with the hardware. But, with virtualized @@ -2257,10 +2293,8 @@ build_ipam(struct hmap *datapaths, struct hmap *ls_ports) struct ovs_list updates; ovs_list_init(&updates); - HMAP_FOR_EACH (od, key_node, datapaths) { - if (!od->nbs) { - continue; - } + HMAP_FOR_EACH (od, key_node, ls_datapaths) { + ovs_assert(od->nbs); for (size_t i = 0; i < od->nbs->n_ports; i++) { const struct nbrec_logical_switch_port *nbsp = od->nbs->ports[i]; @@ -2440,8 +2474,8 @@ tag_alloc_create_new_tag(struct hmap *tag_alloc_table, static void join_logical_ports(struct northd_input *input_data, - struct hmap *datapaths, struct hmap *ports, - struct hmap *chassis_qdisc_queues, + struct hmap *ls_datapaths, struct hmap *lr_datapaths, + struct hmap *ports, struct hmap *chassis_qdisc_queues, struct hmap *tag_alloc_table, struct ovs_list *sb_only, struct ovs_list *nb_only, struct ovs_list *both) { @@ -2458,225 +2492,226 @@ join_logical_ports(struct northd_input *input_data, } struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { - if (od->nbs) { - size_t n_allocated_localnet_ports = 0; - for (size_t i = 0; i < od->nbs->n_ports; i++) { - const struct nbrec_logical_switch_port *nbsp - = od->nbs->ports[i]; - struct ovn_port *op = ovn_port_find_bound(ports, nbsp->name); - if (op && (op->od || op->nbsp || op->nbrp)) { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "duplicate logical port %s", nbsp->name); - continue; - } else if (op && (!op->sb || op->sb->datapath == od->sb)) { - /* - * Handle cases where lport type was explicitly changed - * in the NBDB, in such cases: - * 1. remove the current sbrec of the affected lport from - * the port_binding table. - * - * 2. create a new sbrec with the same logical_port as the - * deleted lport and add it to the nb_only list which - * will make the northd handle this lport as a new - * created one and recompute everything that is needed - * for this lport. - * - * This change will affect container/virtual lport type - * changes only for now, this change is needed in - * contaier/virtual lport cases to avoid port type - * conflicts in the ovn-controller when the user clears - * the parent_port field in the container lport or updated - * the lport type. - * - */ - bool update_sbrec = false; - if (op->sb && lsp_is_type_changed(op->sb, nbsp, - &update_sbrec) - && update_sbrec) { - ovs_list_remove(&op->list); - sbrec_port_binding_delete(op->sb); - ovn_port_destroy(ports, op); - op = ovn_port_create(ports, nbsp->name, nbsp, - NULL, NULL); - ovs_list_push_back(nb_only, &op->list); - } else { - ovn_port_set_nb(op, nbsp, NULL); - ovs_list_remove(&op->list); - - uint32_t queue_id = smap_get_int(&op->sb->options, - "qdisc_queue_id", 0); - if (queue_id && op->sb->chassis) { - add_chassis_queue( - chassis_qdisc_queues, - &op->sb->chassis->header_.uuid, - queue_id); - } - - ovs_list_push_back(both, &op->list); - - /* This port exists due to a SB binding, but should - * not have been initialized fully. */ - ovs_assert(!op->n_lsp_addrs && !op->n_ps_addrs); - } - } else { - op = ovn_port_create(ports, nbsp->name, nbsp, NULL, NULL); + HMAP_FOR_EACH (od, key_node, ls_datapaths) { + ovs_assert(od->nbs); + size_t n_allocated_localnet_ports = 0; + for (size_t i = 0; i < od->nbs->n_ports; i++) { + const struct nbrec_logical_switch_port *nbsp + = od->nbs->ports[i]; + struct ovn_port *op = ovn_port_find_bound(ports, nbsp->name); + if (op && (op->od || op->nbsp || op->nbrp)) { + static struct vlog_rate_limit rl + = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "duplicate logical port %s", nbsp->name); + continue; + } else if (op && (!op->sb || op->sb->datapath == od->sb)) { + /* + * Handle cases where lport type was explicitly changed + * in the NBDB, in such cases: + * 1. remove the current sbrec of the affected lport from + * the port_binding table. + * + * 2. create a new sbrec with the same logical_port as the + * deleted lport and add it to the nb_only list which + * will make the northd handle this lport as a new + * created one and recompute everything that is needed + * for this lport. + * + * This change will affect container/virtual lport type + * changes only for now, this change is needed in + * contaier/virtual lport cases to avoid port type + * conflicts in the ovn-controller when the user clears + * the parent_port field in the container lport or updated + * the lport type. + * + */ + bool update_sbrec = false; + if (op->sb && lsp_is_type_changed(op->sb, nbsp, + &update_sbrec) + && update_sbrec) { + ovs_list_remove(&op->list); + sbrec_port_binding_delete(op->sb); + ovn_port_destroy(ports, op); + op = ovn_port_create(ports, nbsp->name, nbsp, + NULL, NULL); ovs_list_push_back(nb_only, &op->list); - } + } else { + ovn_port_set_nb(op, nbsp, NULL); + ovs_list_remove(&op->list); - if (lsp_is_localnet(nbsp)) { - if (od->n_localnet_ports >= n_allocated_localnet_ports) { - od->localnet_ports = x2nrealloc( - od->localnet_ports, &n_allocated_localnet_ports, - sizeof *od->localnet_ports); - } - od->localnet_ports[od->n_localnet_ports++] = op; - } + uint32_t queue_id = smap_get_int(&op->sb->options, + "qdisc_queue_id", 0); + if (queue_id && op->sb->chassis) { + add_chassis_queue( + chassis_qdisc_queues, + &op->sb->chassis->header_.uuid, + queue_id); + } - if (lsp_is_vtep(nbsp)) { - od->has_vtep_lports = true; - } + ovs_list_push_back(both, &op->list); - op->lsp_addrs - = xmalloc(sizeof *op->lsp_addrs * nbsp->n_addresses); - for (size_t j = 0; j < nbsp->n_addresses; j++) { - if (!strcmp(nbsp->addresses[j], "unknown")) { - op->has_unknown = true; - continue; - } - if (!strcmp(nbsp->addresses[j], "router")) { - continue; - } - if (is_dynamic_lsp_address(nbsp->addresses[j])) { - continue; - } else if (!extract_lsp_addresses(nbsp->addresses[j], - &op->lsp_addrs[op->n_lsp_addrs])) { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_INFO_RL(&rl, "invalid syntax '%s' in logical " - "switch port addresses. No MAC " - "address found", - op->nbsp->addresses[j]); - continue; - } - op->n_lsp_addrs++; - } - op->n_lsp_non_router_addrs = op->n_lsp_addrs; - - op->ps_addrs - = xmalloc(sizeof *op->ps_addrs * nbsp->n_port_security); - for (size_t j = 0; j < nbsp->n_port_security; j++) { - if (!extract_lsp_addresses(nbsp->port_security[j], - &op->ps_addrs[op->n_ps_addrs])) { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_INFO_RL(&rl, "invalid syntax '%s' in port " - "security. No MAC address found", - op->nbsp->port_security[j]); - continue; - } - op->n_ps_addrs++; + /* This port exists due to a SB binding, but should + * not have been initialized fully. */ + ovs_assert(!op->n_lsp_addrs && !op->n_ps_addrs); } + } else { + op = ovn_port_create(ports, nbsp->name, nbsp, NULL, NULL); + ovs_list_push_back(nb_only, &op->list); + } - op->od = od; - ovs_list_push_back(&od->port_list, &op->dp_node); - tag_alloc_add_existing_tags(tag_alloc_table, nbsp); + if (lsp_is_localnet(nbsp)) { + if (od->n_localnet_ports >= n_allocated_localnet_ports) { + od->localnet_ports = x2nrealloc( + od->localnet_ports, &n_allocated_localnet_ports, + sizeof *od->localnet_ports); + } + od->localnet_ports[od->n_localnet_ports++] = op; } - } else { - size_t n_allocated_l3dgw_ports = 0; - for (size_t i = 0; i < od->nbr->n_ports; i++) { - const struct nbrec_logical_router_port *nbrp - = od->nbr->ports[i]; - struct lport_addresses lrp_networks; - if (!extract_lrp_networks(nbrp, &lrp_networks)) { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "bad 'mac' %s", nbrp->mac); + if (lsp_is_vtep(nbsp)) { + od->has_vtep_lports = true; + } + + op->lsp_addrs + = xmalloc(sizeof *op->lsp_addrs * nbsp->n_addresses); + for (size_t j = 0; j < nbsp->n_addresses; j++) { + if (!strcmp(nbsp->addresses[j], "unknown")) { + op->has_unknown = true; continue; } - - if (!lrp_networks.n_ipv4_addrs && !lrp_networks.n_ipv6_addrs) { + if (!strcmp(nbsp->addresses[j], "router")) { continue; } - - struct ovn_port *op = ovn_port_find_bound(ports, nbrp->name); - if (op && (op->od || op->nbsp || op->nbrp)) { + if (is_dynamic_lsp_address(nbsp->addresses[j])) { + continue; + } else if (!extract_lsp_addresses(nbsp->addresses[j], + &op->lsp_addrs[op->n_lsp_addrs])) { static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "duplicate logical router port %s", - nbrp->name); - destroy_lport_addresses(&lrp_networks); + = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_INFO_RL(&rl, "invalid syntax '%s' in logical " + "switch port addresses. No MAC " + "address found", + op->nbsp->addresses[j]); continue; - } else if (op && (!op->sb || op->sb->datapath == od->sb)) { - ovn_port_set_nb(op, NULL, nbrp); - ovs_list_remove(&op->list); - ovs_list_push_back(both, &op->list); + } + op->n_lsp_addrs++; + } + op->n_lsp_non_router_addrs = op->n_lsp_addrs; - /* This port exists but should not have been - * initialized fully. */ - ovs_assert(!op->lrp_networks.n_ipv4_addrs - && !op->lrp_networks.n_ipv6_addrs); - } else { - op = ovn_port_create(ports, nbrp->name, NULL, nbrp, NULL); - ovs_list_push_back(nb_only, &op->list); + op->ps_addrs + = xmalloc(sizeof *op->ps_addrs * nbsp->n_port_security); + for (size_t j = 0; j < nbsp->n_port_security; j++) { + if (!extract_lsp_addresses(nbsp->port_security[j], + &op->ps_addrs[op->n_ps_addrs])) { + static struct vlog_rate_limit rl + = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_INFO_RL(&rl, "invalid syntax '%s' in port " + "security. No MAC address found", + op->nbsp->port_security[j]); + continue; } + op->n_ps_addrs++; + } - op->lrp_networks = lrp_networks; - op->od = od; - ovs_list_push_back(&od->port_list, &op->dp_node); + op->od = od; + ovs_list_push_back(&od->port_list, &op->dp_node); + tag_alloc_add_existing_tags(tag_alloc_table, nbsp); + } + } + HMAP_FOR_EACH (od, key_node, lr_datapaths) { + ovs_assert(od->nbr); + size_t n_allocated_l3dgw_ports = 0; + for (size_t i = 0; i < od->nbr->n_ports; i++) { + const struct nbrec_logical_router_port *nbrp + = od->nbr->ports[i]; - if (!od->redirect_bridged) { - const char *redirect_type = - smap_get(&nbrp->options, "redirect-type"); - od->redirect_bridged = - redirect_type && !strcasecmp(redirect_type, "bridged"); - } + struct lport_addresses lrp_networks; + if (!extract_lrp_networks(nbrp, &lrp_networks)) { + static struct vlog_rate_limit rl + = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "bad 'mac' %s", nbrp->mac); + continue; + } - if (op->nbrp->ha_chassis_group || - op->nbrp->n_gateway_chassis) { - /* Additional "derived" ovn_port crp represents the - * instance of op on the gateway chassis. */ - const char *gw_chassis = smap_get(&op->od->nbr->options, - "chassis"); - if (gw_chassis) { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "Bad configuration: distributed " - "gateway port configured on port %s " - "on L3 gateway router", nbrp->name); - continue; - } + if (!lrp_networks.n_ipv4_addrs && !lrp_networks.n_ipv6_addrs) { + continue; + } - char *redirect_name = - ovn_chassis_redirect_name(nbrp->name); - struct ovn_port *crp = ovn_port_find(ports, redirect_name); - if (crp && crp->sb && crp->sb->datapath == od->sb) { - ovn_port_set_nb(crp, NULL, nbrp); - ovs_list_remove(&crp->list); - ovs_list_push_back(both, &crp->list); - } else { - crp = ovn_port_create(ports, redirect_name, - NULL, nbrp, NULL); - ovs_list_push_back(nb_only, &crp->list); - } - crp->l3dgw_port = op; - op->cr_port = crp; - crp->od = od; - free(redirect_name); + struct ovn_port *op = ovn_port_find_bound(ports, nbrp->name); + if (op && (op->od || op->nbsp || op->nbrp)) { + static struct vlog_rate_limit rl + = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "duplicate logical router port %s", + nbrp->name); + destroy_lport_addresses(&lrp_networks); + continue; + } else if (op && (!op->sb || op->sb->datapath == od->sb)) { + ovn_port_set_nb(op, NULL, nbrp); + ovs_list_remove(&op->list); + ovs_list_push_back(both, &op->list); + + /* This port exists but should not have been + * initialized fully. */ + ovs_assert(!op->lrp_networks.n_ipv4_addrs + && !op->lrp_networks.n_ipv6_addrs); + } else { + op = ovn_port_create(ports, nbrp->name, NULL, nbrp, NULL); + ovs_list_push_back(nb_only, &op->list); + } - /* Add to l3dgw_ports in od, for later use during flow - * creation. */ - if (od->n_l3dgw_ports == n_allocated_l3dgw_ports) { - od->l3dgw_ports = x2nrealloc(od->l3dgw_ports, - &n_allocated_l3dgw_ports, - sizeof *od->l3dgw_ports); - } - od->l3dgw_ports[od->n_l3dgw_ports++] = op; + op->lrp_networks = lrp_networks; + op->od = od; + ovs_list_push_back(&od->port_list, &op->dp_node); - assign_routable_addresses(op); + if (!od->redirect_bridged) { + const char *redirect_type = + smap_get(&nbrp->options, "redirect-type"); + od->redirect_bridged = + redirect_type && !strcasecmp(redirect_type, "bridged"); + } + + if (op->nbrp->ha_chassis_group || + op->nbrp->n_gateway_chassis) { + /* Additional "derived" ovn_port crp represents the + * instance of op on the gateway chassis. */ + const char *gw_chassis = smap_get(&op->od->nbr->options, + "chassis"); + if (gw_chassis) { + static struct vlog_rate_limit rl + = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "Bad configuration: distributed " + "gateway port configured on port %s " + "on L3 gateway router", nbrp->name); + continue; } + + char *redirect_name = + ovn_chassis_redirect_name(nbrp->name); + struct ovn_port *crp = ovn_port_find(ports, redirect_name); + if (crp && crp->sb && crp->sb->datapath == od->sb) { + ovn_port_set_nb(crp, NULL, nbrp); + ovs_list_remove(&crp->list); + ovs_list_push_back(both, &crp->list); + } else { + crp = ovn_port_create(ports, redirect_name, + NULL, nbrp, NULL); + ovs_list_push_back(nb_only, &crp->list); + } + crp->l3dgw_port = op; + op->cr_port = crp; + crp->od = od; + free(redirect_name); + + /* Add to l3dgw_ports in od, for later use during flow + * creation. */ + if (od->n_l3dgw_ports == n_allocated_l3dgw_ports) { + od->l3dgw_ports = x2nrealloc(od->l3dgw_ports, + &n_allocated_l3dgw_ports, + sizeof *od->l3dgw_ports); + } + od->l3dgw_ports[od->n_l3dgw_ports++] = op; + + assign_routable_addresses(op); } } } @@ -3704,14 +3739,14 @@ ovn_port_update_sbrec(struct northd_input *input_data, * deleted. */ static void cleanup_mac_bindings(struct northd_input *input_data, - struct hmap *datapaths, + struct hmap *lr_datapaths, struct hmap *lr_ports) { const struct sbrec_mac_binding *b; SBREC_MAC_BINDING_TABLE_FOR_EACH_SAFE (b, input_data->sbrec_mac_binding_table) { const struct ovn_datapath *od = - ovn_datapath_from_sbrec(datapaths, b->datapath); + ovn_datapath_from_sbrec(NULL, lr_datapaths, b->datapath); if (!od || ovn_datapath_is_stale(od) || !ovn_port_find(lr_ports, b->logical_port)) { @@ -3735,14 +3770,14 @@ cleanup_sb_ha_chassis_groups(struct northd_input *input_data, static void cleanup_stale_fdb_entries(struct northd_input *input_data, - struct hmap *datapaths) + struct hmap *ls_datapaths) { const struct sbrec_fdb *fdb_e; SBREC_FDB_TABLE_FOR_EACH_SAFE (fdb_e, input_data->sbrec_fdb_table) { bool delete = true; struct ovn_datapath *od - = ovn_datapath_find_by_key(datapaths, fdb_e->dp_key); + = ovn_datapath_find_by_key(ls_datapaths, fdb_e->dp_key); if (od) { if (ovn_tnlid_present(&od->port_tnlids, fdb_e->port_key)) { delete = false; @@ -3988,8 +4023,8 @@ build_lrouter_lb_ips(struct ovn_lb_ip_set *lb_ips, } static void -build_lbs(struct northd_input *input_data, struct hmap *datapaths, - struct hmap *lbs, struct hmap *lb_groups) +build_lbs(struct northd_input *input_data, struct hmap *ls_datapaths, + struct hmap *lr_datapaths, struct hmap *lbs, struct hmap *lb_groups) { const struct nbrec_load_balancer_group *nbrec_lb_group; struct ovn_lb_group *lb_group; @@ -4002,7 +4037,8 @@ build_lbs(struct northd_input *input_data, struct hmap *datapaths, NBREC_LOAD_BALANCER_TABLE_FOR_EACH (nbrec_lb, input_data->nbrec_load_balancer_table) { struct ovn_northd_lb *lb_nb = ovn_northd_lb_create(nbrec_lb, - n_datapaths); + n_ls_datapaths, + n_lr_datapaths); hmap_insert(lbs, &lb_nb->hmap_node, uuid_hash(&nbrec_lb->header_.uuid)); } @@ -4010,7 +4046,8 @@ build_lbs(struct northd_input *input_data, struct hmap *datapaths, NBREC_LOAD_BALANCER_GROUP_TABLE_FOR_EACH (nbrec_lb_group, input_data->nbrec_load_balancer_group_table) { lb_group = ovn_lb_group_create(nbrec_lb_group, lbs, - hmap_count(datapaths)); + hmap_count(ls_datapaths), + hmap_count(lr_datapaths)); for (size_t i = 0; i < lb_group->n_lbs; i++) { build_lrouter_lb_ips(lb_group->lb_ips, lb_group->lbs[i]); @@ -4021,7 +4058,7 @@ build_lbs(struct northd_input *input_data, struct hmap *datapaths, } struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { + HMAP_FOR_EACH (od, key_node, ls_datapaths) { if (!od->nbs) { continue; } @@ -4048,7 +4085,7 @@ build_lbs(struct northd_input *input_data, struct hmap *datapaths, } } - HMAP_FOR_EACH (od, key_node, datapaths) { + HMAP_FOR_EACH (od, key_node, lr_datapaths) { if (!od->nbr) { continue; } @@ -4198,11 +4235,11 @@ build_lrouter_lb_reachable_ips(struct ovn_datapath *od, } static void -build_lrouter_lbs_check(const struct hmap *datapaths) +build_lrouter_lbs_check(const struct hmap *lr_datapaths) { struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { + HMAP_FOR_EACH (od, key_node, lr_datapaths) { if (!od->nbr) { continue; } @@ -4221,12 +4258,12 @@ build_lrouter_lbs_check(const struct hmap *datapaths) } static void -build_lrouter_lbs_reachable_ips(struct hmap *datapaths, struct hmap *lbs, +build_lrouter_lbs_reachable_ips(struct hmap *lr_datapaths, struct hmap *lbs, struct hmap *lb_groups) { struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { + HMAP_FOR_EACH (od, key_node, lr_datapaths) { if (!od->nbr) { continue; } @@ -4263,8 +4300,8 @@ build_lswitch_lbs_from_lrouter(struct hmap *lbs, struct hmap *lb_groups) size_t index; HMAP_FOR_EACH (lb, hmap_node, lbs) { - BITMAP_FOR_EACH_1 (index, n_datapaths, lb->nb_lr_map) { - struct ovn_datapath *od = datapaths_array[index]; + BITMAP_FOR_EACH_1 (index, n_lr_datapaths, lb->nb_lr_map) { + struct ovn_datapath *od = lr_datapaths_array[index]; ovn_northd_lb_add_ls(lb, od->n_ls_peers, od->ls_peers); } } @@ -4288,8 +4325,8 @@ build_lb_count_dps(struct hmap *lbs) struct ovn_northd_lb *lb; HMAP_FOR_EACH (lb, hmap_node, lbs) { - lb->n_nb_lr = bitmap_count1(lb->nb_lr_map, n_datapaths); - lb->n_nb_ls = bitmap_count1(lb->nb_ls_map, n_datapaths); + lb->n_nb_lr = bitmap_count1(lb->nb_lr_map, n_lr_datapaths); + lb->n_nb_ls = bitmap_count1(lb->nb_ls_map, n_ls_datapaths); } } @@ -4298,13 +4335,13 @@ build_lb_count_dps(struct hmap *lbs) * networks to have been parsed. */ static void -build_lb_port_related_data(struct hmap *datapaths, struct hmap *ls_ports, +build_lb_port_related_data(struct hmap *lr_datapaths, struct hmap *ls_ports, struct hmap *lbs, struct hmap *lb_groups, struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn) { - build_lrouter_lbs_check(datapaths); - build_lrouter_lbs_reachable_ips(datapaths, lbs, lb_groups); + build_lrouter_lbs_check(lr_datapaths); + build_lrouter_lbs_reachable_ips(lr_datapaths, lbs, lb_groups); build_lb_svcs(input_data, ovnsb_txn, ls_ports, lbs); build_lswitch_lbs_from_lrouter(lbs, lb_groups); } @@ -4318,12 +4355,13 @@ struct ovn_dp_group { static struct ovn_dp_group * ovn_dp_group_find(const struct hmap *dp_groups, - const unsigned long *dpg_bitmap, uint32_t hash) + const unsigned long *dpg_bitmap, size_t bitmap_len, + uint32_t hash) { struct ovn_dp_group *dpg; HMAP_FOR_EACH_WITH_HASH (dpg, node, hash, dp_groups) { - if (bitmap_equal(dpg->bitmap, dpg_bitmap, n_datapaths)) { + if (bitmap_equal(dpg->bitmap, dpg_bitmap, bitmap_len)) { return dpg; } } @@ -4332,14 +4370,16 @@ ovn_dp_group_find(const struct hmap *dp_groups, static struct sbrec_logical_dp_group * ovn_sb_insert_logical_dp_group(struct ovsdb_idl_txn *ovnsb_txn, - const unsigned long *dpg_bitmap) + const unsigned long *dpg_bitmap, + size_t bitmap_len, + struct ovn_datapath **datapaths_array) { struct sbrec_logical_dp_group *dp_group; const struct sbrec_datapath_binding **sb; size_t n = 0, index; - sb = xmalloc(bitmap_count1(dpg_bitmap, n_datapaths) * sizeof *sb); - BITMAP_FOR_EACH_1 (index, n_datapaths, dpg_bitmap) { + sb = xmalloc(bitmap_count1(dpg_bitmap, bitmap_len) * sizeof *sb); + BITMAP_FOR_EACH_1 (index, bitmap_len, dpg_bitmap) { sb[n++] = datapaths_array[index]->sb; } dp_group = sbrec_logical_dp_group_insert(ovnsb_txn); @@ -4355,7 +4395,7 @@ ovn_sb_insert_logical_dp_group(struct ovsdb_idl_txn *ovnsb_txn, */ static void sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, - struct hmap *datapaths, struct hmap *lbs) + struct hmap *ls_datapaths, struct hmap *lbs) { struct hmap dp_groups = HMAP_INITIALIZER(&dp_groups); struct ovn_northd_lb *lb; @@ -4401,11 +4441,11 @@ sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, struct ovn_dp_group *dpg = xzalloc(sizeof *dpg); size_t i, n = 0; - dpg->bitmap = bitmap_allocate(n_datapaths); + dpg->bitmap = bitmap_allocate(n_ls_datapaths); for (i = 0; i < dp_group->n_datapaths; i++) { struct ovn_datapath *datapath_od; - datapath_od = ovn_datapath_from_sbrec(datapaths, + datapath_od = ovn_datapath_from_sbrec(ls_datapaths, NULL, dp_group->datapaths[i]); if (!datapath_od || ovn_datapath_is_stale(datapath_od)) { break; @@ -4416,7 +4456,8 @@ sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, if (i == dp_group->n_datapaths) { uint32_t hash = hash_int(n, 0); - if (!ovn_dp_group_find(&dp_groups, dpg->bitmap, hash)) { + if (!ovn_dp_group_find(&dp_groups, dpg->bitmap, n_ls_datapaths, + hash)) { dpg->dp_group = dp_group; hmap_insert(&dp_groups, &dpg->node, hash); continue; @@ -4459,12 +4500,15 @@ sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, uint32_t hash; hash = hash_int(lb->n_nb_ls, 0); - dpg = ovn_dp_group_find(&dp_groups, lb->nb_ls_map, hash); + dpg = ovn_dp_group_find(&dp_groups, lb->nb_ls_map, n_ls_datapaths, + hash); if (!dpg) { dpg = xzalloc(sizeof *dpg); dpg->dp_group = ovn_sb_insert_logical_dp_group(ovnsb_txn, - lb->nb_ls_map); - dpg->bitmap = bitmap_clone(lb->nb_ls_map, n_datapaths); + lb->nb_ls_map, + n_ls_datapaths, + ls_datapaths_array); + dpg->bitmap = bitmap_clone(lb->nb_ls_map, n_ls_datapaths); hmap_insert(&dp_groups, &dpg->node, hash); } @@ -4490,10 +4534,8 @@ sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, * schema for compatibility reasons. Reset it to empty, just in case. */ struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { - if (!od->nbs) { - continue; - } + HMAP_FOR_EACH (od, key_node, ls_datapaths) { + ovs_assert(od->nbs); if (od->sb->n_load_balancers) { sbrec_datapath_binding_set_load_balancers(od->sb, NULL, 0); @@ -4572,8 +4614,8 @@ build_ports(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, struct ovsdb_idl_index *sbrec_chassis_by_name, struct ovsdb_idl_index *sbrec_chassis_by_hostname, - struct hmap *datapaths, struct hmap *ls_ports, - struct hmap *lr_ports) + struct hmap *ls_datapaths, struct hmap *lr_datapaths, + struct hmap *ls_ports, struct hmap *lr_ports) { struct ovs_list sb_only, nb_only, both; struct hmap tag_alloc_table = HMAP_INITIALIZER(&tag_alloc_table); @@ -4586,8 +4628,8 @@ build_ports(struct northd_input *input_data, /* Borrow ls_ports for joining NB and SB for both LSPs and LRPs. * We will split them later. */ struct hmap *ports = ls_ports; - join_logical_ports(input_data, - datapaths, ports, &chassis_qdisc_queues, + join_logical_ports(input_data, ls_datapaths, lr_datapaths, + ports, &chassis_qdisc_queues, &tag_alloc_table, &sb_only, &nb_only, &both); /* Purge stale Mac_Bindings if ports are deleted. */ @@ -4669,7 +4711,7 @@ build_ports(struct northd_input *input_data, } if (remove_mac_bindings) { - cleanup_mac_bindings(input_data, datapaths, lr_ports); + cleanup_mac_bindings(input_data, lr_datapaths, lr_ports); } tag_alloc_destroy(&tag_alloc_table); @@ -5101,11 +5143,11 @@ static int parallelization_state = STATE_NULL; static void ovn_lflow_init(struct ovn_lflow *lflow, struct ovn_datapath *od, - enum ovn_stage stage, uint16_t priority, + size_t dp_bitmap_len, enum ovn_stage stage, uint16_t priority, char *match, char *actions, char *io_port, char *ctrl_meter, char *stage_hint, const char *where) { - lflow->dpg_bitmap = bitmap_allocate(n_datapaths); + lflow->dpg_bitmap = bitmap_allocate(dp_bitmap_len); lflow->od = od; lflow->stage = stage; lflow->priority = priority; @@ -5219,14 +5261,15 @@ static thread_local size_t thread_lflow_counter = 0; static void ovn_dp_group_add_with_reference(struct ovn_lflow *lflow_ref, const struct ovn_datapath *od, - const unsigned long *dp_bitmap) + const unsigned long *dp_bitmap, + size_t bitmap_len) OVS_REQUIRES(fake_hash_mutex) { if (od) { bitmap_set1(lflow_ref->dpg_bitmap, od->index); } if (dp_bitmap) { - bitmap_or(lflow_ref->dpg_bitmap, dp_bitmap, n_datapaths); + bitmap_or(lflow_ref->dpg_bitmap, dp_bitmap, bitmap_len); } } @@ -5246,10 +5289,13 @@ do_ovn_lflow_add(struct hmap *lflow_map, const struct ovn_datapath *od, struct ovn_lflow *old_lflow; struct ovn_lflow *lflow; + size_t n_datapaths = ovn_stage_to_datapath_type(stage) == DP_SWITCH ? + n_ls_datapaths : n_lr_datapaths; + old_lflow = ovn_lflow_find(lflow_map, NULL, stage, priority, match, actions, ctrl_meter, hash); if (old_lflow) { - ovn_dp_group_add_with_reference(old_lflow, od, dp_bitmap); + ovn_dp_group_add_with_reference(old_lflow, od, dp_bitmap, n_datapaths); return; } @@ -5257,13 +5303,13 @@ do_ovn_lflow_add(struct hmap *lflow_map, const struct ovn_datapath *od, /* While adding new logical flows we're not setting single datapath, but * collecting a group. 'od' will be updated later for all flows with only * one datapath in a group, so it could be hashed correctly. */ - ovn_lflow_init(lflow, NULL, stage, priority, + ovn_lflow_init(lflow, NULL, n_datapaths, stage, priority, xstrdup(match), xstrdup(actions), io_port ? xstrdup(io_port) : NULL, nullable_xstrdup(ctrl_meter), ovn_lflow_hint(stage_hint), where); - ovn_dp_group_add_with_reference(lflow, od, dp_bitmap); + ovn_dp_group_add_with_reference(lflow, od, dp_bitmap, n_datapaths); if (parallelization_state != STATE_USE_PARALLELIZATION) { hmap_insert(lflow_map, &lflow->hmap_node, hash); @@ -5772,9 +5818,7 @@ static void build_lswitch_learn_fdb_od( struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbs) { - return; - } + ovs_assert(od->nbs); ovn_lflow_add(lflows, od, S_SWITCH_IN_LOOKUP_FDB, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_SWITCH_IN_PUT_FDB, 0, "1", "next;"); } @@ -5786,9 +5830,7 @@ static void build_lswitch_output_port_sec_od(struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbs) { - return; - } + ovs_assert(od->nbs); ovn_lflow_add(lflows, od, S_SWITCH_OUT_CHECK_PORT_SEC, 100, "eth.mcast", REGBIT_PORT_SEC_DROP" = 0; next;"); ovn_lflow_add(lflows, od, S_SWITCH_OUT_CHECK_PORT_SEC, 0, "1", @@ -7166,7 +7208,7 @@ build_lb_affinity_lr_flows(struct hmap *lflows, struct ovn_northd_lb *lb, char *lb_action, const unsigned long *dp_bitmap) { if (!lb->affinity_timeout || - bitmap_is_all_zeros(dp_bitmap, n_datapaths)) { + bitmap_is_all_zeros(dp_bitmap, n_lr_datapaths)) { return; } @@ -7476,9 +7518,7 @@ static void build_lswitch_lb_affinity_default_flows(struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbs) { - return; - } + ovs_assert(od->nbs); ovn_lflow_add(lflows, od, S_SWITCH_IN_LB_AFF_CHECK, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_SWITCH_IN_LB_AFF_LEARN, 0, "1", "next;"); } @@ -7487,9 +7527,7 @@ static void build_lrouter_lb_affinity_default_flows(struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); ovn_lflow_add(lflows, od, S_ROUTER_IN_LB_AFF_CHECK, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_ROUTER_IN_LB_AFF_LEARN, 0, "1", "next;"); } @@ -7539,9 +7577,9 @@ build_lb_rules(struct hmap *lflows, struct ovn_northd_lb *lb, if (reject) { size_t index; - dp_non_meter = bitmap_clone(lb->nb_ls_map, n_datapaths); - BITMAP_FOR_EACH_1 (index, n_datapaths, lb->nb_ls_map) { - struct ovn_datapath *od = datapaths_array[index]; + dp_non_meter = bitmap_clone(lb->nb_ls_map, n_ls_datapaths); + BITMAP_FOR_EACH_1 (index, n_ls_datapaths, lb->nb_ls_map) { + struct ovn_datapath *od = ls_datapaths_array[index]; meter = copp_meter_get(COPP_REJECT, od->nbs->copp, meter_groups); @@ -7717,8 +7755,8 @@ build_vtep_hairpin(struct ovn_datapath *od, struct hmap *lflows) static void build_fwd_group_lflows(struct ovn_datapath *od, struct hmap *lflows) { - - if (!od->nbs || !od->nbs->n_forwarding_groups) { + ovs_assert(od->nbs); + if (!od->nbs->n_forwarding_groups) { return; } struct ds match = DS_EMPTY_INITIALIZER; @@ -8399,9 +8437,7 @@ build_lswitch_lflows_pre_acl_and_acl(struct ovn_datapath *od, struct hmap *lflows, const struct shash *meter_groups) { - if (!od->nbs) { - return; - } + ovs_assert(od->nbs); ls_get_acl_flags(od); build_pre_acls(od, port_groups, lflows); @@ -8421,9 +8457,7 @@ static void build_lswitch_lflows_admission_control(struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbs) { - return; - } + ovs_assert(od->nbs); /* Logical VLANs not supported. */ if (!is_vlan_transparent(od)) { /* Block logical VLANs. */ @@ -8786,9 +8820,8 @@ static void build_lswitch_arp_nd_responder_default(struct ovn_datapath *od, struct hmap *lflows) { - if (od->nbs) { - ovn_lflow_add(lflows, od, S_SWITCH_IN_ARP_ND_RSP, 0, "1", "next;"); - } + ovs_assert(od->nbs); + ovn_lflow_add(lflows, od, S_SWITCH_IN_ARP_ND_RSP, 0, "1", "next;"); } /* Ingress table 19: ARP/ND responder for service monitor source ip. @@ -8921,9 +8954,7 @@ static void build_lswitch_dhcp_and_dns_defaults(struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbs) { - return; - } + ovs_assert(od->nbs); ovn_lflow_add(lflows, od, S_SWITCH_IN_DHCP_OPTIONS, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_SWITCH_IN_DHCP_RESPONSE, 0, "1", "next;"); ovn_lflow_add(lflows, od, S_SWITCH_IN_DNS_LOOKUP, 0, "1", "next;"); @@ -8939,7 +8970,8 @@ build_lswitch_dns_lookup_and_response(struct ovn_datapath *od, struct hmap *lflows, const struct shash *meter_groups) { - if (!od->nbs || !ls_has_dns_records(od->nbs)) { + ovs_assert(od->nbs); + if (!ls_has_dns_records(od->nbs)) { return; } ovn_lflow_metered(lflows, od, S_SWITCH_IN_DNS_LOOKUP, 100, @@ -8986,9 +9018,7 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od, struct ds *actions, const struct shash *meter_groups) { - if (!od->nbs) { - return; - } + ovs_assert(od->nbs); ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 110, "eth.dst == $svc_monitor_mac", @@ -10650,14 +10680,14 @@ build_gw_lrouter_nat_flows_for_lb(struct lrouter_nat_lb_flows_ctx *ctx, bool build_non_meter = false; size_t index; - if (bitmap_is_all_zeros(dp_bitmap, n_datapaths)) { + if (bitmap_is_all_zeros(dp_bitmap, n_lr_datapaths)) { return; } if (ctx->reject) { - dp_non_meter = bitmap_clone(dp_bitmap, n_datapaths); - BITMAP_FOR_EACH_1 (index, n_datapaths, dp_bitmap) { - struct ovn_datapath *od = datapaths_array[index]; + dp_non_meter = bitmap_clone(dp_bitmap, n_lr_datapaths); + BITMAP_FOR_EACH_1 (index, n_lr_datapaths, dp_bitmap) { + struct ovn_datapath *od = lr_datapaths_array[index]; const char *meter; meter = copp_meter_get(COPP_REJECT, od->nbr->copp, @@ -10795,15 +10825,15 @@ build_lrouter_nat_flows_for_lb(struct ovn_lb_vip *lb_vip, unsigned long *dp_bitmap[LROUTER_NAT_LB_FLOW_MAX + 2]; for (size_t i = 0; i < LROUTER_NAT_LB_FLOW_MAX + 2; i++) { - dp_bitmap[i] = bitmap_allocate(n_datapaths); + dp_bitmap[i] = bitmap_allocate(n_lr_datapaths); } /* Group gw router since we do not have datapath dependency in * lflow generation for them. */ size_t index; - BITMAP_FOR_EACH_1 (index, n_datapaths, lb->nb_lr_map) { - struct ovn_datapath *od = datapaths_array[index]; + BITMAP_FOR_EACH_1 (index, n_lr_datapaths, lb->nb_lr_map) { + struct ovn_datapath *od = lr_datapaths_array[index]; enum lrouter_nat_lb_flow_type type; if (lb->skip_snat) { @@ -10897,8 +10927,8 @@ build_lswitch_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows, } size_t index; - BITMAP_FOR_EACH_1 (index, n_datapaths, lb->nb_ls_map) { - struct ovn_datapath *od = datapaths_array[index]; + BITMAP_FOR_EACH_1 (index, n_ls_datapaths, lb->nb_ls_map) { + struct ovn_datapath *od = ls_datapaths_array[index]; ovn_lflow_add_with_hint__(lflows, od, S_SWITCH_IN_PRE_LB, 130, ds_cstr(match), @@ -11001,8 +11031,8 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows, continue; } - BITMAP_FOR_EACH_1 (index, n_datapaths, lb->nb_lr_map) { - struct ovn_datapath *od = datapaths_array[index]; + BITMAP_FOR_EACH_1 (index, n_lr_datapaths, lb->nb_lr_map) { + struct ovn_datapath *od = lr_datapaths_array[index]; ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_DNAT, 130, ds_cstr(match), ds_cstr(action), @@ -11015,8 +11045,8 @@ build_lrouter_flows_for_lb(struct ovn_northd_lb *lb, struct hmap *lflows, } if (lb->skip_snat) { - BITMAP_FOR_EACH_1 (index, n_datapaths, lb->nb_lr_map) { - struct ovn_datapath *od = datapaths_array[index]; + BITMAP_FOR_EACH_1 (index, n_lr_datapaths, lb->nb_lr_map) { + struct ovn_datapath *od = lr_datapaths_array[index]; ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT, 120, "flags.skip_snat_for_lb == 1 && ip", "next;"); @@ -11619,9 +11649,7 @@ static void build_adm_ctrl_flows_for_lrouter( struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Logical VLANs not supported. * Broadcast/multicast source address is invalid. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_ADMISSION, 100, @@ -11776,9 +11804,7 @@ build_neigh_learning_flows_for_lrouter( struct ds *match, struct ds *actions, const struct shash *meter_groups) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Learn MAC bindings from ARP/IPv6 ND. * @@ -12066,10 +12092,9 @@ build_ND_RA_flows_for_lrouter_port( static void build_ND_RA_flows_for_lrouter(struct ovn_datapath *od, struct hmap *lflows) { - if (od->nbr) { - ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_OPTIONS, 0, "1", "next;"); - ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_RESPONSE, 0, "1", "next;"); - } + ovs_assert(od->nbr); + ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_OPTIONS, 0, "1", "next;"); + ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_RESPONSE, 0, "1", "next;"); } /* Logical router ingress table IP_ROUTING_PRE: @@ -12078,10 +12103,9 @@ static void build_ip_routing_pre_flows_for_lrouter(struct ovn_datapath *od, struct hmap *lflows) { - if (od->nbr) { - ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING_PRE, 0, "1", - REG_ROUTE_TABLE_ID" = 0; next;"); - } + ovs_assert(od->nbr); + ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING_PRE, 0, "1", + REG_ROUTE_TABLE_ID" = 0; next;"); } /* Logical router ingress table IP_ROUTING : IP Routing. @@ -12172,9 +12196,7 @@ build_static_route_flows_for_lrouter( struct hmap *lflows, const struct hmap *lr_ports, const struct hmap *bfd_connections) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP); ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_IP_ROUTING); ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP, 150, @@ -12238,9 +12260,7 @@ build_mcast_lookup_flows_for_lrouter( struct ovn_datapath *od, struct hmap *lflows, struct ds *match, struct ds *actions) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Drop IPv6 multicast traffic that shouldn't be forwarded, * i.e., router solicitation and router advertisement. @@ -12341,9 +12361,7 @@ build_ingress_policy_flows_for_lrouter( struct ovn_datapath *od, struct hmap *lflows, const struct hmap *lr_ports) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* This is a catch-all rule. It has the lowest priority (0) * does a match-all("1") and pass-through (next) */ ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY, 0, "1", @@ -12376,9 +12394,7 @@ static void build_arp_resolve_flows_for_lrouter( struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Multicast packets already have the outport set so just advance to * next table (priority 500). */ ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_RESOLVE, 500, @@ -12808,9 +12824,7 @@ build_check_pkt_len_flows_for_lrouter( struct ds *match, struct ds *actions, const struct shash *meter_groups) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Packets are allowed by default. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_CHK_PKT_LEN, 0, "1", @@ -12835,9 +12849,7 @@ build_gateway_redirect_flows_for_lrouter( struct ovn_datapath *od, struct hmap *lflows, struct ds *match, struct ds *actions) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); for (size_t i = 0; i < od->n_l3dgw_ports; i++) { if (l3dgw_port_has_associated_vtep_lports(od->l3dgw_ports[i])) { /* Skip adding redirect lflow for vtep-enabled l3dgw ports. @@ -12924,9 +12936,7 @@ build_arp_request_flows_for_lrouter( struct ds *match, struct ds *actions, const struct shash *meter_groups) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); for (int i = 0; i < od->nbr->n_static_routes; i++) { const struct nbrec_logical_router_static_route *route; @@ -13044,9 +13054,7 @@ static void build_misc_local_traffic_drop_flows_for_lrouter( struct ovn_datapath *od, struct hmap *lflows) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Allow IGMP and MLD packets (with TTL = 1) if the router is * configured to flood them statically on some ports. */ @@ -13300,9 +13308,7 @@ build_lrouter_arp_nd_for_datapath(struct ovn_datapath *od, struct hmap *lflows, const struct shash *meter_groups) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Priority-90-92 flows handle ARP requests and ND packets. Most are * per logical port but DNAT addresses can be handled per datapath * for non gateway router ports. @@ -14265,9 +14271,7 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, const struct shash *meter_groups, const struct chassis_features *features) { - if (!od->nbr) { - return; - } + ovs_assert(od->nbr); /* Packets are allowed by default. */ ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG, 0, "1", "next;"); @@ -14590,7 +14594,8 @@ build_lrouter_nat_defrag_and_lb(struct ovn_datapath *od, struct hmap *lflows, struct lswitch_flow_build_info { - const struct hmap *datapaths; + const struct hmap *ls_datapaths; + const struct hmap *lr_datapaths; const struct hmap *ls_ports; const struct hmap *lr_ports; const struct hmap *port_groups; @@ -14608,17 +14613,16 @@ struct lswitch_flow_build_info { }; /* Helper function to combine all lflow generation which is iterated by - * datapath. + * logical switch datapath. * * When extending the function new "work data" must be added to the lsi * struct, not passed as an argument. */ - static void -build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od, +build_lswitch_and_lrouter_iterate_by_ls(struct ovn_datapath *od, struct lswitch_flow_build_info *lsi) { - /* Build Logical Switch Flows. */ + ovs_assert(od->nbs); build_lswitch_lflows_pre_acl_and_acl(od, lsi->port_groups, lsi->features, lsi->lflows, @@ -14634,8 +14638,16 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od, lsi->meter_groups); build_lswitch_output_port_sec_od(od, lsi->lflows); build_lswitch_lb_affinity_default_flows(od, lsi->lflows); +} - /* Build Logical Router Flows. */ +/* Helper function to combine all lflow generation which is iterated by + * logical router datapath. + */ +static void +build_lswitch_and_lrouter_iterate_by_lr(struct ovn_datapath *od, + struct lswitch_flow_build_info *lsi) +{ + ovs_assert(od->nbr); build_adm_ctrl_flows_for_lrouter(od, lsi->lflows); build_neigh_learning_flows_for_lrouter(od, lsi->lflows, &lsi->match, &lsi->actions, lsi->meter_groups); @@ -14748,14 +14760,27 @@ build_lflows_thread(void *arg) if (lsi) { /* Iterate over bucket ThreadID, ThreadID+size, ... */ for (bnum = control->id; - bnum <= lsi->datapaths->mask; + bnum <= lsi->ls_datapaths->mask; + bnum += control->pool->size) + { + HMAP_FOR_EACH_IN_PARALLEL (od, key_node, bnum, + lsi->ls_datapaths) { + if (stop_parallel_processing()) { + return NULL; + } + build_lswitch_and_lrouter_iterate_by_ls(od, lsi); + } + } + for (bnum = control->id; + bnum <= lsi->lr_datapaths->mask; bnum += control->pool->size) { - HMAP_FOR_EACH_IN_PARALLEL (od, key_node, bnum, lsi->datapaths) { + HMAP_FOR_EACH_IN_PARALLEL (od, key_node, bnum, + lsi->lr_datapaths) { if (stop_parallel_processing()) { return NULL; } - build_lswitch_and_lrouter_iterate_by_od(od, lsi); + build_lswitch_and_lrouter_iterate_by_lr(od, lsi); } } for (bnum = control->id; @@ -14859,7 +14884,8 @@ fix_flow_map_size(struct hmap *lflow_map, } static void -build_lswitch_and_lrouter_flows(const struct hmap *datapaths, +build_lswitch_and_lrouter_flows(const struct hmap *ls_datapaths, + const struct hmap *lr_datapaths, const struct hmap *ls_ports, const struct hmap *lr_ports, const struct hmap *port_groups, @@ -14887,7 +14913,8 @@ build_lswitch_and_lrouter_flows(const struct hmap *datapaths, * on a per-bucket level. */ lsiv[index].lflows = lflows; - lsiv[index].datapaths = datapaths; + lsiv[index].ls_datapaths = ls_datapaths; + lsiv[index].lr_datapaths = lr_datapaths; lsiv[index].ls_ports = ls_ports; lsiv[index].lr_ports = lr_ports; lsiv[index].port_groups = port_groups; @@ -14920,7 +14947,8 @@ build_lswitch_and_lrouter_flows(const struct hmap *datapaths, struct ovn_northd_lb *lb; struct ovn_igmp_group *igmp_group; struct lswitch_flow_build_info lsi = { - .datapaths = datapaths, + .ls_datapaths = ls_datapaths, + .lr_datapaths = lr_datapaths, .ls_ports = ls_ports, .lr_ports = lr_ports, .port_groups = port_groups, @@ -14940,8 +14968,11 @@ build_lswitch_and_lrouter_flows(const struct hmap *datapaths, * will move here and will be reogranized by iterator type. */ stopwatch_start(LFLOWS_DATAPATHS_STOPWATCH_NAME, time_msec()); - HMAP_FOR_EACH (od, key_node, datapaths) { - build_lswitch_and_lrouter_iterate_by_od(od, &lsi); + HMAP_FOR_EACH (od, key_node, ls_datapaths) { + build_lswitch_and_lrouter_iterate_by_ls(od, &lsi); + } + HMAP_FOR_EACH (od, key_node, lr_datapaths) { + build_lswitch_and_lrouter_iterate_by_lr(od, &lsi); } stopwatch_stop(LFLOWS_DATAPATHS_STOPWATCH_NAME, time_msec()); stopwatch_start(LFLOWS_PORTS_STOPWATCH_NAME, time_msec()); @@ -14978,7 +15009,7 @@ build_lswitch_and_lrouter_flows(const struct hmap *datapaths, } free(svc_check_match); - build_lswitch_flows(datapaths, lflows); + build_lswitch_flows(ls_datapaths, lflows); } static void @@ -14986,12 +15017,14 @@ ovn_sb_set_lflow_logical_dp_group( struct ovsdb_idl_txn *ovnsb_txn, struct hmap *dp_groups, const struct sbrec_logical_flow *sbflow, - const unsigned long *dpg_bitmap) + const unsigned long *dpg_bitmap, + size_t bitmap_len, + struct ovn_datapath **datapaths_array) { struct ovn_dp_group *dpg; size_t n_ods; - n_ods = bitmap_count1(dpg_bitmap, n_datapaths); + n_ods = bitmap_count1(dpg_bitmap, bitmap_len); if (!n_ods) { sbrec_logical_flow_set_logical_dp_group(sbflow, NULL); @@ -15000,11 +15033,14 @@ ovn_sb_set_lflow_logical_dp_group( ovs_assert(n_ods != 1); - dpg = ovn_dp_group_find(dp_groups, dpg_bitmap, hash_int(n_ods, 0)); + dpg = ovn_dp_group_find(dp_groups, dpg_bitmap, bitmap_len, + hash_int(n_ods, 0)); ovs_assert(dpg != NULL); if (!dpg->dp_group) { - dpg->dp_group = ovn_sb_insert_logical_dp_group(ovnsb_txn, dpg->bitmap); + dpg->dp_group = ovn_sb_insert_logical_dp_group(ovnsb_txn, dpg->bitmap, + bitmap_len, + datapaths_array); } sbrec_logical_flow_set_logical_dp_group(sbflow, dpg->dp_group); } @@ -15031,7 +15067,7 @@ void run_update_worker_pool(int n_threads) static void build_mcast_groups(struct lflow_input *data, - const struct hmap *datapaths, + const struct hmap *ls_datapaths, const struct hmap *ls_ports, const struct hmap *lr_ports, struct hmap *mcast_groups, @@ -15046,13 +15082,14 @@ void build_lflows(struct lflow_input *input_data, struct hmap mcast_groups; struct hmap igmp_groups; - build_mcast_groups(input_data, input_data->datapaths, + build_mcast_groups(input_data, input_data->ls_datapaths, input_data->ls_ports, input_data->lr_ports, &mcast_groups, &igmp_groups); fast_hmap_size_for(&lflows, max_seen_lflow_size); - build_lswitch_and_lrouter_flows(input_data->datapaths, + build_lswitch_and_lrouter_flows(input_data->ls_datapaths, + input_data->lr_datapaths, input_data->ls_ports, input_data->lr_ports, input_data->port_groups, &lflows, @@ -15076,7 +15113,8 @@ void build_lflows(struct lflow_input *input_data, stopwatch_start(LFLOWS_DP_GROUPS_STOPWATCH_NAME, time_msec()); /* Collecting all unique datapath groups. */ - struct hmap dp_groups = HMAP_INITIALIZER(&dp_groups); + struct hmap ls_dp_groups = HMAP_INITIALIZER(&ls_dp_groups); + struct hmap lr_dp_groups = HMAP_INITIALIZER(&lr_dp_groups); struct hmap single_dp_lflows; /* Single dp_flows will never grow bigger than lflows, @@ -15092,6 +15130,19 @@ void build_lflows(struct lflow_input *input_data, struct ovn_dp_group *dpg; uint32_t hash, n_ods; + struct hmap *dp_groups; + size_t n_datapaths; + struct ovn_datapath **datapaths_array; + if (ovn_stage_to_datapath_type(lflow->stage) == DP_SWITCH) { + n_datapaths = n_ls_datapaths; + dp_groups = &ls_dp_groups; + datapaths_array = ls_datapaths_array; + } else { + n_datapaths = n_lr_datapaths; + dp_groups = &lr_dp_groups; + datapaths_array = lr_datapaths_array; + } + n_ods = bitmap_count1(lflow->dpg_bitmap, n_datapaths); ovs_assert(n_ods); @@ -15117,11 +15168,12 @@ void build_lflows(struct lflow_input *input_data, } hash = hash_int(n_ods, 0); - dpg = ovn_dp_group_find(&dp_groups, lflow->dpg_bitmap, hash); + dpg = ovn_dp_group_find(dp_groups, lflow->dpg_bitmap, n_datapaths, + hash); if (!dpg) { dpg = xzalloc(sizeof *dpg); dpg->bitmap = bitmap_clone(lflow->dpg_bitmap, n_datapaths); - hmap_insert(&dp_groups, &dpg->node, hash); + hmap_insert(dp_groups, &dpg->node, hash); } lflow->dpg = dpg; } @@ -15147,7 +15199,9 @@ void build_lflows(struct lflow_input *input_data, struct sbrec_datapath_binding *dp = sbflow->logical_datapath; if (dp) { logical_datapath_od = ovn_datapath_from_sbrec( - input_data->datapaths, dp); + input_data->ls_datapaths, + input_data->lr_datapaths, + dp); if (logical_datapath_od && ovn_datapath_is_stale(logical_datapath_od)) { logical_datapath_od = NULL; @@ -15155,7 +15209,9 @@ void build_lflows(struct lflow_input *input_data, } for (i = 0; dp_group && i < dp_group->n_datapaths; i++) { logical_datapath_od = ovn_datapath_from_sbrec( - input_data->datapaths, dp_group->datapaths[i]); + input_data->ls_datapaths, + input_data->lr_datapaths, + dp_group->datapaths[i]); if (logical_datapath_od && !ovn_datapath_is_stale(logical_datapath_od)) { break; @@ -15179,6 +15235,18 @@ void build_lflows(struct lflow_input *input_data, sbflow->priority, sbflow->match, sbflow->actions, sbflow->controller_meter, sbflow->hash); if (lflow) { + struct hmap *dp_groups; + size_t n_datapaths; + struct ovn_datapath **datapaths_array; + if (ovn_stage_to_datapath_type(lflow->stage) == DP_SWITCH) { + n_datapaths = n_ls_datapaths; + dp_groups = &ls_dp_groups; + datapaths_array = ls_datapaths_array; + } else { + n_datapaths = n_lr_datapaths; + dp_groups = &lr_dp_groups; + datapaths_array = lr_datapaths_array; + } if (input_data->ovn_internal_version_changed) { const char *stage_name = smap_get_def(&sbflow->external_ids, "stage-name", ""); @@ -15231,7 +15299,8 @@ void build_lflows(struct lflow_input *input_data, /* Check all logical datapaths from the group. */ for (i = 0; i < dp_group->n_datapaths; i++) { od = ovn_datapath_from_sbrec( - input_data->datapaths, dp_group->datapaths[i]); + input_data->ls_datapaths, input_data->lr_datapaths, + dp_group->datapaths[i]); if (!od || ovn_datapath_is_stale(od)) { continue; } @@ -15244,8 +15313,10 @@ void build_lflows(struct lflow_input *input_data, } if (update_dp_group) { - ovn_sb_set_lflow_logical_dp_group(ovnsb_txn, &dp_groups, - sbflow, lflow->dpg_bitmap); + ovn_sb_set_lflow_logical_dp_group(ovnsb_txn, dp_groups, + sbflow, lflow->dpg_bitmap, + n_datapaths, + datapaths_array); } else if (lflow->dpg && !lflow->dpg->dp_group) { /* Setting relation between unique datapath group and * Sb DB datapath goup. */ @@ -15263,12 +15334,26 @@ void build_lflows(struct lflow_input *input_data, const char *pipeline = ovn_stage_get_pipeline_name(lflow->stage); uint8_t table = ovn_stage_get_table(lflow->stage); + struct hmap *dp_groups; + size_t n_datapaths; + struct ovn_datapath **datapaths_array; + if (ovn_stage_to_datapath_type(lflow->stage) == DP_SWITCH) { + n_datapaths = n_ls_datapaths; + dp_groups = &ls_dp_groups; + datapaths_array = ls_datapaths_array; + } else { + n_datapaths = n_lr_datapaths; + dp_groups = &lr_dp_groups; + datapaths_array = lr_datapaths_array; + } + sbflow = sbrec_logical_flow_insert(ovnsb_txn); if (lflow->od) { sbrec_logical_flow_set_logical_datapath(sbflow, lflow->od->sb); } - ovn_sb_set_lflow_logical_dp_group(ovnsb_txn, &dp_groups, - sbflow, lflow->dpg_bitmap); + ovn_sb_set_lflow_logical_dp_group(ovnsb_txn, dp_groups, + sbflow, lflow->dpg_bitmap, + n_datapaths, datapaths_array); sbrec_logical_flow_set_pipeline(sbflow, pipeline); sbrec_logical_flow_set_table_id(sbflow, table); sbrec_logical_flow_set_priority(sbflow, lflow->priority); @@ -15309,18 +15394,25 @@ void build_lflows(struct lflow_input *input_data, stopwatch_stop(LFLOWS_TO_SB_STOPWATCH_NAME, time_msec()); struct ovn_dp_group *dpg; - HMAP_FOR_EACH_POP (dpg, node, &dp_groups) { + HMAP_FOR_EACH_POP (dpg, node, &ls_dp_groups) { bitmap_free(dpg->bitmap); free(dpg); } - hmap_destroy(&dp_groups); + hmap_destroy(&ls_dp_groups); + HMAP_FOR_EACH_POP (dpg, node, &lr_dp_groups) { + bitmap_free(dpg->bitmap); + free(dpg); + } + hmap_destroy(&lr_dp_groups); /* Push changes to the Multicast_Group table to database. */ const struct sbrec_multicast_group *sbmc; SBREC_MULTICAST_GROUP_TABLE_FOR_EACH_SAFE (sbmc, input_data->sbrec_multicast_group_table) { struct ovn_datapath *od = ovn_datapath_from_sbrec( - input_data->datapaths, sbmc->datapath); + input_data->ls_datapaths, + input_data->lr_datapaths, + sbmc->datapath); if (!od || ovn_datapath_is_stale(od)) { sbrec_multicast_group_delete(sbmc); @@ -15705,12 +15797,13 @@ get_dns_info_from_hmap(struct hmap *dns_map, struct uuid *uuid) static void sync_dns_entries(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, - struct hmap *datapaths) + struct hmap *ls_datapaths) { struct hmap dns_map = HMAP_INITIALIZER(&dns_map); struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { - if (!od->nbs || !od->nbs->n_dns_records) { + HMAP_FOR_EACH (od, key_node, ls_datapaths) { + ovs_assert(od->nbs); + if (!od->nbs->n_dns_records) { continue; } @@ -15828,9 +15921,9 @@ sync_template_vars(struct northd_input *input_data, } static void -destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ls_ports, - struct hmap *lr_ports, - struct ovs_list *lr_list) +destroy_datapaths_and_ports(struct hmap *ls_datapaths, + struct hmap *lr_datapaths, struct hmap *ls_ports, + struct hmap *lr_ports, struct ovs_list *lr_list) { struct ovn_datapath *router_dp; LIST_FOR_EACH_POP (router_dp, lr_list, lr_list) { @@ -15848,10 +15941,15 @@ destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ls_ports, } struct ovn_datapath *dp; - HMAP_FOR_EACH_SAFE (dp, key_node, datapaths) { - ovn_datapath_destroy(datapaths, dp); + HMAP_FOR_EACH_SAFE (dp, key_node, ls_datapaths) { + ovn_datapath_destroy(ls_datapaths, dp); + } + hmap_destroy(ls_datapaths); + + HMAP_FOR_EACH_SAFE (dp, key_node, lr_datapaths) { + ovn_datapath_destroy(lr_datapaths, dp); } - hmap_destroy(datapaths); + hmap_destroy(lr_datapaths); struct ovn_port *port; HMAP_FOR_EACH_SAFE (port, key_node, ls_ports) { @@ -15868,14 +15966,12 @@ destroy_datapaths_and_ports(struct hmap *datapaths, struct hmap *ls_ports, static void build_ip_mcast(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn, - struct hmap *datapaths) + struct hmap *ls_datapaths) { struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { - if (!od->nbs) { - continue; - } + HMAP_FOR_EACH (od, key_node, ls_datapaths) { + ovs_assert(od->nbs); const struct sbrec_ip_multicast *ip_mcast = ip_mcast_lookup(input_data->sbrec_ip_mcast_by_dp, od->sb); @@ -15891,7 +15987,7 @@ build_ip_mcast(struct northd_input *input_data, SBREC_IP_MULTICAST_TABLE_FOR_EACH_SAFE (sb, input_data->sbrec_ip_multicast_table) { - od = ovn_datapath_from_sbrec(datapaths, sb->datapath); + od = ovn_datapath_from_sbrec(ls_datapaths, NULL, sb->datapath); if (!od || ovn_datapath_is_stale(od)) { sbrec_ip_multicast_delete(sb); } @@ -15900,7 +15996,7 @@ build_ip_mcast(struct northd_input *input_data, static void build_mcast_groups(struct lflow_input *input_data, - const struct hmap *datapaths, + const struct hmap *ls_datapaths, const struct hmap *ls_ports, const struct hmap *lr_ports, struct hmap *mcast_groups, @@ -15912,7 +16008,7 @@ build_mcast_groups(struct lflow_input *input_data, hmap_init(igmp_groups); struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, datapaths) { + HMAP_FOR_EACH (od, key_node, ls_datapaths) { init_mcast_flow_count(od); } @@ -15976,7 +16072,7 @@ build_mcast_groups(struct lflow_input *input_data, } /* If the datapath value is stale, purge the group. */ - od = ovn_datapath_from_sbrec(datapaths, sb_igmp->datapath); + od = ovn_datapath_from_sbrec(ls_datapaths, NULL, sb_igmp->datapath); if (!od || ovn_datapath_is_stale(od)) { sbrec_igmp_group_delete(sb_igmp); @@ -16021,7 +16117,7 @@ build_mcast_groups(struct lflow_input *input_data, * IGMP groups are based on the groups learnt by their multicast enabled * peers. */ - HMAP_FOR_EACH (od, key_node, datapaths) { + HMAP_FOR_EACH (od, key_node, ls_datapaths) { if (ovs_list_is_empty(&od->mcast_info.groups)) { continue; @@ -16192,7 +16288,8 @@ build_static_mac_binding_table(struct northd_input *input_data, void northd_init(struct northd_data *data) { - hmap_init(&data->datapaths); + hmap_init(&data->ls_datapaths); + hmap_init(&data->lr_datapaths); hmap_init(&data->ls_ports); hmap_init(&data->lr_ports); hmap_init(&data->port_groups); @@ -16247,8 +16344,9 @@ northd_destroy(struct northd_data *data) */ cleanup_macam(); - destroy_datapaths_and_ports(&data->datapaths, &data->ls_ports, - &data->lr_ports, &data->lr_list); + destroy_datapaths_and_ports(&data->ls_datapaths, &data->lr_datapaths, + &data->ls_ports, &data->lr_ports, + &data->lr_list); destroy_debug_config(); } @@ -16336,20 +16434,22 @@ ovnnb_db_run(struct northd_input *input_data, init_debug_config(nb); - build_datapaths(input_data, ovnsb_txn, &data->datapaths, &data->lr_list); - build_lbs(input_data, &data->datapaths, &data->lbs, &data->lb_groups); + build_datapaths(input_data, ovnsb_txn, &data->ls_datapaths, + &data->lr_datapaths, &data->lr_list); + build_lbs(input_data, &data->ls_datapaths, &data->lr_datapaths, &data->lbs, + &data->lb_groups); build_ports(input_data, ovnsb_txn, sbrec_chassis_by_name, - sbrec_chassis_by_hostname, &data->datapaths, - &data->ls_ports, &data->lr_ports); - build_lb_port_related_data(&data->datapaths, &data->ls_ports, + sbrec_chassis_by_hostname, &data->ls_datapaths, + &data->lr_datapaths, &data->ls_ports, &data->lr_ports); + build_lb_port_related_data(&data->lr_datapaths, &data->ls_ports, &data->lbs, &data->lb_groups, input_data, ovnsb_txn); build_lb_count_dps(&data->lbs); - build_ipam(&data->datapaths, &data->ls_ports); + build_ipam(&data->ls_datapaths, &data->ls_ports); build_port_group_lswitches(input_data, &data->port_groups, &data->ls_ports); build_lrouter_groups(&data->lr_ports, &data->lr_list); - build_ip_mcast(input_data, ovnsb_txn, &data->datapaths); + build_ip_mcast(input_data, ovnsb_txn, &data->ls_datapaths); build_meter_groups(input_data, &data->meter_groups); build_static_mac_binding_table(input_data, ovnsb_txn, &data->lr_ports); stopwatch_stop(BUILD_LFLOWS_CTX_STOPWATCH_NAME, time_msec()); @@ -16357,14 +16457,14 @@ ovnnb_db_run(struct northd_input *input_data, ovn_update_ipv6_options(&data->lr_ports); ovn_update_ipv6_prefix(&data->lr_ports); - sync_lbs(input_data, ovnsb_txn, &data->datapaths, &data->lbs); + sync_lbs(input_data, ovnsb_txn, &data->ls_datapaths, &data->lbs); sync_port_groups(input_data, ovnsb_txn, &data->port_groups); sync_meters(input_data, ovnsb_txn, &data->meter_groups); sync_mirrors(input_data, ovnsb_txn); - sync_dns_entries(input_data, ovnsb_txn, &data->datapaths); + sync_dns_entries(input_data, ovnsb_txn, &data->ls_datapaths); sync_template_vars(input_data, ovnsb_txn); - cleanup_stale_fdb_entries(input_data, &data->datapaths); + cleanup_stale_fdb_entries(input_data, &data->ls_datapaths); stopwatch_stop(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec()); /* Set up SB_Global (depends on chassis features). */ diff --git a/northd/northd.h b/northd/northd.h index cdb521d46566..cfd36e32c9a7 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -76,7 +76,8 @@ struct chassis_features { struct northd_data { /* Global state for 'en-northd'. */ - struct hmap datapaths; + struct hmap ls_datapaths; + struct hmap lr_datapaths; struct hmap ls_ports; struct hmap lr_ports; struct hmap port_groups; @@ -102,7 +103,8 @@ struct lflow_input { /* Indexes */ struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp; - const struct hmap *datapaths; + const struct hmap *ls_datapaths; + const struct hmap *lr_datapaths; const struct hmap *ls_ports; const struct hmap *lr_ports; const struct hmap *port_groups;