On Wed, Mar 16, 2022 at 12:11 PM Dumitru Ceara <[email protected]> wrote:
>
> This commit doesn't change any functionality, it just performs the
> following refactor work:
>
> a. consolidates the old build_ovn_lbs(), build_lrouter_lbs() and
> build_ovn_lr_lbs() functions into a single function, build_lbs(),
> that builds all the load balancer port-independent information.
> Part of this was not possible before because we were logging a
> warning message in build_ovn_lr_lbs() if a load balancer is
> applied to a non-gateway router with more than 1 distributed
> gateway ports. We now move the log to build_lrouter_lbs_check()
> which is called after ports are processed.
>
> b. consolidates all the load balancer processing that depends on logical
> ports being parsed too into the build_lb_port_related_data()
> function.
>
> c. split out the part that syncs load balancers to the Southbound
> database.
>
> This has two advantages:
>
> 1. it allows a simpler overview of what is being processed, that is:
> - build datapaths
> - build load balancer state that depends on datapaths
> - build ports
> - add load balancer state that depends on ports
>
> 2. it may enable further optimization as now the part that builds the
> datapath-dependent load balancer state can be processed separately,
> potentially in an incremental fashion. This part of the northd
> processing has been shown to be quite time consuming in the past.
>
> Signed-off-by: Dumitru Ceara <[email protected]>
Thanks for the refactor. The patch LGTM. I went ahead and applied to
the main branch.
Numan
> ---
> northd/northd.c | 319 ++++++++++++++++++++++++------------------------
> tests/ovn.at | 14 ++-
> 2 files changed, 167 insertions(+), 166 deletions(-)
>
> diff --git a/northd/northd.c b/northd/northd.c
> index b264fb850b..8c871171f5 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -3732,53 +3732,28 @@ build_lb_vip_actions(struct ovn_lb_vip *lb_vip,
> }
>
> static void
> -build_ovn_lr_lbs(struct hmap *datapaths, struct hmap *lbs)
> +build_lrouter_lb_ips(struct ovn_datapath *od, const struct ovn_northd_lb *lb)
> {
> - struct ovn_northd_lb *lb;
> - struct ovn_datapath *od;
> -
> - HMAP_FOR_EACH (od, key_node, datapaths) {
> - if (!od->nbr) {
> - continue;
> - }
> - if (!smap_get(&od->nbr->options, "chassis")
> - && od->n_l3dgw_ports != 1) {
> - if (od->n_l3dgw_ports > 1 && od->has_lb_vip) {
> - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1,
> 1);
> - VLOG_WARN_RL(&rl, "Load-balancers are configured on logical "
> - "router %s, which has %"PRIuSIZE" distributed "
> - "gateway ports. Load-balancer is not supported "
> - "yet when there is more than one distributed "
> - "gateway port on the router.",
> - od->nbr->name, od->n_l3dgw_ports);
> - }
> - continue;
> - }
> + bool is_routable = smap_get_bool(&lb->nlb->options, "add_route", false);
> + const char *ip_address;
>
> - for (size_t i = 0; i < od->nbr->n_load_balancer; i++) {
> - const struct uuid *lb_uuid =
> - &od->nbr->load_balancer[i]->header_.uuid;
> - lb = ovn_northd_lb_find(lbs, lb_uuid);
> - ovn_northd_lb_add_lr(lb, od);
> + SSET_FOR_EACH (ip_address, &lb->ips_v4) {
> + sset_add(&od->lb_ips_v4, ip_address);
> + if (is_routable) {
> + sset_add(&od->lb_ips_v4_routable, ip_address);
> }
> -
> - for (size_t i = 0; i < od->nbr->n_load_balancer_group; i++) {
> - const struct nbrec_load_balancer_group *lbg =
> - od->nbr->load_balancer_group[i];
> - for (size_t j = 0; j < lbg->n_load_balancer; j++) {
> - const struct uuid *lb_uuid =
> - &lbg->load_balancer[j]->header_.uuid;
> - lb = ovn_northd_lb_find(lbs, lb_uuid);
> - ovn_northd_lb_add_lr(lb, od);
> - }
> + }
> + SSET_FOR_EACH (ip_address, &lb->ips_v6) {
> + sset_add(&od->lb_ips_v6, ip_address);
> + if (is_routable) {
> + sset_add(&od->lb_ips_v6_routable, ip_address);
> }
> }
> }
>
> static void
> -build_ovn_lbs(struct northd_input *input_data,
> - struct ovsdb_idl_txn *ovnsb_txn,
> - struct hmap *datapaths, struct hmap *lbs)
> +build_lbs(struct northd_input *input_data, struct hmap *datapaths,
> + struct hmap *lbs)
> {
> struct ovn_northd_lb *lb;
>
> @@ -3817,94 +3792,38 @@ build_ovn_lbs(struct northd_input *input_data,
> }
> }
>
> - /* Delete any stale SB load balancer rows. */
> - struct hmapx existing_lbs = HMAPX_INITIALIZER(&existing_lbs);
> - const struct sbrec_load_balancer *sbrec_lb, *next;
> - SBREC_LOAD_BALANCER_TABLE_FOR_EACH_SAFE (sbrec_lb, next,
> - input_data->sbrec_load_balancer_table) {
> - const char *nb_lb_uuid = smap_get(&sbrec_lb->external_ids, "lb_id");
> - struct uuid lb_uuid;
> - if (!nb_lb_uuid || !uuid_from_string(&lb_uuid, nb_lb_uuid)) {
> - sbrec_load_balancer_delete(sbrec_lb);
> - continue;
> - }
> -
> - /* Delete any SB load balancer entries that refer to NB load
> balancers
> - * that don't exist anymore or are not applied to switches anymore.
> - *
> - * There is also a special case in which duplicate LBs might be
> created
> - * in the SB, e.g., due to the fact that OVSDB only ensures
> - * "at-least-once" consistency for clustered database tables that
> - * are not indexed in any way.
> - */
> - lb = ovn_northd_lb_find(lbs, &lb_uuid);
> - if (!lb || !lb->n_nb_ls || !hmapx_add(&existing_lbs, lb)) {
> - sbrec_load_balancer_delete(sbrec_lb);
> - } else {
> - lb->slb = sbrec_lb;
> - }
> - }
> - hmapx_destroy(&existing_lbs);
> -
> - /* Create SB Load balancer records if not present and sync
> - * the SB load balancer columns. */
> - HMAP_FOR_EACH (lb, hmap_node, lbs) {
> -
> - if (!lb->n_nb_ls) {
> + HMAP_FOR_EACH (od, key_node, datapaths) {
> + if (!od->nbr) {
> continue;
> }
>
> - /* Store the fact that northd provides the original (destination IP +
> - * transport port) tuple.
> - */
> - struct smap options;
> - smap_clone(&options, &lb->nlb->options);
> - smap_replace(&options, "hairpin_orig_tuple", "true");
> -
> - struct sbrec_datapath_binding **lb_dps =
> - xmalloc(lb->n_nb_ls * sizeof *lb_dps);
> - for (size_t i = 0; i < lb->n_nb_ls; i++) {
> - lb_dps[i] = CONST_CAST(struct sbrec_datapath_binding *,
> - lb->nb_ls[i]->sb);
> - }
> -
> - if (!lb->slb) {
> - sbrec_lb = sbrec_load_balancer_insert(ovnsb_txn);
> - lb->slb = sbrec_lb;
> - char *lb_id = xasprintf(
> - UUID_FMT, UUID_ARGS(&lb->nlb->header_.uuid));
> - const struct smap external_ids =
> - SMAP_CONST1(&external_ids, "lb_id", lb_id);
> - sbrec_load_balancer_set_external_ids(sbrec_lb, &external_ids);
> - free(lb_id);
> - }
> - sbrec_load_balancer_set_name(lb->slb, lb->nlb->name);
> - sbrec_load_balancer_set_vips(lb->slb, &lb->nlb->vips);
> - sbrec_load_balancer_set_protocol(lb->slb, lb->nlb->protocol);
> - sbrec_load_balancer_set_datapaths(lb->slb, lb_dps, lb->n_nb_ls);
> - sbrec_load_balancer_set_options(lb->slb, &options);
> - smap_destroy(&options);
> - free(lb_dps);
> - }
> -
> - /* Datapath_Binding.load_balancers is not used anymore, it's still in the
> - * schema for compatibility reasons. Reset it to empty, just in case.
> - */
> - HMAP_FOR_EACH (od, key_node, datapaths) {
> - if (!od->nbs) {
> - continue;
> + for (size_t i = 0; i < od->nbr->n_load_balancer; i++) {
> + const struct uuid *lb_uuid =
> + &od->nbr->load_balancer[i]->header_.uuid;
> + lb = ovn_northd_lb_find(lbs, lb_uuid);
> + ovn_northd_lb_add_lr(lb, od);
> + build_lrouter_lb_ips(od, lb);
> }
>
> - if (od->sb->n_load_balancers) {
> - sbrec_datapath_binding_set_load_balancers(od->sb, NULL, 0);
> + for (size_t i = 0; i < od->nbr->n_load_balancer_group; i++) {
> + const struct nbrec_load_balancer_group *lbg =
> + od->nbr->load_balancer_group[i];
> + for (size_t j = 0; j < lbg->n_load_balancer; j++) {
> + const struct uuid *lb_uuid =
> + &lbg->load_balancer[j]->header_.uuid;
> + lb = ovn_northd_lb_find(lbs, lb_uuid);
> + ovn_northd_lb_add_lr(lb, od);
> + build_lrouter_lb_ips(od, lb);
> + }
> }
> }
> }
>
> static void
> -build_ovn_lb_svcs(struct northd_input *input_data,
> - struct ovsdb_idl_txn *ovnsb_txn,
> - struct hmap *ports, struct hmap *lbs)
> +build_lb_svcs(struct northd_input *input_data,
> + struct ovsdb_idl_txn *ovnsb_txn,
> + struct hmap *ports,
> + struct hmap *lbs)
> {
> struct hmap monitor_map = HMAP_INITIALIZER(&monitor_map);
>
> @@ -3936,26 +3855,6 @@ build_ovn_lb_svcs(struct northd_input *input_data,
> hmap_destroy(&monitor_map);
> }
>
> -static void
> -build_lrouter_lb_ips(struct ovn_datapath *od, const struct ovn_northd_lb *lb)
> -{
> - bool is_routable = smap_get_bool(&lb->nlb->options, "add_route", false);
> - const char *ip_address;
> -
> - SSET_FOR_EACH (ip_address, &lb->ips_v4) {
> - sset_add(&od->lb_ips_v4, ip_address);
> - if (is_routable) {
> - sset_add(&od->lb_ips_v4_routable, ip_address);
> - }
> - }
> - SSET_FOR_EACH (ip_address, &lb->ips_v6) {
> - sset_add(&od->lb_ips_v6, ip_address);
> - if (is_routable) {
> - sset_add(&od->lb_ips_v6_routable, ip_address);
> - }
> - }
> -}
> -
> static bool lrouter_port_ipv4_reachable(const struct ovn_port *op,
> ovs_be32 addr);
> static bool lrouter_port_ipv6_reachable(const struct ovn_port *op,
> @@ -3989,7 +3888,7 @@ build_lrouter_lb_reachable_ips(struct ovn_datapath *od,
> }
>
> static void
> -build_lrouter_lbs(struct hmap *datapaths, struct hmap *lbs)
> +build_lrouter_lbs_check(const struct hmap *datapaths)
> {
> struct ovn_datapath *od;
>
> @@ -3998,22 +3897,15 @@ build_lrouter_lbs(struct hmap *datapaths, struct hmap
> *lbs)
> continue;
> }
>
> - for (size_t i = 0; i < od->nbr->n_load_balancer; i++) {
> - struct ovn_northd_lb *lb =
> - ovn_northd_lb_find(lbs,
> - &od->nbr->load_balancer[i]->header_.uuid);
> - build_lrouter_lb_ips(od, lb);
> - }
> -
> - for (size_t i = 0; i < od->nbr->n_load_balancer_group; i++) {
> - const struct nbrec_load_balancer_group *lbg =
> - od->nbr->load_balancer_group[i];
> - for (size_t j = 0; j < lbg->n_load_balancer; j++) {
> - struct ovn_northd_lb *lb =
> - ovn_northd_lb_find(lbs,
> - &lbg->load_balancer[j]->header_.uuid);
> - build_lrouter_lb_ips(od, lb);
> - }
> + if (od->has_lb_vip && od->n_l3dgw_ports > 1
> + && !smap_get(&od->nbr->options, "chassis")) {
> + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> + VLOG_WARN_RL(&rl, "Load-balancers are configured on logical "
> + "router %s, which has %"PRIuSIZE" distributed "
> + "gateway ports. Load-balancer is not supported "
> + "yet when there is more than one distributed "
> + "gateway port on the router.",
> + od->nbr->name, od->n_l3dgw_ports);
> }
> }
> }
> @@ -4048,6 +3940,114 @@ build_lrouter_lbs_reachable_ips(struct hmap
> *datapaths, struct hmap *lbs)
> }
> }
>
> +/* This must be called after all ports have been processed, i.e., after
> + * build_ports() because the reachability check requires the router ports
> + * networks to have been parsed.
> + */
> +static void
> +build_lb_port_related_data(struct hmap *datapaths, struct hmap *ports,
> + struct hmap *lbs, struct northd_input *input_data,
> + struct ovsdb_idl_txn *ovnsb_txn)
> +{
> + build_lrouter_lbs_check(datapaths);
> + build_lrouter_lbs_reachable_ips(datapaths, lbs);
> + build_lb_svcs(input_data, ovnsb_txn, ports, lbs);
> +}
> +
> +/* Syncs relevant load balancers (applied to logical switches) to the
> + * Southbound database.
> + */
> +static void
> +sync_lbs(struct northd_input *input_data, struct ovsdb_idl_txn *ovnsb_txn,
> + struct hmap *datapaths, struct hmap *lbs)
> +{
> + struct ovn_northd_lb *lb;
> +
> + /* Delete any stale SB load balancer rows. */
> + struct hmapx existing_lbs = HMAPX_INITIALIZER(&existing_lbs);
> + const struct sbrec_load_balancer *sbrec_lb, *next;
> + SBREC_LOAD_BALANCER_TABLE_FOR_EACH_SAFE (sbrec_lb, next,
> + input_data->sbrec_load_balancer_table) {
> + const char *nb_lb_uuid = smap_get(&sbrec_lb->external_ids, "lb_id");
> + struct uuid lb_uuid;
> + if (!nb_lb_uuid || !uuid_from_string(&lb_uuid, nb_lb_uuid)) {
> + sbrec_load_balancer_delete(sbrec_lb);
> + continue;
> + }
> +
> + /* Delete any SB load balancer entries that refer to NB load
> balancers
> + * that don't exist anymore or are not applied to switches anymore.
> + *
> + * There is also a special case in which duplicate LBs might be
> created
> + * in the SB, e.g., due to the fact that OVSDB only ensures
> + * "at-least-once" consistency for clustered database tables that
> + * are not indexed in any way.
> + */
> + lb = ovn_northd_lb_find(lbs, &lb_uuid);
> + if (!lb || !lb->n_nb_ls || !hmapx_add(&existing_lbs, lb)) {
> + sbrec_load_balancer_delete(sbrec_lb);
> + } else {
> + lb->slb = sbrec_lb;
> + }
> + }
> + hmapx_destroy(&existing_lbs);
> +
> + /* Create SB Load balancer records if not present and sync
> + * the SB load balancer columns. */
> + HMAP_FOR_EACH (lb, hmap_node, lbs) {
> +
> + if (!lb->n_nb_ls) {
> + continue;
> + }
> +
> + /* Store the fact that northd provides the original (destination IP +
> + * transport port) tuple.
> + */
> + struct smap options;
> + smap_clone(&options, &lb->nlb->options);
> + smap_replace(&options, "hairpin_orig_tuple", "true");
> +
> + struct sbrec_datapath_binding **lb_dps =
> + xmalloc(lb->n_nb_ls * sizeof *lb_dps);
> + for (size_t i = 0; i < lb->n_nb_ls; i++) {
> + lb_dps[i] = CONST_CAST(struct sbrec_datapath_binding *,
> + lb->nb_ls[i]->sb);
> + }
> +
> + if (!lb->slb) {
> + sbrec_lb = sbrec_load_balancer_insert(ovnsb_txn);
> + lb->slb = sbrec_lb;
> + char *lb_id = xasprintf(
> + UUID_FMT, UUID_ARGS(&lb->nlb->header_.uuid));
> + const struct smap external_ids =
> + SMAP_CONST1(&external_ids, "lb_id", lb_id);
> + sbrec_load_balancer_set_external_ids(sbrec_lb, &external_ids);
> + free(lb_id);
> + }
> + sbrec_load_balancer_set_name(lb->slb, lb->nlb->name);
> + sbrec_load_balancer_set_vips(lb->slb, &lb->nlb->vips);
> + sbrec_load_balancer_set_protocol(lb->slb, lb->nlb->protocol);
> + sbrec_load_balancer_set_datapaths(lb->slb, lb_dps, lb->n_nb_ls);
> + sbrec_load_balancer_set_options(lb->slb, &options);
> + smap_destroy(&options);
> + free(lb_dps);
> + }
> +
> + /* Datapath_Binding.load_balancers is not used anymore, it's still in the
> + * 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;
> + }
> +
> + if (od->sb->n_load_balancers) {
> + sbrec_datapath_binding_set_load_balancers(od->sb, NULL, 0);
> + }
> + }
> +}
> +
> static bool
> ovn_port_add_tnlid(struct ovn_port *op, uint32_t tunnel_key)
> {
> @@ -15121,14 +15121,12 @@ ovnnb_db_run(struct northd_input *input_data,
> "ignore_lsp_down", true);
>
> build_datapaths(input_data, ovnsb_txn, &data->datapaths, &data->lr_list);
> - build_ovn_lbs(input_data, ovnsb_txn, &data->datapaths, &data->lbs);
> - build_lrouter_lbs(&data->datapaths, &data->lbs);
> + build_lbs(input_data, &data->datapaths, &data->lbs);
> build_ports(input_data, ovnsb_txn, sbrec_chassis_by_name,
> sbrec_chassis_by_hostname,
> &data->datapaths, &data->ports);
> - build_lrouter_lbs_reachable_ips(&data->datapaths, &data->lbs);
> - build_ovn_lr_lbs(&data->datapaths, &data->lbs);
> - build_ovn_lb_svcs(input_data, ovnsb_txn, &data->ports, &data->lbs);
> + build_lb_port_related_data(&data->datapaths, &data->ports, &data->lbs,
> + input_data, ovnsb_txn);
> build_ipam(&data->datapaths, &data->ports);
> build_port_group_lswitches(input_data, &data->port_groups, &data->ports);
> build_lrouter_groups(&data->ports, &data->lr_list);
> @@ -15138,7 +15136,8 @@ ovnnb_db_run(struct northd_input *input_data,
> stopwatch_start(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, time_msec());
> ovn_update_ipv6_prefix(&data->ports);
>
> - sync_address_sets(input_data, ovnsb_txn, &data->datapaths);
> + sync_lbs(input_data, ovnsb_txn, &data->datapaths, &data->lbs);
> + sync_address_sets(input_data, ovnsb_txn, &data->datapaths);
> sync_port_groups(input_data, ovnsb_txn, &data->port_groups);
> sync_meters(input_data, ovnsb_txn, &data->meter_groups);
> sync_dns_entries(input_data, ovnsb_txn, &data->datapaths);
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 9b13a980da..2b13dd1b8f 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -24834,8 +24834,10 @@ ovn-nbctl acl-add pg1 to-lport 1002 "outport == @pg1
> && ip4 && ip4.src == 0.0.0.
> ovn-nbctl acl-add pg1 to-lport 1002 "outport == @pg1 && ip4 && ip4.src ==
> 0.0.0.0/0 && tcp && tcp.dst == 80" allow-related
> ovn-nbctl acl-add pg1 to-lport 1002 "outport == @pg1 && ip4 && ip4.src ==
> 0.0.0.0/0 && udp && udp.dst == 80" allow-related
>
> -# Create a logical router and attach both logical switches
> +# Create a logical router and attach both logical switches.
> +# Make the logical router a GW router for load balancing to be supported.
> ovn-nbctl lr-add lr0
> +ovn-nbctl set logical_router lr0 options:chassis=hv1
> ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
> ovn-nbctl lsp-add sw0 sw0-lr0
> ovn-nbctl lsp-set-type sw0-lr0 router
> @@ -24856,7 +24858,7 @@ ovn-nbctl lr-lb-add lr0 lb1
>
> OVS_WAIT_UNTIL([
> test $(as hv1 ovs-ofctl dump-groups br-int | \
> - grep "selection_method=dp_hash" -c) -eq 1
> + grep "selection_method=dp_hash" -c) -eq 2
> ])
>
> OVS_WAIT_UNTIL([
> @@ -24870,7 +24872,7 @@ ovn-nbctl set load_balancer $lb1_uuid
> selection_fields="ip_src,ip_dst,tp_src,tp_
>
> OVS_WAIT_UNTIL([
> test $(as hv1 ovs-ofctl dump-groups br-int | \
> - grep "selection_method=hash,fields(ip_src,ip_dst,tcp_src,tcp_dst)" -c)
> -eq 1
> + grep "selection_method=hash,fields(ip_src,ip_dst,tcp_src,tcp_dst)" -c)
> -eq 2
> ])
>
> OVS_WAIT_UNTIL([
> @@ -24882,7 +24884,7 @@ OVS_WAIT_UNTIL([
> ovn-nbctl set load_balancer $lb1_uuid protocol=udp
> OVS_WAIT_UNTIL([
> test $(as hv1 ovs-ofctl dump-groups br-int | \
> - grep "selection_method=hash,fields(ip_src,ip_dst,udp_src,udp_dst)" -c)
> -eq 1
> + grep "selection_method=hash,fields(ip_src,ip_dst,udp_src,udp_dst)" -c)
> -eq 2
> ])
>
> OVS_WAIT_UNTIL([
> @@ -24894,7 +24896,7 @@ OVS_WAIT_UNTIL([
> ovn-nbctl set load_balancer $lb1_uuid protocol=sctp
> OVS_WAIT_UNTIL([
> test $(as hv1 ovs-ofctl dump-groups br-int | \
> - grep "selection_method=hash,fields(ip_src,ip_dst,sctp_src,sctp_dst)" -c)
> -eq 1
> + grep "selection_method=hash,fields(ip_src,ip_dst,sctp_src,sctp_dst)" -c)
> -eq 2
> ])
>
> OVS_WAIT_UNTIL([
> @@ -24905,7 +24907,7 @@ OVS_WAIT_UNTIL([
> ovn-nbctl set load_balancer $lb1_uuid selection_fields="ip_src,ip_dst,tp_dst"
> OVS_WAIT_UNTIL([
> test $(as hv1 ovs-ofctl dump-groups br-int | \
> - grep "selection_method=hash,fields(ip_src,ip_dst,sctp_dst)" -c) -eq 1
> + grep "selection_method=hash,fields(ip_src,ip_dst,sctp_dst)" -c) -eq 2
> ])
>
> OVS_WAIT_UNTIL([
> --
> 2.27.0
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev