On Thu, Jan 11, 2024 at 7:29 AM <num...@ovn.org> wrote:
>
> From: Numan Siddique <num...@ovn.org>
>
> This new engine now maintains the NAT related data for each
> logical router which was earlier maintained by the northd
> engine node in the 'struct ovn_datapath'.  The input to
> this engine node is 'northd'.
>
> A record for each logical router (lr_nat_record) is maintained
> in the 'lr_nats' hmap table which stores the lr's NAT dat.
>
> 'northd' engine now reports logical routers changed due to NATs
> in its tracking data.  'lr_nat' engine node makes use of
> this tracked data in its northd change handler to update the
> NAT data.
>
> This engine node becomes an input to 'lflow' node.
>
> Signed-off-by: Numan Siddique <num...@ovn.org>
> ---
>  lib/ovn-util.c           |   6 +-
>  lib/ovn-util.h           |   2 +-
>  lib/stopwatch-names.h    |   1 +
>  northd/automake.mk       |   2 +
>  northd/en-lflow.c        |   5 +
>  northd/en-lr-nat.c       | 423 ++++++++++++++++++++++++++++
>  northd/en-lr-nat.h       | 127 +++++++++
>  northd/en-northd.c       |   4 +
>  northd/en-sync-sb.c      |   6 +-
>  northd/inc-proc-northd.c |   6 +
>  northd/northd.c          | 589 ++++++++++++++++-----------------------
>  northd/northd.h          |  46 +--
>  northd/ovn-northd.c      |   1 +
>  tests/ovn-northd.at      |  46 ++-
>  14 files changed, 885 insertions(+), 379 deletions(-)
>  create mode 100644 northd/en-lr-nat.c
>  create mode 100644 northd/en-lr-nat.h
>
> diff --git a/lib/ovn-util.c b/lib/ovn-util.c
> index 6ef9cac7f2..c8b89cc216 100644
> --- a/lib/ovn-util.c
> +++ b/lib/ovn-util.c
> @@ -385,7 +385,7 @@ extract_sbrec_binding_first_mac(const struct
sbrec_port_binding *binding,
>  }
>
>  bool
> -lport_addresses_is_empty(struct lport_addresses *laddrs)
> +lport_addresses_is_empty(const struct lport_addresses *laddrs)
>  {
>      return !laddrs->n_ipv4_addrs && !laddrs->n_ipv6_addrs;
>  }
> @@ -395,6 +395,10 @@ destroy_lport_addresses(struct lport_addresses
*laddrs)
>  {
>      free(laddrs->ipv4_addrs);
>      free(laddrs->ipv6_addrs);
> +    laddrs->ipv4_addrs = NULL;
> +    laddrs->ipv6_addrs = NULL;
> +    laddrs->n_ipv4_addrs = 0;
> +    laddrs->n_ipv6_addrs = 0;
>  }
>
>  /* Returns a string of the IP address of 'laddrs' that overlaps with
'ip_s'.
> diff --git a/lib/ovn-util.h b/lib/ovn-util.h
> index aa0b3b2fb4..d245d57d56 100644
> --- a/lib/ovn-util.h
> +++ b/lib/ovn-util.h
> @@ -112,7 +112,7 @@ bool extract_sbrec_binding_first_mac(const struct
sbrec_port_binding *binding,
>  bool extract_lrp_networks__(char *mac, char **networks, size_t
n_networks,
>                              struct lport_addresses *laddrs);
>
> -bool lport_addresses_is_empty(struct lport_addresses *);
> +bool lport_addresses_is_empty(const struct lport_addresses *);
>  void destroy_lport_addresses(struct lport_addresses *);
>  const char *find_lport_address(const struct lport_addresses *laddrs,
>                                 const char *ip_s);
> diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h
> index 4e93c1dc14..782d64320a 100644
> --- a/lib/stopwatch-names.h
> +++ b/lib/stopwatch-names.h
> @@ -29,5 +29,6 @@
>  #define LFLOWS_TO_SB_STOPWATCH_NAME "lflows_to_sb"
>  #define PORT_GROUP_RUN_STOPWATCH_NAME "port_group_run"
>  #define SYNC_METERS_RUN_STOPWATCH_NAME "sync_meters_run"
> +#define LR_NAT_RUN_STOPWATCH_NAME "lr_nat_run"
>
>  #endif
> diff --git a/northd/automake.mk b/northd/automake.mk
> index 5d77ca67b7..a477105470 100644
> --- a/northd/automake.mk
> +++ b/northd/automake.mk
> @@ -24,6 +24,8 @@ northd_ovn_northd_SOURCES = \
>         northd/en-sync-from-sb.h \
>         northd/en-lb-data.c \
>         northd/en-lb-data.h \
> +       northd/en-lr-nat.c \
> +       northd/en-lr-nat.h \
>         northd/inc-proc-northd.c \
>         northd/inc-proc-northd.h \
>         northd/ipam.c \
> diff --git a/northd/en-lflow.c b/northd/en-lflow.c
> index 6ba26006e0..e4f875ef7c 100644
> --- a/northd/en-lflow.c
> +++ b/northd/en-lflow.c
> @@ -19,6 +19,7 @@
>  #include <stdio.h>
>
>  #include "en-lflow.h"
> +#include "en-lr-nat.h"
>  #include "en-northd.h"
>  #include "en-meters.h"
>
> @@ -40,6 +41,9 @@ lflow_get_input_data(struct engine_node *node,
>          engine_get_input_data("port_group", node);
>      struct sync_meters_data *sync_meters_data =
>          engine_get_input_data("sync_meters", node);
> +    struct ed_type_lr_nat_data *lr_nat_data =
> +        engine_get_input_data("lr_nat", node);
> +
>      lflow_input->nbrec_bfd_table =
>          EN_OVSDB_GET(engine_get_input("NB_bfd", node));
>      lflow_input->sbrec_bfd_table =
> @@ -61,6 +65,7 @@ lflow_get_input_data(struct engine_node *node,
>      lflow_input->ls_ports = &northd_data->ls_ports;
>      lflow_input->lr_ports = &northd_data->lr_ports;
>      lflow_input->ls_port_groups = &pg_data->ls_port_groups;
> +    lflow_input->lr_nats = &lr_nat_data->lr_nats;
>      lflow_input->meter_groups = &sync_meters_data->meter_groups;
>      lflow_input->lb_datapaths_map = &northd_data->lb_datapaths_map;
>      lflow_input->svc_monitor_map = &northd_data->svc_monitor_map;
> diff --git a/northd/en-lr-nat.c b/northd/en-lr-nat.c
> new file mode 100644
> index 0000000000..273c5be34b
> --- /dev/null
> +++ b/northd/en-lr-nat.c
> @@ -0,0 +1,423 @@
> +/*
> + * Copyright (c) 2023, 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>
> +
> +#include <getopt.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +/* OVS includes */
> +#include "include/openvswitch/hmap.h"
> +#include "openvswitch/util.h"
> +#include "openvswitch/vlog.h"
> +#include "stopwatch.h"
> +
> +/* OVN includes */
> +#include "en-lr-nat.h"
> +#include "lib/inc-proc-eng.h"
> +#include "lib/lb.h"
> +#include "lib/ovn-nb-idl.h"
> +#include "lib/ovn-sb-idl.h"
> +#include "lib/ovn-util.h"
> +#include "lib/stopwatch-names.h"
> +#include "northd.h"
> +
> +VLOG_DEFINE_THIS_MODULE(en_lr_nat);
> +
> +/* Static function declarations. */
> +static void lr_nat_table_init(struct lr_nat_table *);
> +static void lr_nat_table_clear(struct lr_nat_table *);
> +static void lr_nat_table_destroy(struct lr_nat_table *);
> +static void lr_nat_table_build(struct lr_nat_table *,
> +                               const struct ovn_datapaths *lr_datapaths);
> +static struct lr_nat_record *lr_nat_table_find_(const struct
lr_nat_table *,
> +                                         const struct
nbrec_logical_router *);
> +static struct lr_nat_record *lr_nat_table_find_by_index_(
> +    const struct lr_nat_table *, size_t od_index);
> +
> +static struct lr_nat_record *lr_nat_record_create(
> +    struct lr_nat_table *, const struct ovn_datapath *);
> +static void lr_nat_record_init(struct lr_nat_record *);
> +static void lr_nat_record_reinit(struct lr_nat_record *);
> +static void lr_nat_record_destroy(struct lr_nat_record *);
> +
> +static void lr_nat_entries_init(struct lr_nat_record *);
> +static void lr_nat_entries_destroy(struct lr_nat_record *);
> +static void lr_nat_external_ips_init(struct lr_nat_record *);
> +static void lr_nat_external_ips_destroy(struct lr_nat_record *);
> +static bool get_force_snat_ip(struct lr_nat_record *, const char
*key_type,
> +                              struct lport_addresses *);
> +
> +const struct lr_nat_record *
> +lr_nat_table_find_by_index(const struct lr_nat_table *table,
> +                           size_t od_index)
> +{
> +    return lr_nat_table_find_by_index_(table, od_index);
> +}
> +
> +/* 'lr_nat' engine node manages the NB logical router NAT data.
> + */
> +void *
> +en_lr_nat_init(struct engine_node *node OVS_UNUSED,
> +               struct engine_arg *arg OVS_UNUSED)
> +{
> +    struct ed_type_lr_nat_data *data = xzalloc(sizeof *data);
> +    lr_nat_table_init(&data->lr_nats);
> +    hmapx_init(&data->trk_data.crupdated);
> +    return data;
> +}
> +
> +void
> +en_lr_nat_cleanup(void *data_)
> +{
> +    struct ed_type_lr_nat_data *data = (struct ed_type_lr_nat_data *)
data_;
> +    lr_nat_table_destroy(&data->lr_nats);
> +    hmapx_destroy(&data->trk_data.crupdated);
> +}
> +
> +void
> +en_lr_nat_clear_tracked_data(void *data_)
> +{
> +    struct ed_type_lr_nat_data *data = (struct ed_type_lr_nat_data *)
data_;
> +    hmapx_clear(&data->trk_data.crupdated);
> +}
> +
> +void
> +en_lr_nat_run(struct engine_node *node, void *data_)
> +{
> +    struct northd_data *northd_data = engine_get_input_data("northd",
node);
> +    struct ed_type_lr_nat_data *data = data_;
> +
> +    stopwatch_start(LR_NAT_RUN_STOPWATCH_NAME, time_msec());
> +    lr_nat_table_clear(&data->lr_nats);
> +    lr_nat_table_build(&data->lr_nats, &northd_data->lr_datapaths);
> +
> +    stopwatch_stop(LR_NAT_RUN_STOPWATCH_NAME, time_msec());
> +    engine_set_node_state(node, EN_UPDATED);
> +}
> +
> +/* Handler functions. */
> +bool
> +lr_nat_northd_handler(struct engine_node *node, void *data_)
> +{
> +    struct northd_data *northd_data = engine_get_input_data("northd",
node);
> +    if (!northd_has_tracked_data(&northd_data->trk_data)) {
> +        return false;
> +    }
> +
> +    if (!northd_has_lr_nats_in_tracked_data(&northd_data->trk_data)) {
> +        return true;
> +    }
> +
> +    struct ed_type_lr_nat_data *data = data_;
> +    struct lr_nat_record *lrnat_rec;
> +    const struct ovn_datapath *od;
> +    struct hmapx_node *hmapx_node;
> +
> +    HMAPX_FOR_EACH (hmapx_node,
&northd_data->trk_data.lr_with_changed_nats) {
> +        od = hmapx_node->data;
> +        lrnat_rec = lr_nat_table_find_(&data->lr_nats, od->nbr);
> +        ovs_assert(lrnat_rec);
> +        lr_nat_record_reinit(lrnat_rec);
> +
> +        /* Add the lrnet rec to the tracking data. */
> +        hmapx_add(&data->trk_data.crupdated, lrnat_rec);
> +    }
> +
> +    if (lr_nat_has_tracked_data(&data->trk_data)) {
> +        engine_set_node_state(node, EN_UPDATED);
> +    }
> +
> +    return true;
> +}
> +
> +/* static functions. */
> +static void
> +lr_nat_table_init(struct lr_nat_table *table)
> +{
> +    *table = (struct lr_nat_table) {
> +        .entries = HMAP_INITIALIZER(&table->entries),
> +    };
> +}
> +
> +static void
> +lr_nat_table_clear(struct lr_nat_table *table)
> +{
> +    struct lr_nat_record *lrnat_rec;
> +    HMAP_FOR_EACH_POP (lrnat_rec, key_node, &table->entries) {
> +        lr_nat_record_destroy(lrnat_rec);
> +    }
> +
> +    free(table->array);
> +    table->array = NULL;
> +}
> +
> +static void
> +lr_nat_table_build(struct lr_nat_table *table,
> +                   const struct ovn_datapaths *lr_datapaths)
> +{
> +    table->array = xrealloc(table->array,
> +                            ods_size(lr_datapaths) * sizeof
*table->array);
> +
> +    const struct ovn_datapath *od;
> +    HMAP_FOR_EACH (od, key_node, &lr_datapaths->datapaths) {
> +        lr_nat_record_create(table, od);
> +    }
> +}
> +
> +static void
> +lr_nat_table_destroy(struct lr_nat_table *table)
> +{
> +    lr_nat_table_clear(table);
> +    hmap_destroy(&table->entries);
> +}
> +
> +struct lr_nat_record *
> +lr_nat_table_find_(const struct lr_nat_table *table,
> +                   const struct nbrec_logical_router *nbr)
> +{
> +    struct lr_nat_record *lrnat_rec;
> +
> +    HMAP_FOR_EACH_WITH_HASH (lrnat_rec, key_node,
> +                             uuid_hash(&nbr->header_.uuid),
&table->entries) {
> +        if (nbr == lrnat_rec->od->nbr) {
> +            return lrnat_rec;
> +        }
> +    }
> +    return NULL;
> +}
> +
> +
> +struct lr_nat_record *
> +lr_nat_table_find_by_index_(const struct lr_nat_table *table,
> +                            size_t od_index)
> +{
> +    ovs_assert(od_index <= hmap_count(&table->entries));
> +
> +    return table->array[od_index];
> +}
> +
> +static struct lr_nat_record *
> +lr_nat_record_create(struct lr_nat_table *table,
> +                     const struct ovn_datapath *od)
> +{
> +    ovs_assert(od->nbr);
> +
> +    struct lr_nat_record *lrnat_rec = xzalloc(sizeof *lrnat_rec);
> +    lrnat_rec->od = od;
> +    lr_nat_record_init(lrnat_rec);
> +
> +    hmap_insert(&table->entries, &lrnat_rec->key_node,
> +                uuid_hash(&od->nbr->header_.uuid));
> +    table->array[od->index] = lrnat_rec;
> +    return lrnat_rec;
> +}
> +
> +static void
> +lr_nat_record_init(struct lr_nat_record *lrnat_rec)
> +{
> +    lr_nat_entries_init(lrnat_rec);
> +    lr_nat_external_ips_init(lrnat_rec);
> +}
> +
> +static void
> +lr_nat_record_reinit(struct lr_nat_record *lrnat_rec)
> +{
> +    lr_nat_entries_destroy(lrnat_rec);
> +    lr_nat_external_ips_destroy(lrnat_rec);
> +    lr_nat_record_init(lrnat_rec);
> +}
> +
> +static void
> +lr_nat_record_destroy(struct lr_nat_record *lrnat_rec)
> +{
> +    lr_nat_entries_destroy(lrnat_rec);
> +    lr_nat_external_ips_destroy(lrnat_rec);
> +    free(lrnat_rec);
> +}
> +
> +static void
> +lr_nat_external_ips_init(struct lr_nat_record *lrnat_rec)
> +{
> +    sset_init(&lrnat_rec->external_ips);
> +    for (size_t i = 0; i < lrnat_rec->od->nbr->n_nat; i++) {
> +        sset_add(&lrnat_rec->external_ips,
> +                 lrnat_rec->od->nbr->nat[i]->external_ip);
> +    }
> +}
> +
> +static void
> +lr_nat_external_ips_destroy(struct lr_nat_record *lrnat_rec)
> +{
> +    sset_destroy(&lrnat_rec->external_ips);
> +}
> +
> +static void
> +snat_ip_add(struct lr_nat_record *lrnat_rec, const char *ip,
> +            struct ovn_nat *nat_entry)
> +{
> +    struct ovn_snat_ip *snat_ip = shash_find_data(&lrnat_rec->snat_ips,
ip);
> +
> +    if (!snat_ip) {
> +        snat_ip = xzalloc(sizeof *snat_ip);
> +        ovs_list_init(&snat_ip->snat_entries);
> +        shash_add(&lrnat_rec->snat_ips, ip, snat_ip);
> +    }
> +
> +    if (nat_entry) {
> +        ovs_list_push_back(&snat_ip->snat_entries,
> +                           &nat_entry->ext_addr_list_node);
> +    }
> +}
> +
> +static void
> +lr_nat_entries_init(struct lr_nat_record *lrnat_rec)
> +{
> +    shash_init(&lrnat_rec->snat_ips);
> +    sset_init(&lrnat_rec->external_macs);
> +    lrnat_rec->has_distributed_nat = false;
> +
> +    if (get_force_snat_ip(lrnat_rec, "dnat",
> +                          &lrnat_rec->dnat_force_snat_addrs)) {
> +        if (lrnat_rec->dnat_force_snat_addrs.n_ipv4_addrs) {
> +            snat_ip_add(lrnat_rec,
> +
 lrnat_rec->dnat_force_snat_addrs.ipv4_addrs[0].addr_s,
> +                        NULL);
> +        }
> +        if (lrnat_rec->dnat_force_snat_addrs.n_ipv6_addrs) {
> +            snat_ip_add(lrnat_rec,
> +
 lrnat_rec->dnat_force_snat_addrs.ipv6_addrs[0].addr_s,
> +                        NULL);
> +        }
> +    }
> +
> +    /* Check if 'lb_force_snat_ip' is configured with 'router_ip'. */
> +    const char *lb_force_snat =
> +        smap_get(&lrnat_rec->od->nbr->options, "lb_force_snat_ip");
> +    if (lb_force_snat && !strcmp(lb_force_snat, "router_ip")
> +            && smap_get(&lrnat_rec->od->nbr->options, "chassis")) {
> +
> +        /* Set it to true only if its gateway router and
> +         * options:lb_force_snat_ip=router_ip. */
> +        lrnat_rec->lb_force_snat_router_ip = true;
> +    } else {
> +        lrnat_rec->lb_force_snat_router_ip = false;
> +
> +        /* Check if 'lb_force_snat_ip' is configured with a set of
> +         * IP address(es). */
> +        if (get_force_snat_ip(lrnat_rec, "lb",
> +                              &lrnat_rec->lb_force_snat_addrs)) {
> +            if (lrnat_rec->lb_force_snat_addrs.n_ipv4_addrs) {
> +                snat_ip_add(lrnat_rec,
> +
 lrnat_rec->lb_force_snat_addrs.ipv4_addrs[0].addr_s,
> +                        NULL);
> +            }
> +            if (lrnat_rec->lb_force_snat_addrs.n_ipv6_addrs) {
> +                snat_ip_add(lrnat_rec,
> +
 lrnat_rec->lb_force_snat_addrs.ipv6_addrs[0].addr_s,
> +                        NULL);
> +            }
> +        }
> +    }
> +
> +    if (!lrnat_rec->od->nbr->n_nat) {
> +        return;
> +    }
> +
> +    lrnat_rec->nat_entries =
> +        xmalloc(lrnat_rec->od->nbr->n_nat * sizeof
*lrnat_rec->nat_entries);
> +
> +    for (size_t i = 0; i < lrnat_rec->od->nbr->n_nat; i++) {
> +        const struct nbrec_nat *nat = lrnat_rec->od->nbr->nat[i];
> +        struct ovn_nat *nat_entry = &lrnat_rec->nat_entries[i];
> +
> +        nat_entry->nb = nat;
> +        if (!extract_ip_addresses(nat->external_ip,
> +                                  &nat_entry->ext_addrs) ||
> +                !nat_entry_is_valid(nat_entry)) {
> +            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5,
1);
> +
> +            VLOG_WARN_RL(&rl,
> +                         "Bad ip address %s in nat configuration "
> +                         "for router %s", nat->external_ip,
> +                         lrnat_rec->od->nbr->name);
> +            continue;
> +        }
> +
> +        /* If this is a SNAT rule add the IP to the set of unique SNAT
IPs. */
> +        if (!strcmp(nat->type, "snat")) {
> +            if (!nat_entry_is_v6(nat_entry)) {
> +                snat_ip_add(lrnat_rec,
> +                            nat_entry->ext_addrs.ipv4_addrs[0].addr_s,
> +                            nat_entry);
> +            } else {
> +                snat_ip_add(lrnat_rec,
> +                            nat_entry->ext_addrs.ipv6_addrs[0].addr_s,
> +                            nat_entry);
> +            }
> +        } else {
> +            if (!strcmp(nat->type, "dnat_and_snat")
> +                    && nat->logical_port && nat->external_mac) {
> +                lrnat_rec->has_distributed_nat = true;
> +            }
> +
> +            if (nat->external_mac) {
> +                sset_add(&lrnat_rec->external_macs, nat->external_mac);
> +            }
> +        }
> +    }
> +    lrnat_rec->n_nat_entries = lrnat_rec->od->nbr->n_nat;
> +}
> +
> +static bool
> +get_force_snat_ip(struct lr_nat_record *lrnat_rec, const char *key_type,
> +                  struct lport_addresses *laddrs)
> +{
> +    char *key = xasprintf("%s_force_snat_ip", key_type);
> +    const char *addresses = smap_get(&lrnat_rec->od->nbr->options, key);
> +    free(key);
> +
> +    if (!addresses) {
> +        return false;
> +    }
> +
> +    if (!extract_ip_address(addresses, laddrs)) {
> +        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> +        VLOG_WARN_RL(&rl, "bad ip %s in options of router "UUID_FMT"",
> +                     addresses,
UUID_ARGS(&lrnat_rec->od->nbr->header_.uuid));
> +        return false;
> +    }
> +
> +    return true;
> +}
> +
> +static void
> +lr_nat_entries_destroy(struct lr_nat_record *lrnat_rec)
> +{
> +    shash_destroy_free_data(&lrnat_rec->snat_ips);
> +    destroy_lport_addresses(&lrnat_rec->dnat_force_snat_addrs);
> +    destroy_lport_addresses(&lrnat_rec->lb_force_snat_addrs);
> +
> +    for (size_t i = 0; i < lrnat_rec->n_nat_entries; i++) {
> +        destroy_lport_addresses(&lrnat_rec->nat_entries[i].ext_addrs);
> +    }
> +
> +    free(lrnat_rec->nat_entries);
> +    lrnat_rec->nat_entries = NULL;
> +    lrnat_rec->n_nat_entries = 0;
> +    sset_destroy(&lrnat_rec->external_macs);
> +}
> diff --git a/northd/en-lr-nat.h b/northd/en-lr-nat.h
> new file mode 100644
> index 0000000000..3ec4c7b506
> --- /dev/null
> +++ b/northd/en-lr-nat.h
> @@ -0,0 +1,127 @@
> +/*
> + * Copyright (c) 2023, 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 EN_LR_NAT_H
> +#define EN_LR_NAT_H 1
> +
> +#include <stdint.h>
> +
> +/* OVS includes. */
> +#include "lib/hmapx.h"
> +#include "openvswitch/hmap.h"
> +#include "sset.h"
> +
> +/* OVN includes. */
> +#include "lib/inc-proc-eng.h"
> +#include "lib/ovn-nb-idl.h"
> +#include "lib/ovn-sb-idl.h"
> +#include "lib/ovn-util.h"
> +
> +/* Contains a NAT entry with the external addresses pre-parsed. */
> +struct ovn_nat {
> +    const struct nbrec_nat *nb;
> +    struct lport_addresses ext_addrs;
> +    struct ovs_list ext_addr_list_node; /* Linkage in the per-external IP
> +                                         * list of nat entries. Currently
> +                                         * only used for SNAT.
> +                                         */
> +};
> +
> +/* Stores the list of SNAT entries referencing a unique SNAT IP address.
> + * The 'snat_entries' list will be empty if the SNAT IP is used only for
> + * dnat_force_snat_ip or lb_force_snat_ip.
> + */
> +struct ovn_snat_ip {
> +    struct ovs_list snat_entries;
> +};
> +
> +struct lr_nat_record {
> +    struct hmap_node key_node;  /* Index on 'nbr->header_.uuid'. */
> +
> +    const struct ovn_datapath *od;

Hi Numan, I still think storing this kind of reference directly to objects
belonging to the input node is very risky. It can easily create implicit
dependency. With such implicit dependency, we will need to very carefully
examine how the "od" is used by engine nodes that depend on the lr_nat
node. Please see an example of a potential problem I pointed out in the
next patch's comments.

Thanks,
Han
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to