[ovs-dev] [PATCH ovn v2 1/5] controller: Move 'struct local_datapath' to a separate file.

Han Zhou zhouhan at gmail.com
Tue Jul 27 01:47:05 UTC 2021


On Fri, Jul 16, 2021 at 4:45 AM <numans at ovn.org> wrote:
>
> From: Numan Siddique <numans at ovn.org>
>
> This would uncomplicate the binding.c code a bit.  The tracking
> data and the related functions are also moved to the file - ldata.h.
> This would help in an upcoming patch.
>
> Signed-off-by: Numan Siddique <numans at ovn.org>
> ---
>  controller/automake.mk      |   4 +-
>  controller/binding.c        | 363 ++++++-----------------------------
>  controller/binding.h        |  13 --
>  controller/ldata.c          | 368 ++++++++++++++++++++++++++++++++++++
>  controller/ldata.h          | 120 ++++++++++++
>  controller/lflow.c          |   1 +
>  controller/lport.c          |  40 ++++
>  controller/lport.h          |   7 +-
>  controller/ovn-controller.c |  50 ++---
>  controller/ovn-controller.h |  34 ----
>  controller/patch.c          |   1 +
>  controller/physical.c       |   1 +
>  controller/pinctrl.c        |   1 +
>  13 files changed, 618 insertions(+), 385 deletions(-)
>  create mode 100644 controller/ldata.c
>  create mode 100644 controller/ldata.h
>
> diff --git a/controller/automake.mk b/controller/automake.mk
> index 2f6c50890..a3c5c6af5 100644
> --- a/controller/automake.mk
> +++ b/controller/automake.mk
> @@ -33,7 +33,9 @@ controller_ovn_controller_SOURCES = \
>         controller/physical.c \
>         controller/physical.h \
>         controller/mac-learn.c \
> -       controller/mac-learn.h
> +       controller/mac-learn.h \
> +       controller/ldata.c \
> +       controller/ldata.h
>
>  controller_ovn_controller_LDADD = lib/libovn.la $(OVS_LIBDIR)/
libopenvswitch.la
>  man_MANS += controller/ovn-controller.8
> diff --git a/controller/binding.c b/controller/binding.c
> index d50f3affa..e68546ca9 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -14,13 +14,8 @@
>   */
>
>  #include <config.h>
> -#include "binding.h"
> -#include "ha-chassis.h"
> -#include "if-status.h"
> -#include "lflow.h"
> -#include "lport.h"
> -#include "patch.h"
>
> +/* OVS includes. */
>  #include "lib/bitmap.h"
>  #include "openvswitch/poll-loop.h"
>  #include "lib/sset.h"
> @@ -29,9 +24,18 @@
>  #include "lib/vswitch-idl.h"
>  #include "openvswitch/hmap.h"
>  #include "openvswitch/vlog.h"
> +
> +/* OVN includes. */
> +#include "binding.h"
> +#include "ha-chassis.h"
> +#include "if-status.h"
> +#include "ldata.h"
> +#include "lflow.h"
>  #include "lib/chassis-index.h"
>  #include "lib/ovn-sb-idl.h"
> +#include "lport.h"
>  #include "ovn-controller.h"
> +#include "patch.h"
>
>  VLOG_DEFINE_THIS_MODULE(binding);
>
> @@ -76,106 +80,27 @@ binding_register_ovs_idl(struct ovsdb_idl *ovs_idl)
>      ovsdb_idl_add_column(ovs_idl, &ovsrec_qos_col_type);
>  }
>
> -static struct tracked_binding_datapath *tracked_binding_datapath_create(
> -    const struct sbrec_datapath_binding *,
> -    bool is_new, struct hmap *tracked_dps);
> -static struct tracked_binding_datapath *tracked_binding_datapath_find(
> -    struct hmap *, const struct sbrec_datapath_binding *);
> -static void tracked_binding_datapath_lport_add(
> -    const struct sbrec_port_binding *, struct hmap *tracked_datapaths);
>  static void update_lport_tracking(const struct sbrec_port_binding *pb,
> -                                  struct hmap *tracked_dp_bindings);
> -
> -static void
> -add_local_datapath__(struct ovsdb_idl_index
*sbrec_datapath_binding_by_key,
> -                     struct ovsdb_idl_index
*sbrec_port_binding_by_datapath,
> -                     struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                     const struct sbrec_datapath_binding *datapath,
> -                     bool has_local_l3gateway, int depth,
> -                     struct hmap *local_datapaths,
> -                     struct hmap *tracked_datapaths)
> -{
> -    uint32_t dp_key = datapath->tunnel_key;
> -    struct local_datapath *ld = get_local_datapath(local_datapaths,
dp_key);
> -    if (ld) {
> -        if (has_local_l3gateway) {
> -            ld->has_local_l3gateway = true;
> -        }
> -        return;
> -    }
> +                                  struct hmap *tracked_dp_bindings,
> +                                  bool claimed);
>
> -    ld = xzalloc(sizeof *ld);
> -    hmap_insert(local_datapaths, &ld->hmap_node, dp_key);
> -    ld->datapath = datapath;
> -    ld->localnet_port = NULL;
> -    shash_init(&ld->external_ports);
> -    ld->has_local_l3gateway = has_local_l3gateway;
> -
> -    if (tracked_datapaths) {
> -        struct tracked_binding_datapath *tdp =
> -            tracked_binding_datapath_find(tracked_datapaths, datapath);
> -        if (!tdp) {
> -            tracked_binding_datapath_create(datapath, true,
tracked_datapaths);
> -        } else {
> -            /* Its possible that there is already an entry in tracked
datapaths
> -             * for this 'datapath'. tracked_binding_datapath_lport_add()
may
> -             * have created it. Since the 'datapath' is added to the
> -             * local datapaths, set 'tdp->is_new' to true so that the
flows
> -             * for this datapath are programmed properly.
> -             * */
> -            tdp->is_new = true;
> -        }
> -    }
> +struct local_datpath_added_aux {
> +    bool has_local_l3gateway;
> +    struct hmap *tracked_datapaths;
> +};
>
> -    if (depth >= 100) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> -        VLOG_WARN_RL(&rl, "datapaths nested too deep");
> -        return;
> +/* This function is called by local_datapath_add() if a new
local_datapath
> + * is created. */
> +static void
> +local_datapath_added(struct local_datapath *ld, void *aux)
> +{
> +    struct local_datpath_added_aux *aux_ = aux;
> +    if (aux_->tracked_datapaths) {
> +        tracked_datapath_add(ld->datapath, TRACKED_RESOURCE_NEW,
> +                             aux_->tracked_datapaths);
>      }
>
> -    struct sbrec_port_binding *target =
> -
 sbrec_port_binding_index_init_row(sbrec_port_binding_by_datapath);
> -    sbrec_port_binding_index_set_datapath(target, datapath);
> -
> -    const struct sbrec_port_binding *pb;
> -    SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target,
> -                                       sbrec_port_binding_by_datapath) {
> -        if (!strcmp(pb->type, "patch") || !strcmp(pb->type,
"l3gateway")) {
> -            const char *peer_name = smap_get(&pb->options, "peer");
> -            if (peer_name) {
> -                const struct sbrec_port_binding *peer;
> -
> -                peer = lport_lookup_by_name(sbrec_port_binding_by_name,
> -                                            peer_name);
> -
> -                if (peer && peer->datapath) {
> -                    if (!strcmp(pb->type, "patch")) {
> -                        /* Add the datapath to local datapath only for
patch
> -                         * ports. For l3gateway ports, since gateway
router
> -                         * resides on one chassis, we don't need to add.
> -                         * Otherwise, all other chassis might create
patch
> -                         * ports between br-int and the provider bridge.
*/
> -
 add_local_datapath__(sbrec_datapath_binding_by_key,
> -
sbrec_port_binding_by_datapath,
> -                                             sbrec_port_binding_by_name,
> -                                             peer->datapath, false,
> -                                             depth + 1, local_datapaths,
> -                                             tracked_datapaths);
> -                    }
> -                    ld->n_peer_ports++;
> -                    if (ld->n_peer_ports > ld->n_allocated_peer_ports) {
> -                        ld->peer_ports =
> -                            x2nrealloc(ld->peer_ports,
> -                                       &ld->n_allocated_peer_ports,
> -                                       sizeof *ld->peer_ports);
> -                    }
> -                    ld->peer_ports[ld->n_peer_ports - 1].local = pb;
> -                    ld->peer_ports[ld->n_peer_ports - 1].remote = peer;
> -                }
> -            }
> -        }
> -    }
> -    sbrec_port_binding_index_destroy_row(target);
> +    ld->has_local_l3gateway = aux_->has_local_l3gateway;
>  }
>
>  static void
> @@ -186,11 +111,17 @@ add_local_datapath(struct ovsdb_idl_index
*sbrec_datapath_binding_by_key,
>                     bool has_local_l3gateway, struct hmap
*local_datapaths,
>                     struct hmap *tracked_datapaths)
>  {
> -    add_local_datapath__(sbrec_datapath_binding_by_key,
> -                         sbrec_port_binding_by_datapath,
> -                         sbrec_port_binding_by_name,
> -                         datapath, has_local_l3gateway, 0,
local_datapaths,
> -                         tracked_datapaths);
> +    struct local_datpath_added_aux aux = {
> +        .has_local_l3gateway = has_local_l3gateway,
> +        .tracked_datapaths = tracked_datapaths,
> +    };
> +
> +    local_datapath_add(local_datapaths, datapath,
> +                       sbrec_datapath_binding_by_key,
> +                       sbrec_port_binding_by_datapath,
> +                       sbrec_port_binding_by_name,
> +                       local_datapath_added,
> +                       &aux);
>  }
>
>  static void
> @@ -559,7 +490,8 @@ update_related_lport(const struct sbrec_port_binding
*pb,
>
>          if (b_ctx->tracked_dp_bindings) {
>              /* Add the 'pb' to the tracked_datapaths. */
> -            tracked_binding_datapath_lport_add(pb,
b_ctx->tracked_dp_bindings);
> +            tracked_datapath_lport_add(pb, TRACKED_RESOURCE_NEW,
> +                                       b_ctx->tracked_dp_bindings);
>          }
>      }
>      sset_add(&b_ctx->related_lports->lport_names, pb->logical_port);
> @@ -582,7 +514,8 @@ remove_related_lport(const struct sbrec_port_binding
*pb,
>
>          if (b_ctx->tracked_dp_bindings) {
>              /* Add the 'pb' to the tracked_datapaths. */
> -            tracked_binding_datapath_lport_add(pb,
b_ctx->tracked_dp_bindings);
> +            tracked_datapath_lport_add(pb, TRACKED_RESOURCE_REMOVED,
> +                                       b_ctx->tracked_dp_bindings);
>          }
>      }
>  }
> @@ -927,74 +860,6 @@ is_lport_vif(const struct sbrec_port_binding *pb)
>      return !pb->type[0];
>  }
>
> -static struct tracked_binding_datapath *
> -tracked_binding_datapath_create(const struct sbrec_datapath_binding *dp,
> -                                bool is_new,
> -                                struct hmap *tracked_datapaths)
> -{
> -    struct tracked_binding_datapath *t_dp = xzalloc(sizeof *t_dp);
> -    t_dp->dp = dp;
> -    t_dp->is_new = is_new;
> -    shash_init(&t_dp->lports);
> -    hmap_insert(tracked_datapaths, &t_dp->node,
uuid_hash(&dp->header_.uuid));
> -    return t_dp;
> -}
> -
> -static struct tracked_binding_datapath *
> -tracked_binding_datapath_find(struct hmap *tracked_datapaths,
> -                              const struct sbrec_datapath_binding *dp)
> -{
> -    struct tracked_binding_datapath *t_dp;
> -    size_t hash = uuid_hash(&dp->header_.uuid);
> -    HMAP_FOR_EACH_WITH_HASH (t_dp, node, hash, tracked_datapaths) {
> -        if (uuid_equals(&t_dp->dp->header_.uuid, &dp->header_.uuid)) {
> -            return t_dp;
> -        }
> -    }
> -
> -    return NULL;
> -}
> -
> -static void
> -tracked_binding_datapath_lport_add(const struct sbrec_port_binding *pb,
> -                                   struct hmap *tracked_datapaths)
> -{
> -    if (!tracked_datapaths) {
> -        return;
> -    }
> -
> -    struct tracked_binding_datapath *tracked_dp =
> -        tracked_binding_datapath_find(tracked_datapaths, pb->datapath);
> -    if (!tracked_dp) {
> -        tracked_dp = tracked_binding_datapath_create(pb->datapath, false,
> -                                                     tracked_datapaths);
> -    }
> -
> -    /* Check if the lport is already present or not.
> -     * If it is already present, then just update the 'pb' field. */
> -    struct tracked_binding_lport *lport =
> -        shash_find_data(&tracked_dp->lports, pb->logical_port);
> -
> -    if (!lport) {
> -        lport = xmalloc(sizeof *lport);
> -        shash_add(&tracked_dp->lports, pb->logical_port, lport);
> -    }
> -
> -    lport->pb = pb;
> -}
> -
> -void
> -binding_tracked_dp_destroy(struct hmap *tracked_datapaths)
> -{
> -    struct tracked_binding_datapath *t_dp;
> -    HMAP_FOR_EACH_POP (t_dp, node, tracked_datapaths) {
> -        shash_destroy_free_data(&t_dp->lports);
> -        free(t_dp);
> -    }
> -
> -    hmap_destroy(tracked_datapaths);
> -}
> -
>  static enum en_lport_type
>  get_lport_type(const struct sbrec_port_binding *pb)
>  {
> @@ -1129,7 +994,7 @@ claim_lport(const struct sbrec_port_binding *pb,
>          sbrec_port_binding_set_chassis(pb, chassis_rec);
>
>          if (tracked_datapaths) {
> -            update_lport_tracking(pb, tracked_datapaths);
> +            update_lport_tracking(pb, tracked_datapaths, true);
>          }
>      }
>
> @@ -1178,7 +1043,7 @@ release_lport(const struct sbrec_port_binding *pb,
bool sb_readonly,
>          sbrec_port_binding_set_virtual_parent(pb, NULL);
>      }
>
> -    update_lport_tracking(pb, tracked_datapaths);
> +    update_lport_tracking(pb, tracked_datapaths, false);
>      if_status_mgr_release_iface(if_mgr, pb->logical_port);
>      VLOG_INFO("Releasing lport %s from this chassis.", pb->logical_port);
>      return true;
> @@ -1828,42 +1693,6 @@ binding_cleanup(struct ovsdb_idl_txn
*ovnsb_idl_txn,
>      return !any_changes;
>  }
>
> -static const struct sbrec_port_binding *
> -get_peer_lport__(const struct sbrec_port_binding *pb,
> -                 struct binding_ctx_in *b_ctx_in)
> -{
> -    const char *peer_name = smap_get(&pb->options, "peer");
> -
> -    if (!peer_name) {
> -        return NULL;
> -    }
> -
> -    const struct sbrec_port_binding *peer;
> -    peer = lport_lookup_by_name(b_ctx_in->sbrec_port_binding_by_name,
> -                                peer_name);
> -    return (peer && peer->datapath) ? peer : NULL;
> -}
> -
> -static const struct sbrec_port_binding *
> -get_l3gw_peer_lport(const struct sbrec_port_binding *pb,
> -                    struct binding_ctx_in *b_ctx_in)
> -{
> -    if (strcmp(pb->type, "l3gateway")) {
> -        return NULL;
> -    }
> -    return get_peer_lport__(pb, b_ctx_in);
> -}
> -
> -static const struct sbrec_port_binding *
> -get_peer_lport(const struct sbrec_port_binding *pb,
> -               struct binding_ctx_in *b_ctx_in)
> -{
> -    if (strcmp(pb->type, "patch")) {
> -        return NULL;
> -    }
> -    return get_peer_lport__(pb, b_ctx_in);
> -}
> -
>  /* This function adds the local datapath of the 'peer' of
>   * lport 'pb' to the local datapaths if it is not yet added.
>   */
> @@ -1873,61 +1702,16 @@ add_local_datapath_peer_port(const struct
sbrec_port_binding *pb,
>                               struct binding_ctx_out *b_ctx_out,
>                               struct local_datapath *ld)
>  {
> -    const struct sbrec_port_binding *peer;
> -    peer = get_peer_lport(pb, b_ctx_in);
> -
> -    if (!peer) {
> -        return;
> -    }
> -
> -    bool present = false;
> -    for (size_t i = 0; i < ld->n_peer_ports; i++) {
> -        if (ld->peer_ports[i].local == pb) {
> -            present = true;
> -            break;
> -        }
> -    }
> -
> -    if (!present) {
> -        ld->n_peer_ports++;
> -        if (ld->n_peer_ports > ld->n_allocated_peer_ports) {
> -            ld->peer_ports =
> -                x2nrealloc(ld->peer_ports,
> -                           &ld->n_allocated_peer_ports,
> -                           sizeof *ld->peer_ports);
> -        }
> -        ld->peer_ports[ld->n_peer_ports - 1].local = pb;
> -        ld->peer_ports[ld->n_peer_ports - 1].remote = peer;
> -    }
> -
> -    struct local_datapath *peer_ld =
> -        get_local_datapath(b_ctx_out->local_datapaths,
> -                           peer->datapath->tunnel_key);
> -    if (!peer_ld) {
> -        add_local_datapath__(b_ctx_in->sbrec_datapath_binding_by_key,
> -                             b_ctx_in->sbrec_port_binding_by_datapath,
> -                             b_ctx_in->sbrec_port_binding_by_name,
> -                             peer->datapath, false,
> -                             1, b_ctx_out->local_datapaths,
> -                             b_ctx_out->tracked_dp_bindings);
> -        return;
> -    }
> -
> -    for (size_t i = 0; i < peer_ld->n_peer_ports; i++) {
> -        if (peer_ld->peer_ports[i].local == peer) {
> -            return;
> -        }
> -    }
> +    struct local_datpath_added_aux aux = {
> +        .has_local_l3gateway = false,
> +        .tracked_datapaths = b_ctx_out->tracked_dp_bindings,
> +    };
>
> -    peer_ld->n_peer_ports++;
> -    if (peer_ld->n_peer_ports > peer_ld->n_allocated_peer_ports) {
> -        peer_ld->peer_ports =
> -            x2nrealloc(peer_ld->peer_ports,
> -                        &peer_ld->n_allocated_peer_ports,
> -                        sizeof *peer_ld->peer_ports);
> -    }
> -    peer_ld->peer_ports[peer_ld->n_peer_ports - 1].local = peer;
> -    peer_ld->peer_ports[peer_ld->n_peer_ports - 1].remote = pb;
> +    local_datapath_add_peer_port(pb,
b_ctx_in->sbrec_datapath_binding_by_key,
> +
b_ctx_in->sbrec_port_binding_by_datapath,
> +                                 b_ctx_in->sbrec_port_binding_by_name,
> +                                 ld, b_ctx_out->local_datapaths,
> +                                 local_datapath_added, &aux);
>  }
>
>  static void
> @@ -1935,34 +1719,7 @@ remove_local_datapath_peer_port(const struct
sbrec_port_binding *pb,
>                                  struct local_datapath *ld,
>                                  struct hmap *local_datapaths)
>  {
> -    size_t i = 0;
> -    for (i = 0; i < ld->n_peer_ports; i++) {
> -        if (ld->peer_ports[i].local == pb) {
> -            break;
> -        }
> -    }
> -
> -    if (i == ld->n_peer_ports) {
> -        return;
> -    }
> -
> -    const struct sbrec_port_binding *peer = ld->peer_ports[i].remote;
> -
> -    /* Possible improvement: We can shrink the allocated peer ports
> -     * if (ld->n_peer_ports < ld->n_allocated_peer_ports / 2).
> -     */
> -    ld->peer_ports[i].local = ld->peer_ports[ld->n_peer_ports - 1].local;
> -    ld->peer_ports[i].remote = ld->peer_ports[ld->n_peer_ports -
1].remote;
> -    ld->n_peer_ports--;
> -
> -    struct local_datapath *peer_ld =
> -        get_local_datapath(local_datapaths, peer->datapath->tunnel_key);
> -    if (peer_ld) {
> -        /* Remove the peer port from the peer datapath. The peer
> -         * datapath also tries to remove its peer lport, but that would
> -         * be no-op. */
> -        remove_local_datapath_peer_port(peer, peer_ld, local_datapaths);
> -    }
> +   local_datapath_remove_peer_port(pb, ld, local_datapaths);
>  }
>
>  static void
> @@ -1995,13 +1752,16 @@ remove_pb_from_local_datapath(const struct
sbrec_port_binding *pb,
>
>  static void
>  update_lport_tracking(const struct sbrec_port_binding *pb,
> -                      struct hmap *tracked_dp_bindings)
> +                      struct hmap *tracked_dp_bindings,
> +                      bool claimed)
>  {
>      if (!tracked_dp_bindings) {
>          return;
>      }
>
> -    tracked_binding_datapath_lport_add(pb, tracked_dp_bindings);
> +    tracked_datapath_lport_add(
> +        pb, claimed ? TRACKED_RESOURCE_NEW : TRACKED_RESOURCE_REMOVED,
> +        tracked_dp_bindings);
>  }
>
>  /* Considers the ovs iface 'iface_rec' for claiming.
> @@ -2315,7 +2075,7 @@ handle_deleted_lport(const struct
sbrec_port_binding *pb,
>      /* If the binding is not local, if 'pb' is a L3 gateway port, we
should
>       * remove its peer, if that one is local.
>       */
> -    pb = get_l3gw_peer_lport(pb, b_ctx_in);
> +    pb = lport_get_l3gw_peer(pb, b_ctx_in->sbrec_port_binding_by_name);
>      if (pb) {
>          ld = get_local_datapath(b_ctx_out->local_datapaths,
>                                  pb->datapath->tunnel_key);
> @@ -2598,7 +2358,10 @@ delete_done:
>                       * */
>                      const struct sbrec_port_binding *peer;
>                      struct local_datapath *peer_ld = NULL;
> -                    peer = get_peer_lport(pb, b_ctx_in);
> +                    peer =
> +                        lport_get_peer(pb,
> +
b_ctx_in->sbrec_port_binding_by_name);
> +
>                      if (peer) {
>                          peer_ld =
>
 get_local_datapath(b_ctx_out->local_datapaths,
> diff --git a/controller/binding.h b/controller/binding.h
> index 77197e742..b1717bd2b 100644
> --- a/controller/binding.h
> +++ b/controller/binding.h
> @@ -121,19 +121,6 @@ void local_binding_set_up(struct shash
*local_bindings, const char *pb_name,
>  void local_binding_set_down(struct shash *local_bindings, const char
*pb_name,
>                              bool sb_readonly, bool ovs_readonly);
>
> -/* Represents a tracked binding logical port. */
> -struct tracked_binding_lport {
> -    const struct sbrec_port_binding *pb;
> -};
> -
> -/* Represent a tracked binding datapath. */
> -struct tracked_binding_datapath {
> -    struct hmap_node node;
> -    const struct sbrec_datapath_binding *dp;
> -    bool is_new;
> -    struct shash lports; /* shash of struct tracked_binding_lport. */
> -};
> -
>  void binding_register_ovs_idl(struct ovsdb_idl *);
>  void binding_run(struct binding_ctx_in *, struct binding_ctx_out *);
>  bool binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
> diff --git a/controller/ldata.c b/controller/ldata.c
> new file mode 100644
> index 000000000..a6df9b1da
> --- /dev/null
> +++ b/controller/ldata.c
> @@ -0,0 +1,368 @@
> +/* Copyright (c) 2021, Red Hat, Inc.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at:
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#include <config.h>
> +
> +/* OVS includes. */
> +#include "include/openvswitch/json.h"
> +#include "lib/hmapx.h"
> +#include "lib/util.h"
> +#include "openvswitch/vlog.h"
> +
> +/* OVN includes. */
> +#include "ldata.h"
> +#include "lport.h"
> +#include "lib/ovn-util.h"
> +#include "lib/ovn-sb-idl.h"
> +
> +VLOG_DEFINE_THIS_MODULE(ldata);
> +
> +static struct local_datapath *local_datapath_add__(
> +    struct hmap *local_datapaths,
> +    const struct sbrec_datapath_binding *,
> +    struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> +    int depth,
> +    void (*datapath_added)(struct local_datapath *,
> +                           void *aux),
> +    void *aux);
> +
> +static struct tracked_datapath *tracked_datapath_create(
> +    const struct sbrec_datapath_binding *dp,
> +    enum en_tracked_resource_type tracked_type,
> +    struct hmap *tracked_datapaths);
> +
> +struct local_datapath *
> +get_local_datapath(const struct hmap *local_datapaths, uint32_t
tunnel_key)
> +{
> +    struct hmap_node *node = hmap_first_with_hash(local_datapaths,
tunnel_key);
> +    return (node
> +            ? CONTAINER_OF(node, struct local_datapath, hmap_node)
> +            : NULL);
> +}
> +
> +struct local_datapath *
> +local_datapath_alloc(const struct sbrec_datapath_binding *dp)
> +{
> +    struct local_datapath *ld = xzalloc(sizeof *ld);
> +    ld->datapath = dp;
> +    ld->is_switch = datapath_is_switch(dp);
> +    shash_init(&ld->external_ports);
> +    return ld;
> +}
> +
> +void
> +local_datapaths_destroy(struct hmap *local_datapaths)
> +{
> +    struct local_datapath *ld;
> +    HMAP_FOR_EACH_POP (ld, hmap_node, local_datapaths) {
> +        local_datapath_destroy(ld);
> +    }
> +
> +    hmap_destroy(local_datapaths);
> +}
> +
> +void
> +local_datapath_destroy(struct local_datapath *ld)
> +{
> +    free(ld->peer_ports);
> +    shash_destroy(&ld->external_ports);
> +    free(ld);
> +}
> +
> +void
> +local_datapath_add(struct hmap *local_datapaths,
> +                   const struct sbrec_datapath_binding *dp,
> +                   struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> +                   struct ovsdb_idl_index
*sbrec_port_binding_by_datapath,
> +                   struct ovsdb_idl_index *sbrec_port_binding_by_name,
> +                   void (*datapath_added_cb)(
> +                         struct local_datapath *ld,
> +                         void *aux),
> +                   void *aux)
> +{
> +    local_datapath_add__(local_datapaths, dp,
sbrec_datapath_binding_by_key,
> +                         sbrec_port_binding_by_datapath,
> +                         sbrec_port_binding_by_name, 0,
> +                         datapath_added_cb, aux);
> +}
> +
> +void
> +local_datapath_add_peer_port(
> +    const struct sbrec_port_binding *pb,
> +    struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> +    struct local_datapath *ld,
> +    struct hmap *local_datapaths,
> +    void (*datapath_added_cb)(
> +                         struct local_datapath *ld,
> +                         void *aux),
> +    void *aux)
> +{
> +    const struct sbrec_port_binding *peer;
> +    peer = lport_get_peer(pb, sbrec_port_binding_by_name);
> +
> +    if (!peer) {
> +        return;
> +    }
> +
> +    bool present = false;
> +    for (size_t i = 0; i < ld->n_peer_ports; i++) {
> +        if (ld->peer_ports[i].local == pb) {
> +            present = true;
> +            break;
> +        }
> +    }
> +
> +    if (!present) {
> +        ld->n_peer_ports++;
> +        if (ld->n_peer_ports > ld->n_allocated_peer_ports) {
> +            ld->peer_ports =
> +                x2nrealloc(ld->peer_ports,
> +                           &ld->n_allocated_peer_ports,
> +                           sizeof *ld->peer_ports);
> +        }
> +        ld->peer_ports[ld->n_peer_ports - 1].local = pb;
> +        ld->peer_ports[ld->n_peer_ports - 1].remote = peer;
> +    }
> +
> +    struct local_datapath *peer_ld =
> +        get_local_datapath(local_datapaths,
> +                           peer->datapath->tunnel_key);
> +    if (!peer_ld) {
> +        local_datapath_add__(local_datapaths, peer->datapath,
> +                             sbrec_datapath_binding_by_key,
> +                             sbrec_port_binding_by_datapath,
> +                             sbrec_port_binding_by_name, 1,
> +                             datapath_added_cb, aux);
> +        return;
> +    }
> +
> +    for (size_t i = 0; i < peer_ld->n_peer_ports; i++) {
> +        if (peer_ld->peer_ports[i].local == peer) {
> +            return;
> +        }
> +    }
> +
> +    peer_ld->n_peer_ports++;
> +    if (peer_ld->n_peer_ports > peer_ld->n_allocated_peer_ports) {
> +        peer_ld->peer_ports =
> +            x2nrealloc(peer_ld->peer_ports,
> +                        &peer_ld->n_allocated_peer_ports,
> +                        sizeof *peer_ld->peer_ports);
> +    }
> +    peer_ld->peer_ports[peer_ld->n_peer_ports - 1].local = peer;
> +    peer_ld->peer_ports[peer_ld->n_peer_ports - 1].remote = pb;
> +}
> +
> +void
> +local_datapath_remove_peer_port(const struct sbrec_port_binding *pb,
> +                                struct local_datapath *ld,
> +                                struct hmap *local_datapaths)
> +{
> +    size_t i = 0;
> +    for (i = 0; i < ld->n_peer_ports; i++) {
> +        if (ld->peer_ports[i].local == pb) {
> +            break;
> +        }
> +    }
> +
> +    if (i == ld->n_peer_ports) {
> +        return;
> +    }
> +
> +    const struct sbrec_port_binding *peer = ld->peer_ports[i].remote;
> +
> +    /* Possible improvement: We can shrink the allocated peer ports
> +     * if (ld->n_peer_ports < ld->n_allocated_peer_ports / 2).
> +     */
> +    ld->peer_ports[i].local = ld->peer_ports[ld->n_peer_ports - 1].local;
> +    ld->peer_ports[i].remote = ld->peer_ports[ld->n_peer_ports -
1].remote;
> +    ld->n_peer_ports--;
> +
> +    struct local_datapath *peer_ld =
> +        get_local_datapath(local_datapaths, peer->datapath->tunnel_key);
> +    if (peer_ld) {
> +        /* Remove the peer port from the peer datapath. The peer
> +         * datapath also tries to remove its peer lport, but that would
> +         * be no-op. */
> +        local_datapath_remove_peer_port(peer, peer_ld, local_datapaths);
> +    }
> +}
> +
> +/* track datapath functions. */
> +struct tracked_datapath *
> +tracked_datapath_add(const struct sbrec_datapath_binding *dp,
> +                     enum en_tracked_resource_type tracked_type,
> +                     struct hmap *tracked_datapaths)
> +{
> +    struct tracked_datapath *t_dp =
> +        tracked_datapath_find(tracked_datapaths, dp);
> +    if (!t_dp) {
> +        t_dp = tracked_datapath_create(dp, tracked_type,
tracked_datapaths);
> +    } else {
> +        t_dp->tracked_type = tracked_type;
> +    }
> +
> +    return t_dp;
> +}
> +
> +struct tracked_datapath *
> +tracked_datapath_find(struct hmap *tracked_datapaths,
> +                      const struct sbrec_datapath_binding *dp)
> +{
> +    struct tracked_datapath *t_dp;
> +    size_t hash = uuid_hash(&dp->header_.uuid);
> +    HMAP_FOR_EACH_WITH_HASH (t_dp, node, hash, tracked_datapaths) {
> +        if (uuid_equals(&t_dp->dp->header_.uuid, &dp->header_.uuid)) {
> +            return t_dp;
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
> +void
> +tracked_datapath_lport_add(const struct sbrec_port_binding *pb,
> +                           enum en_tracked_resource_type tracked_type,
> +                           struct hmap *tracked_datapaths)
> +{
> +    struct tracked_datapath *tracked_dp =
> +        tracked_datapath_find(tracked_datapaths, pb->datapath);
> +    if (!tracked_dp) {
> +        tracked_dp = tracked_datapath_create(pb->datapath,
> +                                             TRACKED_RESOURCE_UPDATED,
> +                                             tracked_datapaths);
> +    }
> +
> +    /* Check if the lport is already present or not.
> +     * If it is already present, then just update the 'pb' field. */
> +    struct tracked_lport *lport =
> +        shash_find_data(&tracked_dp->lports, pb->logical_port);
> +
> +    if (!lport) {
> +        lport = xmalloc(sizeof *lport);
> +        shash_add(&tracked_dp->lports, pb->logical_port, lport);
> +    }
> +
> +    lport->pb = pb;
> +    lport->tracked_type = tracked_type;
> +}
> +
> +void
> +tracked_datapaths_destroy(struct hmap *tracked_datapaths)
> +{
> +    struct tracked_datapath *t_dp;
> +    HMAP_FOR_EACH_POP (t_dp, node, tracked_datapaths) {
> +        shash_destroy_free_data(&t_dp->lports);
> +        free(t_dp);
> +    }
> +
> +    hmap_destroy(tracked_datapaths);
> +}
> +
> +/* static functions. */
> +static struct local_datapath *
> +local_datapath_add__(struct hmap *local_datapaths,
> +                     const struct sbrec_datapath_binding *dp,
> +                     struct ovsdb_idl_index
*sbrec_datapath_binding_by_key,
> +                     struct ovsdb_idl_index
*sbrec_port_binding_by_datapath,
> +                     struct ovsdb_idl_index *sbrec_port_binding_by_name,
> +                     int depth,
> +                     void (*datapath_added_cb)(
> +                           struct local_datapath *ld,
> +                           void *aux),
> +                     void *aux)
> +{
> +    uint32_t dp_key = dp->tunnel_key;
> +    struct local_datapath *ld = get_local_datapath(local_datapaths,
dp_key);
> +    if (ld) {
> +        return ld;

This changes the original behavior that when the ld is found it updates the
has_local_l3gateway before returning. Would this cause a problem?

> +    }
> +
> +    ld = local_datapath_alloc(dp);
> +    hmap_insert(local_datapaths, &ld->hmap_node, dp_key);
> +    ld->datapath = dp;
> +
> +    if (datapath_added_cb) {
> +        datapath_added_cb(ld, aux);
> +    }
> +
> +    if (depth >= 100) {
> +        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
> +        VLOG_WARN_RL(&rl, "datapaths nested too deep");
> +        return ld;
> +    }
> +
> +    struct sbrec_port_binding *target =
> +
 sbrec_port_binding_index_init_row(sbrec_port_binding_by_datapath);
> +    sbrec_port_binding_index_set_datapath(target, dp);
> +
> +    const struct sbrec_port_binding *pb;
> +    SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, target,
> +                                       sbrec_port_binding_by_datapath) {
> +        if (!strcmp(pb->type, "patch") || !strcmp(pb->type,
"l3gateway")) {
> +            const char *peer_name = smap_get(&pb->options, "peer");
> +            if (peer_name) {
> +                const struct sbrec_port_binding *peer;
> +
> +                peer = lport_lookup_by_name(sbrec_port_binding_by_name,
> +                                            peer_name);
> +
> +                if (peer && peer->datapath) {
> +                    if (!strcmp(pb->type, "patch")) {
> +                        /* Add the datapath to local datapath only for
patch
> +                         * ports. For l3gateway ports, since gateway
router
> +                         * resides on one chassis, we don't need to add.
> +                         * Otherwise, all other chassis might create
patch
> +                         * ports between br-int and the provider bridge.
*/
> +                        local_datapath_add__(local_datapaths,
peer->datapath,
> +
sbrec_datapath_binding_by_key,
> +
sbrec_port_binding_by_datapath,
> +                                             sbrec_port_binding_by_name,
> +                                             depth + 1,
datapath_added_cb,
> +                                             aux);
> +                    }
> +                    ld->n_peer_ports++;
> +                    if (ld->n_peer_ports > ld->n_allocated_peer_ports) {
> +                        ld->peer_ports =
> +                            x2nrealloc(ld->peer_ports,
> +                                       &ld->n_allocated_peer_ports,
> +                                       sizeof *ld->peer_ports);
> +                    }
> +                    ld->peer_ports[ld->n_peer_ports - 1].local = pb;
> +                    ld->peer_ports[ld->n_peer_ports - 1].remote = peer;
> +                }
> +            }
> +        }
> +    }
> +    sbrec_port_binding_index_destroy_row(target);
> +    return ld;
> +}
> +
> +static struct tracked_datapath *
> +tracked_datapath_create(const struct sbrec_datapath_binding *dp,
> +                        enum en_tracked_resource_type tracked_type,
> +                        struct hmap *tracked_datapaths)
> +{
> +    struct tracked_datapath *t_dp = xzalloc(sizeof *t_dp);
> +    t_dp->dp = dp;
> +    t_dp->tracked_type = tracked_type;
> +    shash_init(&t_dp->lports);
> +    hmap_insert(tracked_datapaths, &t_dp->node,
uuid_hash(&dp->header_.uuid));
> +    return t_dp;
> +}
> diff --git a/controller/ldata.h b/controller/ldata.h
> new file mode 100644
> index 000000000..16ad43c8f
> --- /dev/null
> +++ b/controller/ldata.h
> @@ -0,0 +1,120 @@
> +/* Copyright (c) 2021, Red Hat, Inc.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at:
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#ifndef LDATA_H
> +#define LDATA_H 1
> +
> +/* OVS includes. */
> +#include "include/openvswitch/shash.h"
> +#include "lib/smap.h"
> +
> +struct sbrec_datapath_binding;
> +struct sbrec_port_binding;
> +struct ovsdb_idl_index;
> +
> +/* A logical datapath that has some relevance to this hypervisor.  A
logical
> + * datapath D is relevant to hypervisor H if:
> + *
> + *     - Some VIF or l2gateway or l3gateway port in D is located on H.
> + *
> + *     - D is reachable over a series of hops across patch ports,
starting from
> + *       a datapath relevant to H.
> + *
> + * The 'hmap_node''s hash value is 'datapath->tunnel_key'. */
> +struct local_datapath {
> +    struct hmap_node hmap_node;
> +    const struct sbrec_datapath_binding *datapath;
> +    bool is_switch;
> +
> +    /* The localnet port in this datapath, if any (at most one is
allowed). */
> +    const struct sbrec_port_binding *localnet_port;
> +
> +    /* True if this datapath contains an l3gateway port located on this
> +     * hypervisor. */
> +    bool has_local_l3gateway;
> +
> +    struct {
> +        const struct sbrec_port_binding *local;
> +        const struct sbrec_port_binding *remote;
> +    } *peer_ports;
> +
> +    size_t n_peer_ports;
> +    size_t n_allocated_peer_ports;
> +
> +    struct shash external_ports;
> +};
> +
> +struct local_datapath *local_datapath_alloc(
> +    const struct sbrec_datapath_binding *);
> +struct local_datapath *get_local_datapath(const struct hmap *,
> +                                          uint32_t tunnel_key);
> +void local_datapath_add(struct hmap *local_datapaths,
> +                        const struct sbrec_datapath_binding *,
> +                        struct ovsdb_idl_index
*sbrec_datapath_binding_by_key,
> +                        struct ovsdb_idl_index
*sbrec_port_binding_by_datapath,
> +                        struct ovsdb_idl_index
*sbrec_port_binding_by_name,
> +                        void (*datapath_added)(struct local_datapath *,
> +                                               void *aux),
> +                        void *aux);
> +
> +void local_datapaths_destroy(struct hmap *local_datapaths);
> +void local_datapath_destroy(struct local_datapath *ld);
> +void local_datapath_add_peer_port(
> +    const struct sbrec_port_binding *pb,
> +    struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name,
> +    struct local_datapath *ld,
> +    struct hmap *local_datapaths,
> +    void (*datapath_added_cb)(
> +                         struct local_datapath *ld,
> +                         void *aux),
> +    void *aux);
> +
> +void local_datapath_remove_peer_port(const struct sbrec_port_binding *pb,
> +                                     struct local_datapath *ld,
> +                                     struct hmap *local_datapaths);
> +
> +enum en_tracked_resource_type {
> +    TRACKED_RESOURCE_NEW,
> +    TRACKED_RESOURCE_REMOVED,
> +    TRACKED_RESOURCE_UPDATED
> +};
> +
> +/* Represents a tracked logical port. */
> +struct tracked_lport {
> +    const struct sbrec_port_binding *pb;
> +    enum en_tracked_resource_type tracked_type;
> +};
> +
> +/* Represent a tracked datapath. */
> +struct tracked_datapath {
> +    struct hmap_node node;
> +    const struct sbrec_datapath_binding *dp;
> +    enum en_tracked_resource_type tracked_type;
> +    struct shash lports; /* shash of struct tracked_binding_lport. */
> +};
> +
> +struct tracked_datapath * tracked_datapath_add(
> +    const struct sbrec_datapath_binding *, enum en_tracked_resource_type,
> +    struct hmap *tracked_datapaths);
> +struct tracked_datapath *tracked_datapath_find(
> +    struct hmap *tracked_datapaths, const struct sbrec_datapath_binding
*);
> +void tracked_datapath_lport_add(const struct sbrec_port_binding *,
> +                                enum en_tracked_resource_type,
> +                                struct hmap *tracked_datapaths);
> +void tracked_datapaths_destroy(struct hmap *tracked_datapaths);
> +
> +#endif /* controller/ldata.h */
> diff --git a/controller/lflow.c b/controller/lflow.c
> index c58c4f25c..d1f32077b 100644
> --- a/controller/lflow.c
> +++ b/controller/lflow.c
> @@ -17,6 +17,7 @@
>  #include "lflow.h"
>  #include "coverage.h"
>  #include "ha-chassis.h"
> +#include "ldata.h"
>  #include "lflow-cache.h"
>  #include "lport.h"
>  #include "ofctrl.h"
> diff --git a/controller/lport.c b/controller/lport.c
> index 478fcfd82..25b4ef200 100644
> --- a/controller/lport.c
> +++ b/controller/lport.c
> @@ -23,6 +23,10 @@
>  #include "lib/ovn-sb-idl.h"
>  VLOG_DEFINE_THIS_MODULE(lport);
>
> +static const struct sbrec_port_binding *get_peer_lport(
> +    const struct sbrec_port_binding *pb,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name);
> +
>  const struct sbrec_port_binding *
>  lport_lookup_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name,
>                       const char *name)
> @@ -84,6 +88,26 @@ lport_is_chassis_resident(struct ovsdb_idl_index
*sbrec_port_binding_by_name,
>      }
>  }
>
> +const struct sbrec_port_binding *
> +lport_get_peer(const struct sbrec_port_binding *pb,
> +               struct ovsdb_idl_index *sbrec_port_binding_by_name)
> +{
> +    if (strcmp(pb->type, "patch")) {
> +        return NULL;
> +    }
> +    return get_peer_lport(pb, sbrec_port_binding_by_name);
> +}
> +
> +const struct sbrec_port_binding *
> +lport_get_l3gw_peer(const struct sbrec_port_binding *pb,
> +                    struct ovsdb_idl_index *sbrec_port_binding_by_name)
> +{
> +    if (strcmp(pb->type, "l3gateway")) {
> +        return NULL;
> +    }
> +    return get_peer_lport(pb, sbrec_port_binding_by_name);
> +}
> +
>  const struct sbrec_datapath_binding *
>  datapath_lookup_by_key(struct ovsdb_idl_index
*sbrec_datapath_binding_by_key,
>                         uint64_t dp_key)
> @@ -120,3 +144,19 @@ mcgroup_lookup_by_dp_name(
>
>      return retval;
>  }
> +
> +static const struct sbrec_port_binding *
> +get_peer_lport(const struct sbrec_port_binding *pb,
> +               struct ovsdb_idl_index *sbrec_port_binding_by_name)
> +{
> +    const char *peer_name = smap_get(&pb->options, "peer");
> +
> +    if (!peer_name) {
> +        return NULL;
> +    }
> +
> +    const struct sbrec_port_binding *peer;
> +    peer = lport_lookup_by_name(sbrec_port_binding_by_name,
> +                                peer_name);
> +    return (peer && peer->datapath) ? peer : NULL;
> +}
> diff --git a/controller/lport.h b/controller/lport.h
> index 345efc184..43b3d714d 100644
> --- a/controller/lport.h
> +++ b/controller/lport.h
> @@ -54,5 +54,10 @@ lport_is_chassis_resident(struct ovsdb_idl_index
*sbrec_port_binding_by_name,
>                            const struct sbrec_chassis *chassis,
>                            const struct sset *active_tunnels,
>                            const char *port_name);
> -
> +const struct sbrec_port_binding *lport_get_peer(
> +    const struct sbrec_port_binding *,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name);
> +const struct sbrec_port_binding *lport_get_l3gw_peer(
> +    const struct sbrec_port_binding *,
> +    struct ovsdb_idl_index *sbrec_port_binding_by_name);
>  #endif /* controller/lport.h */
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 2418c301b..8f620e4ad 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -39,6 +39,7 @@
>  #include "lflow.h"
>  #include "lflow-cache.h"
>  #include "lib/vswitch-idl.h"
> +#include "ldata.h"
>  #include "lport.h"
>  #include "memory.h"
>  #include "ofctrl.h"
> @@ -131,15 +132,6 @@ struct pending_pkt {
>  /* Registered ofctrl seqno type for nb_cfg propagation. */
>  static size_t ofctrl_seq_type_nb_cfg;
>
> -struct local_datapath *
> -get_local_datapath(const struct hmap *local_datapaths, uint32_t
tunnel_key)
> -{
> -    struct hmap_node *node = hmap_first_with_hash(local_datapaths,
tunnel_key);
> -    return (node
> -            ? CONTAINER_OF(node, struct local_datapath, hmap_node)
> -            : NULL);
> -}
> -
>  uint32_t
>  get_tunnel_type(const char *name)
>  {
> @@ -1067,8 +1059,8 @@ struct ed_type_runtime_data {
>   *
>   *
 ------------------------------------------------------------------------
>   * |                      | This is a hmap of
    |
> - * |                      | 'struct tracked_binding_datapath' defined in
   |
> - * |                      | binding.h. Runtime data handlers for OVS
   |
> + * |                      | 'struct tracked_datapath' defined in    |
> + * |                      | ldata.h. Runtime data handlers for OVS
 |
>   * |                      | Interface and Port Binding changes store the
   |
>   * | @tracked_dp_bindings | changed datapaths (datapaths added/removed
from |
>   * |                      | local_datapaths) and changed port bindings
   |

nit: Some alignment problem of the right side border of the above table.

Thanks,
Han

> @@ -1126,7 +1118,7 @@ en_runtime_data_clear_tracked_data(void *data_)
>  {
>      struct ed_type_runtime_data *data = data_;
>
> -    binding_tracked_dp_destroy(&data->tracked_dp_bindings);
> +    tracked_datapaths_destroy(&data->tracked_dp_bindings);
>      hmap_init(&data->tracked_dp_bindings);
>      data->local_lports_changed = false;
>      data->tracked = false;
> @@ -1164,15 +1156,7 @@ en_runtime_data_cleanup(void *data)
>      sset_destroy(&rt_data->active_tunnels);
>      sset_destroy(&rt_data->egress_ifaces);
>      smap_destroy(&rt_data->local_iface_ids);
> -    struct local_datapath *cur_node, *next_node;
> -    HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node,
> -                        &rt_data->local_datapaths) {
> -        free(cur_node->peer_ports);
> -        shash_destroy(&cur_node->external_ports);
> -        hmap_remove(&rt_data->local_datapaths, &cur_node->hmap_node);
> -        free(cur_node);
> -    }
> -    hmap_destroy(&rt_data->local_datapaths);
> +    local_datapaths_destroy(&rt_data->local_datapaths);
>      shash_destroy_free_data(&rt_data->local_active_ports_ipv6_pd);
>      shash_destroy_free_data(&rt_data->local_active_ports_ras);
>      local_binding_data_destroy(&rt_data->lbinding_data);
> @@ -1284,14 +1268,7 @@ en_runtime_data_run(struct engine_node *node, void
*data)
>          /* 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_ports);
> -            shash_destroy(&cur_node->external_ports);
> -            hmap_remove(local_datapaths, &cur_node->hmap_node);
> -            free(cur_node);
> -        }
> -        hmap_clear(local_datapaths);
> +        local_datapaths_destroy(local_datapaths);
>          shash_clear_free_data(local_active_ipv6_pd);
>          shash_clear_free_data(local_active_ras);
>          local_binding_data_destroy(&rt_data->lbinding_data);
> @@ -1300,6 +1277,7 @@ en_runtime_data_run(struct engine_node *node, void
*data)
>          sset_destroy(active_tunnels);
>          sset_destroy(&rt_data->egress_ifaces);
>          smap_destroy(&rt_data->local_iface_ids);
> +        hmap_init(local_datapaths);
>          sset_init(local_lports);
>          related_lports_init(&rt_data->related_lports);
>          sset_init(active_tunnels);
> @@ -1741,12 +1719,12 @@ port_groups_runtime_data_handler(struct
engine_node *node, void *data)
>                                                   pg_sb->name);
>          ovs_assert(pg_lports);
>
> -        struct tracked_binding_datapath *tdp;
> +        struct tracked_datapath *tdp;
>          bool need_update = false;
>          HMAP_FOR_EACH (tdp, node, &rt_data->tracked_dp_bindings) {
>              struct shash_node *shash_node;
>              SHASH_FOR_EACH (shash_node, &tdp->lports) {
> -                struct tracked_binding_lport *lport = shash_node->data;
> +                struct tracked_lport *lport = shash_node->data;
>                  if (sset_contains(pg_lports, lport->pb->logical_port)) {
>                      /* At least one local port-binding change is related
to the
>                       * port_group, so the port_group_cs_local needs
update. */
> @@ -1899,9 +1877,9 @@ ct_zones_runtime_data_handler(struct engine_node
*node, void *data OVS_UNUSED)
>      }
>
>      struct hmap *tracked_dp_bindings = &rt_data->tracked_dp_bindings;
> -    struct tracked_binding_datapath *tdp;
> +    struct tracked_datapath *tdp;
>      HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) {
> -        if (tdp->is_new) {
> +        if (tdp->tracked_type == TRACKED_RESOURCE_NEW) {
>              /* A new datapath has been added. Fall back to full
recompute. */
>              return false;
>          }
> @@ -2423,9 +2401,9 @@ lflow_output_runtime_data_handler(struct
engine_node *node,
>      struct ed_type_lflow_output *fo = data;
>      init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
>
> -    struct tracked_binding_datapath *tdp;
> +    struct tracked_datapath *tdp;
>      HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) {
> -        if (tdp->is_new) {
> +        if (tdp->tracked_type == TRACKED_RESOURCE_NEW) {
>              if (!lflow_add_flows_for_datapath(tdp->dp, &l_ctx_in,
>                                                &l_ctx_out)) {
>                  return false;
> @@ -2433,7 +2411,7 @@ lflow_output_runtime_data_handler(struct
engine_node *node,
>          } else {
>              struct shash_node *shash_node;
>              SHASH_FOR_EACH (shash_node, &tdp->lports) {
> -                struct tracked_binding_lport *lport = shash_node->data;
> +                struct tracked_lport *lport = shash_node->data;
>                  if (!lflow_handle_flows_for_lport(lport->pb, &l_ctx_in,
>                                                    &l_ctx_out)) {
>                      return false;
> diff --git a/controller/ovn-controller.h b/controller/ovn-controller.h
> index b864ed0fa..578588305 100644
> --- a/controller/ovn-controller.h
> +++ b/controller/ovn-controller.h
> @@ -40,40 +40,6 @@ struct ct_zone_pending_entry {
>      enum ct_zone_pending_state state;
>  };
>
> -/* A logical datapath that has some relevance to this hypervisor.  A
logical
> - * datapath D is relevant to hypervisor H if:
> - *
> - *     - Some VIF or l2gateway or l3gateway port in D is located on H.
> - *
> - *     - D is reachable over a series of hops across patch ports,
starting from
> - *       a datapath relevant to H.
> - *
> - * The 'hmap_node''s hash value is 'datapath->tunnel_key'. */
> -struct local_datapath {
> -    struct hmap_node hmap_node;
> -    const struct sbrec_datapath_binding *datapath;
> -
> -    /* The localnet port in this datapath, if any (at most one is
allowed). */
> -    const struct sbrec_port_binding *localnet_port;
> -
> -    /* True if this datapath contains an l3gateway port located on this
> -     * hypervisor. */
> -    bool has_local_l3gateway;
> -
> -    struct {
> -        const struct sbrec_port_binding *local;
> -        const struct sbrec_port_binding *remote;
> -    } *peer_ports;
> -
> -    size_t n_peer_ports;
> -    size_t n_allocated_peer_ports;
> -
> -    struct shash external_ports;
> -};
> -
> -struct local_datapath *get_local_datapath(const struct hmap *,
> -                                          uint32_t tunnel_key);
> -
>  const struct ovsrec_bridge *get_bridge(const struct ovsrec_bridge_table
*,
>                                         const char *br_name);
>
> diff --git a/controller/patch.c b/controller/patch.c
> index e54b56354..99a095c57 100644
> --- a/controller/patch.c
> +++ b/controller/patch.c
> @@ -18,6 +18,7 @@
>  #include "patch.h"
>
>  #include "hash.h"
> +#include "ldata.h"
>  #include "lflow.h"
>  #include "lib/vswitch-idl.h"
>  #include "lport.h"
> diff --git a/controller/physical.c b/controller/physical.c
> index 483a5a49b..b244ff1c2 100644
> --- a/controller/physical.c
> +++ b/controller/physical.c
> @@ -20,6 +20,7 @@
>  #include "encaps.h"
>  #include "flow.h"
>  #include "ha-chassis.h"
> +#include "ldata.h"
>  #include "lflow.h"
>  #include "lport.h"
>  #include "chassis.h"
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 8e4c4d18c..e2d892aab 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -25,6 +25,7 @@
>  #include "encaps.h"
>  #include "flow.h"
>  #include "ha-chassis.h"
> +#include "ldata.h"
>  #include "lport.h"
>  #include "mac-learn.h"
>  #include "nx-match.h"
> --
> 2.31.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev


More information about the dev mailing list