@@ -33,5 +33,6 @@
#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"
+#define LR_LB_NAT_DATA_RUN_STOPWATCH_NAME "lr_lb_nat_data"
#endif
@@ -26,6 +26,8 @@ northd_ovn_northd_SOURCES = \
northd/en-lb-data.h \
northd/en-lr-nat.c \
northd/en-lr-nat.h \
+ northd/en-lr-lb-nat-data.c \
+ northd/en-lr-lb-nat-data.h \
northd/inc-proc-northd.c \
northd/inc-proc-northd.h \
northd/ipam.c \
@@ -20,6 +20,7 @@
#include "en-lflow.h"
#include "en-lr-nat.h"
+#include "en-lr-lb-nat-data.h"
#include "en-northd.h"
#include "en-meters.h"
@@ -43,6 +44,8 @@ lflow_get_input_data(struct engine_node *node,
engine_get_input_data("sync_meters", node);
struct ed_type_lr_nat_data *lr_nat_data =
engine_get_input_data("lr_nat", node);
+ struct ed_type_lr_lb_nat_data *lr_lb_nat_data =
+ engine_get_input_data("lr_lb_nat_data", node);
lflow_input->nbrec_bfd_table =
EN_OVSDB_GET(engine_get_input("NB_bfd", node));
@@ -66,6 +69,7 @@ lflow_get_input_data(struct engine_node *node,
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->lr_lbnats = &lr_lb_nat_data->lr_lbnats;
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;
new file mode 100644
@@ -0,0 +1,635 @@
+/*
+ * 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 "lib/bitmap.h"
+#include "lib/socket-util.h"
+#include "lib/uuidset.h"
+#include "openvswitch/util.h"
+#include "openvswitch/vlog.h"
+#include "stopwatch.h"
+
+/* OVN includes */
+#include "en-lb-data.h"
+#include "en-lr-lb-nat-data.h"
+#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_lb_nat_data);
+
+/* Static function declarations. */
+static void lr_lb_nat_data_table_init(struct lr_lb_nat_data_table *);
+static void lr_lb_nat_data_table_clear(struct lr_lb_nat_data_table *);
+static void lr_lb_nat_data_table_destroy(struct lr_lb_nat_data_table *);
+static struct lr_lb_nat_data_record *lr_lb_nat_data_table_find_(
+ const struct lr_lb_nat_data_table *, const struct nbrec_logical_router *);
+static void lr_lb_nat_data_table_build(struct lr_lb_nat_data_table *,
+ const struct lr_nat_table *,
+ const struct hmap *lb_datapaths_map,
+ const struct hmap *lbgrp_datapaths_map);
+
+static struct lr_lb_nat_data_input lr_lb_nat_data_get_input_data(
+ struct engine_node *);
+
+static struct lr_lb_nat_data_record *lr_lb_nat_data_record_create(
+ struct lr_lb_nat_data_table *, const struct lr_nat_record *,
+ const struct hmap *lb_datapaths_map,
+ const struct hmap *lbgrp_datapaths_map);
+static void lr_lb_nat_data_record_destroy(struct lr_lb_nat_data_record *);
+static void lr_lb_nat_data_record_init(
+ struct lr_lb_nat_data_record *,
+ const struct hmap *lb_datapaths_map,
+ const struct hmap *lbgrp_datapaths_map);
+
+static void build_lrouter_lb_reachable_ips(struct lr_lb_nat_data_record *,
+ const struct ovn_northd_lb *);
+static void add_neigh_ips_to_lrouter(struct lr_lb_nat_data_record *,
+ enum lb_neighbor_responder_mode,
+ const struct sset *lb_ips_v4,
+ const struct sset *lb_ips_v6);
+static void remove_lrouter_lb_reachable_ips(struct lr_lb_nat_data_record *,
+ enum lb_neighbor_responder_mode,
+ const struct sset *lb_ips_v4,
+ const struct sset *lb_ips_v6);
+static void lr_lb_nat_data_build_vip_nats(struct lr_lb_nat_data_record *);
+
+const struct lr_lb_nat_data_record *
+lr_lb_nat_data_table_find(
+ const struct lr_lb_nat_data_table *table,
+ const struct nbrec_logical_router *nbr)
+{
+ return lr_lb_nat_data_table_find_(table, nbr);
+}
+
+/* 'lr_lb_nat_data' engine node manages the NB logical router LB data.
+ */
+void *
+en_lr_lb_nat_data_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+ struct ed_type_lr_lb_nat_data *data = xzalloc(sizeof *data);
+ lr_lb_nat_data_table_init(&data->lr_lbnats);
+ hmapx_init(&data->tracked_data.crupdated);
+ hmapx_init(&data->tracked_data.deleted);
+ return data;
+}
+
+void
+en_lr_lb_nat_data_cleanup(void *data_)
+{
+ struct ed_type_lr_lb_nat_data *data =
+ (struct ed_type_lr_lb_nat_data *) data_;
+ lr_lb_nat_data_table_destroy(&data->lr_lbnats);
+ hmapx_destroy(&data->tracked_data.crupdated);
+ hmapx_destroy(&data->tracked_data.deleted);
+}
+
+void
+en_lr_lb_nat_data_clear_tracked_data(void *data_)
+{
+ struct ed_type_lr_lb_nat_data *data =
+ (struct ed_type_lr_lb_nat_data *) data_;
+
+ struct hmapx_node *hmapx_node;
+ HMAPX_FOR_EACH_SAFE (hmapx_node, &data->tracked_data.deleted) {
+ lr_lb_nat_data_record_destroy(hmapx_node->data);
+ hmapx_delete(&data->tracked_data.deleted, hmapx_node);
+ }
+
+ hmapx_clear(&data->tracked_data.crupdated);
+ data->tracked = false;
+}
+
+void
+en_lr_lb_nat_data_run(struct engine_node *node, void *data_)
+{
+ struct lr_lb_nat_data_input input_data =
+ lr_lb_nat_data_get_input_data(node);
+ struct ed_type_lr_lb_nat_data *data = data_;
+
+ stopwatch_start(LR_LB_NAT_DATA_RUN_STOPWATCH_NAME, time_msec());
+
+ lr_lb_nat_data_table_clear(&data->lr_lbnats);
+ lr_lb_nat_data_table_build(&data->lr_lbnats, input_data.lr_nats,
+ input_data.lb_datapaths_map,
+ input_data.lbgrp_datapaths_map);
+
+ stopwatch_stop(LR_LB_NAT_DATA_RUN_STOPWATCH_NAME, time_msec());
+ engine_set_node_state(node, EN_UPDATED);
+}
+
+bool
+lr_lb_nat_data_northd_handler(struct engine_node *node, void *data OVS_UNUSED)
+{
+ struct northd_data *northd_data = engine_get_input_data("northd", node);
+ if (!northd_data->change_tracked) {
+ return false;
+ }
+
+ return true;
+}
+
+bool
+lr_lb_nat_data_lb_data_handler(struct engine_node *node, void *data_)
+{
+ struct ed_type_lb_data *lb_data = engine_get_input_data("lb_data", node);
+ if (!lb_data->tracked) {
+ return false;
+ }
+
+ struct ed_type_lr_lb_nat_data *data =
+ (struct ed_type_lr_lb_nat_data *) data_;
+ struct lr_lb_nat_data_input input_data =
+ lr_lb_nat_data_get_input_data(node);
+ struct lr_lb_nat_data_record *lr_lbnat_rec;
+ size_t index;
+
+ const struct tracked_lb_data *trk_lb_data = &lb_data->tracked_lb_data;
+ const struct ovn_lb_group_datapaths *lbgrp_dps;
+ const struct crupdated_lbgrp *crupdated_lbgrp;
+ const struct crupdated_od_lb_data *codlb;
+ const struct ovn_lb_datapaths *lb_dps;
+ const struct crupdated_lb *clb;
+ const struct ovn_northd_lb *lb;
+ const struct ovn_datapath *od;
+
+ LIST_FOR_EACH (codlb, list_node, &trk_lb_data->crupdated_lr_lbs) {
+ od = ovn_datapath_find(&input_data.lr_datapaths->datapaths,
+ &codlb->od_uuid);
+ ovs_assert(od);
+
+ lr_lbnat_rec = lr_lb_nat_data_table_find_(&data->lr_lbnats, od->nbr);
+ if (!lr_lbnat_rec) {
+ const struct lr_nat_record *lrnat_rec = lr_nat_table_find(
+ input_data.lr_nats, od->nbr);
+ ovs_assert(lrnat_rec);
+
+ lr_lbnat_rec = lr_lb_nat_data_record_create(&data->lr_lbnats,
+ lrnat_rec,
+ input_data.lb_datapaths_map,
+ input_data.lbgrp_datapaths_map);
+
+ /* Add the lr_lbnat_rec rec to the tracking data. */
+ hmapx_add(&data->tracked_data.crupdated, lr_lbnat_rec);
+ continue;
+ }
+
+ struct uuidset_node *uuidnode;
+ UUIDSET_FOR_EACH (uuidnode, &codlb->assoc_lbs) {
+ lb_dps = ovn_lb_datapaths_find(
+ input_data.lb_datapaths_map, &uuidnode->uuid);
+ ovs_assert(lb_dps);
+
+ /* Add the lb_ips of lb_dps to the od. */
+ build_lrouter_lb_ips(lr_lbnat_rec->lb_ips, lb_dps->lb);
+ build_lrouter_lb_reachable_ips(lr_lbnat_rec, lb_dps->lb);
+ }
+
+ UUIDSET_FOR_EACH (uuidnode, &codlb->assoc_lbgrps) {
+ lbgrp_dps = ovn_lb_group_datapaths_find(
+ input_data.lbgrp_datapaths_map, &uuidnode->uuid);
+ ovs_assert(lbgrp_dps);
+
+ for (size_t j = 0; j < lbgrp_dps->lb_group->n_lbs; j++) {
+ const struct uuid *lb_uuid
+ = &lbgrp_dps->lb_group->lbs[j]->nlb->header_.uuid;
+ lb_dps = ovn_lb_datapaths_find(input_data.lb_datapaths_map,
+ lb_uuid);
+ ovs_assert(lb_dps);
+
+ /* Add the lb_ips of lb_dps to the od. */
+ build_lrouter_lb_ips(lr_lbnat_rec->lb_ips, lb_dps->lb);
+ build_lrouter_lb_reachable_ips(lr_lbnat_rec, lb_dps->lb);
+ }
+ }
+
+ /* Add the lr_lbnat_rec rec to the tracking data. */
+ hmapx_add(&data->tracked_data.crupdated, lr_lbnat_rec);
+ }
+
+ HMAP_FOR_EACH (clb, hmap_node, &trk_lb_data->crupdated_lbs) {
+ lb = clb->lb;
+ const struct uuid *lb_uuid = &lb->nlb->header_.uuid;
+
+ lb_dps = ovn_lb_datapaths_find(input_data.lb_datapaths_map, lb_uuid);
+ ovs_assert(lb_dps);
+
+ BITMAP_FOR_EACH_1 (index, ods_size(input_data.lr_datapaths),
+ lb_dps->nb_lr_map) {
+ od = input_data.lr_datapaths->array[index];
+
+ lr_lbnat_rec = lr_lb_nat_data_table_find_(&data->lr_lbnats,
+ od->nbr);
+ ovs_assert(lr_lbnat_rec);
+
+ /* Update the od->lb_ips with the deleted and inserted
+ * vips (if any). */
+ remove_ips_from_lb_ip_set(lr_lbnat_rec->lb_ips, lb->routable,
+ &clb->deleted_vips_v4,
+ &clb->deleted_vips_v6);
+ add_ips_to_lb_ip_set(lr_lbnat_rec->lb_ips, lb->routable,
+ &clb->inserted_vips_v4,
+ &clb->inserted_vips_v6);
+
+ remove_lrouter_lb_reachable_ips(lr_lbnat_rec, lb->neigh_mode,
+ &clb->deleted_vips_v4,
+ &clb->deleted_vips_v6);
+ add_neigh_ips_to_lrouter(lr_lbnat_rec, lb->neigh_mode,
+ &clb->inserted_vips_v4,
+ &clb->inserted_vips_v6);
+
+ /* Add the lr_lbnat_rec rec to the tracking data. */
+ hmapx_add(&data->tracked_data.crupdated, lr_lbnat_rec);
+ }
+ }
+
+ HMAP_FOR_EACH (crupdated_lbgrp, hmap_node,
+ &trk_lb_data->crupdated_lbgrps) {
+ const struct uuid *lb_uuid = &crupdated_lbgrp->lbgrp->uuid;
+
+ lbgrp_dps = ovn_lb_group_datapaths_find(input_data.lbgrp_datapaths_map,
+ lb_uuid);
+ ovs_assert(lbgrp_dps);
+
+ struct hmapx_node *hnode;
+ HMAPX_FOR_EACH (hnode, &crupdated_lbgrp->assoc_lbs) {
+ lb = hnode->data;
+ lb_uuid = &lb->nlb->header_.uuid;
+ lb_dps = ovn_lb_datapaths_find(input_data.lb_datapaths_map,
+ lb_uuid);
+ ovs_assert(lb_dps);
+ for (size_t i = 0; i < lbgrp_dps->n_lr; i++) {
+ od = lbgrp_dps->lr[i];
+ lr_lbnat_rec = lr_lb_nat_data_table_find_(&data->lr_lbnats,
+ od->nbr);
+ ovs_assert(lr_lbnat_rec);
+ /* Add the lb_ips of lb_dps to the lr lb data. */
+ build_lrouter_lb_ips(lr_lbnat_rec->lb_ips, lb_dps->lb);
+ build_lrouter_lb_reachable_ips(lr_lbnat_rec, lb_dps->lb);
+
+ /* Add the lr_lbnat_rec rec to the tracking data. */
+ hmapx_add(&data->tracked_data.crupdated, lr_lbnat_rec);
+ }
+ }
+ }
+
+ if (!hmapx_is_empty(&data->tracked_data.crupdated)) {
+ struct hmapx_node *hmapx_node;
+ /* For all the modified lr_lb_nat_data records (re)build the
+ * vip nats. */
+ HMAPX_FOR_EACH (hmapx_node, &data->tracked_data.crupdated) {
+ lr_lb_nat_data_build_vip_nats(hmapx_node->data);
+ }
+
+ data->tracked = true;
+ engine_set_node_state(node, EN_UPDATED);
+ }
+
+ return true;
+}
+
+bool
+lr_lb_nat_data_lr_nat_handler(struct engine_node *node, void *data_)
+{
+ struct ed_type_lr_nat_data *lr_nat_data =
+ engine_get_input_data("lr_nat", node);
+
+ if (!lr_nat_data->tracked
+ || !hmapx_is_empty(&lr_nat_data->tracked_data.deleted)) {
+ return false;
+ }
+
+ struct ed_type_lr_lb_nat_data *data =
+ (struct ed_type_lr_lb_nat_data *) data_;
+ struct lr_lb_nat_data_input input_data =
+ lr_lb_nat_data_get_input_data(node);
+ const struct lr_nat_record *lrnat_rec;
+ struct lr_lb_nat_data_record *lr_lbnat_rec;
+ struct hmapx_node *hmapx_node;
+
+ HMAPX_FOR_EACH (hmapx_node, &lr_nat_data->tracked_data.crupdated) {
+ lrnat_rec = hmapx_node->data;
+ lr_lbnat_rec = lr_lb_nat_data_table_find_(&data->lr_lbnats,
+ lrnat_rec->od->nbr);
+ if (!lr_lbnat_rec) {
+ lr_lbnat_rec = lr_lb_nat_data_record_create(&data->lr_lbnats,
+ lrnat_rec,
+ input_data.lb_datapaths_map,
+ input_data.lbgrp_datapaths_map);
+ } else {
+ lr_lb_nat_data_build_vip_nats(lr_lbnat_rec);
+ }
+
+ /* Add the lr_lbnat_rec rec to the tracking data. */
+ hmapx_add(&data->tracked_data.crupdated, lr_lbnat_rec);
+ }
+
+ if (!hmapx_is_empty(&data->tracked_data.crupdated)) {
+ data->tracked = true;
+ engine_set_node_state(node, EN_UPDATED);
+ }
+
+ return true;
+}
+
+/* static functions. */
+static void
+lr_lb_nat_data_table_init(struct lr_lb_nat_data_table *table)
+{
+ *table = (struct lr_lb_nat_data_table) {
+ .entries = HMAP_INITIALIZER(&table->entries),
+ };
+}
+
+static void
+lr_lb_nat_data_table_destroy(struct lr_lb_nat_data_table *table)
+{
+ lr_lb_nat_data_table_clear(table);
+ hmap_destroy(&table->entries);
+}
+
+static void
+lr_lb_nat_data_table_clear(struct lr_lb_nat_data_table *table)
+{
+ struct lr_lb_nat_data_record *lr_lbnat_rec;
+ HMAP_FOR_EACH_POP (lr_lbnat_rec, key_node, &table->entries) {
+ lr_lb_nat_data_record_destroy(lr_lbnat_rec);
+ }
+}
+
+static void
+lr_lb_nat_data_table_build(struct lr_lb_nat_data_table *table,
+ const struct lr_nat_table *lr_nats,
+ const struct hmap *lb_datapaths_map,
+ const struct hmap *lbgrp_datapaths_map)
+{
+ const struct lr_nat_record *lrnat_rec;
+ LR_NAT_TABLE_FOR_EACH (lrnat_rec, lr_nats) {
+ lr_lb_nat_data_record_create(table, lrnat_rec, lb_datapaths_map,
+ lbgrp_datapaths_map);
+ }
+}
+
+static struct lr_lb_nat_data_record *
+lr_lb_nat_data_table_find_(const struct lr_lb_nat_data_table *table,
+ const struct nbrec_logical_router *nbr)
+{
+ struct lr_lb_nat_data_record *lr_lbnat_rec;
+
+ HMAP_FOR_EACH_WITH_HASH (lr_lbnat_rec, key_node,
+ uuid_hash(&nbr->header_.uuid), &table->entries) {
+ if (nbr == lr_lbnat_rec->od->nbr) {
+ return lr_lbnat_rec;
+ }
+ }
+ return NULL;
+}
+
+static struct lr_lb_nat_data_record *
+lr_lb_nat_data_record_create(struct lr_lb_nat_data_table *table,
+ const struct lr_nat_record *lrnat_rec,
+ const struct hmap *lb_datapaths_map,
+ const struct hmap *lbgrp_datapaths_map)
+{
+ struct lr_lb_nat_data_record *lr_lbnat_rec = xzalloc(sizeof *lr_lbnat_rec);
+ lr_lbnat_rec->lrnat_rec = lrnat_rec;
+ lr_lbnat_rec->od = lrnat_rec->od;
+ lr_lb_nat_data_record_init(lr_lbnat_rec, lb_datapaths_map,
+ lbgrp_datapaths_map);
+
+ hmap_insert(&table->entries, &lr_lbnat_rec->key_node,
+ uuid_hash(&lr_lbnat_rec->od->nbr->header_.uuid));
+
+ return lr_lbnat_rec;
+}
+
+static void
+lr_lb_nat_data_record_destroy(struct lr_lb_nat_data_record *lr_lbnat_rec)
+{
+ ovn_lb_ip_set_destroy(lr_lbnat_rec->lb_ips);
+ lr_lbnat_rec->lb_ips = NULL;
+ sset_destroy(&lr_lbnat_rec->vip_nats);
+ free(lr_lbnat_rec);
+}
+
+static void
+lr_lb_nat_data_record_init(struct lr_lb_nat_data_record *lr_lbnat_rec,
+ const struct hmap *lb_datapaths_map,
+ const struct hmap *lbgrp_datapaths_map)
+{
+ const struct nbrec_load_balancer_group *nbrec_lb_group;
+ const struct ovn_lb_group_datapaths *lb_group_dps;
+ const struct ovn_lb_datapaths *lb_dps;
+
+ /* Checking load balancer groups first, starting from the largest one,
+ * to more efficiently copy IP sets. */
+ size_t largest_group = 0;
+
+ const struct nbrec_logical_router *nbr = lr_lbnat_rec->od->nbr;
+ for (size_t i = 1; i < nbr->n_load_balancer_group; i++) {
+ if (nbr->load_balancer_group[i]->n_load_balancer >
+ nbr->load_balancer_group[largest_group]->n_load_balancer) {
+ largest_group = i;
+ }
+ }
+
+ for (size_t i = 0; i < nbr->n_load_balancer_group; i++) {
+ size_t idx = (i + largest_group) % nbr->n_load_balancer_group;
+
+ nbrec_lb_group = nbr->load_balancer_group[idx];
+ const struct uuid *lbgrp_uuid = &nbrec_lb_group->header_.uuid;
+
+ lb_group_dps =
+ ovn_lb_group_datapaths_find(lbgrp_datapaths_map,
+ lbgrp_uuid);
+ ovs_assert(lb_group_dps);
+
+ if (!lr_lbnat_rec->lb_ips) {
+ lr_lbnat_rec->lb_ips =
+ ovn_lb_ip_set_clone(lb_group_dps->lb_group->lb_ips);
+ } else {
+ for (size_t j = 0; j < lb_group_dps->lb_group->n_lbs; j++) {
+ build_lrouter_lb_ips(lr_lbnat_rec->lb_ips,
+ lb_group_dps->lb_group->lbs[j]);
+ }
+ }
+
+ for (size_t j = 0; j < lb_group_dps->lb_group->n_lbs; j++) {
+ build_lrouter_lb_reachable_ips(lr_lbnat_rec,
+ lb_group_dps->lb_group->lbs[j]);
+ }
+ }
+
+ if (!lr_lbnat_rec->lb_ips) {
+ lr_lbnat_rec->lb_ips = ovn_lb_ip_set_create();
+ }
+
+ for (size_t i = 0; i < nbr->n_load_balancer; i++) {
+ const struct uuid *lb_uuid =
+ &nbr->load_balancer[i]->header_.uuid;
+ lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid);
+ ovs_assert(lb_dps);
+ build_lrouter_lb_ips(lr_lbnat_rec->lb_ips, lb_dps->lb);
+ build_lrouter_lb_reachable_ips(lr_lbnat_rec, lb_dps->lb);
+ }
+
+ sset_init(&lr_lbnat_rec->vip_nats);
+
+ if (!nbr->n_nat) {
+ lr_lb_nat_data_build_vip_nats(lr_lbnat_rec);
+ }
+}
+
+static struct lr_lb_nat_data_input
+lr_lb_nat_data_get_input_data(struct engine_node *node)
+{
+ struct northd_data *northd_data = engine_get_input_data("northd", node);
+ struct ed_type_lr_nat_data *lr_nat_data =
+ engine_get_input_data("lr_nat", node);
+
+ return (struct lr_lb_nat_data_input) {
+ .lr_datapaths = &northd_data->lr_datapaths,
+ .lb_datapaths_map = &northd_data->lb_datapaths_map,
+ .lbgrp_datapaths_map = &northd_data->lb_group_datapaths_map,
+ .lr_nats = &lr_nat_data->lr_nats,
+ };
+}
+
+static void
+build_lrouter_lb_reachable_ips(struct lr_lb_nat_data_record *lr_lbnat_rec,
+ const struct ovn_northd_lb *lb)
+{
+ add_neigh_ips_to_lrouter(lr_lbnat_rec, lb->neigh_mode, &lb->ips_v4,
+ &lb->ips_v6);
+}
+
+static void
+add_neigh_ips_to_lrouter(struct lr_lb_nat_data_record *lr_lbnat_rec,
+ enum lb_neighbor_responder_mode neigh_mode,
+ const struct sset *lb_ips_v4,
+ const struct sset *lb_ips_v6)
+{
+ /* If configured to not reply to any neighbor requests for all VIPs
+ * return early.
+ */
+ if (neigh_mode == LB_NEIGH_RESPOND_NONE) {
+ return;
+ }
+
+ const char *ip_address;
+
+ /* If configured to reply to neighbor requests for all VIPs force them
+ * all to be considered "reachable".
+ */
+ if (neigh_mode == LB_NEIGH_RESPOND_ALL) {
+ SSET_FOR_EACH (ip_address, lb_ips_v4) {
+ sset_add(&lr_lbnat_rec->lb_ips->ips_v4_reachable, ip_address);
+ }
+ SSET_FOR_EACH (ip_address, lb_ips_v6) {
+ sset_add(&lr_lbnat_rec->lb_ips->ips_v6_reachable, ip_address);
+ }
+
+ return;
+ }
+
+ /* Otherwise, a VIP is reachable if there's at least one router
+ * subnet that includes it.
+ */
+ ovs_assert(neigh_mode == LB_NEIGH_RESPOND_REACHABLE);
+
+ SSET_FOR_EACH (ip_address, lb_ips_v4) {
+ struct ovn_port *op;
+ ovs_be32 vip_ip4;
+ if (ip_parse(ip_address, &vip_ip4)) {
+ HMAP_FOR_EACH (op, dp_node, &lr_lbnat_rec->od->ports) {
+ if (lrouter_port_ipv4_reachable(op, vip_ip4)) {
+ sset_add(&lr_lbnat_rec->lb_ips->ips_v4_reachable,
+ ip_address);
+ break;
+ }
+ }
+ }
+ }
+
+ SSET_FOR_EACH (ip_address, lb_ips_v6) {
+ struct ovn_port *op;
+ struct in6_addr vip;
+ if (ipv6_parse(ip_address, &vip)) {
+ HMAP_FOR_EACH (op, dp_node, &lr_lbnat_rec->od->ports) {
+ if (lrouter_port_ipv6_reachable(op, &vip)) {
+ sset_add(&lr_lbnat_rec->lb_ips->ips_v6_reachable,
+ ip_address);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void
+remove_lrouter_lb_reachable_ips(struct lr_lb_nat_data_record *lr_lbnat_rec,
+ enum lb_neighbor_responder_mode neigh_mode,
+ const struct sset *lb_ips_v4,
+ const struct sset *lb_ips_v6)
+{
+ if (neigh_mode == LB_NEIGH_RESPOND_NONE) {
+ return;
+ }
+
+ const char *ip_address;
+ SSET_FOR_EACH (ip_address, lb_ips_v4) {
+ sset_find_and_delete(&lr_lbnat_rec->lb_ips->ips_v4_reachable,
+ ip_address);
+ }
+ SSET_FOR_EACH (ip_address, lb_ips_v6) {
+ sset_find_and_delete(&lr_lbnat_rec->lb_ips->ips_v6_reachable,
+ ip_address);
+ }
+}
+
+static void
+lr_lb_nat_data_build_vip_nats(struct lr_lb_nat_data_record *lr_lbnat_rec)
+{
+ sset_clear(&lr_lbnat_rec->vip_nats);
+ const char *external_ip;
+ SSET_FOR_EACH (external_ip, &lr_lbnat_rec->lrnat_rec->external_ips) {
+ bool is_vip_nat = false;
+ if (addr_is_ipv6(external_ip)) {
+ is_vip_nat = sset_contains(&lr_lbnat_rec->lb_ips->ips_v6,
+ external_ip);
+ } else {
+ is_vip_nat = sset_contains(&lr_lbnat_rec->lb_ips->ips_v4,
+ external_ip);
+ }
+
+ if (is_vip_nat) {
+ sset_add(&lr_lbnat_rec->vip_nats, external_ip);
+ }
+ }
+}
new file mode 100644
@@ -0,0 +1,90 @@
+/*
+ * 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_LB_NAT_DATA_H
+#define EN_LR_LB_NAT_DATA_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/lb.h"
+#include "lib/ovn-nb-idl.h"
+#include "lib/ovn-sb-idl.h"
+#include "lib/ovn-util.h"
+
+struct ovn_datapath;
+struct lr_nat_record;
+
+struct lr_lb_nat_data_record {
+ struct hmap_node key_node; /* Index on 'nbr->header_.uuid'. */
+
+ const struct ovn_datapath *od;
+ const struct lr_nat_record *lrnat_rec;
+
+ /* Load Balancer vIPs relevant for this datapath. */
+ struct ovn_lb_ip_set *lb_ips;
+
+ /* sset of vips which are also part of lr nats. */
+ struct sset vip_nats;
+};
+
+struct lr_lb_nat_data_table {
+ struct hmap entries;
+};
+
+#define LR_LB_NAT_DATA_TABLE_FOR_EACH(LR_LB_NAT_REC, TABLE) \
+ HMAP_FOR_EACH (LR_LB_NAT_REC, key_node, &(TABLE)->entries)
+
+struct lr_lb_nat_data_tracked_data {
+ /* Created or updated logical router with LB data. */
+ struct hmapx crupdated; /* Stores 'struct lr_lb_nat_data_record'. */
+
+ /* Deleted logical router with LB data. */
+ struct hmapx deleted; /* Stores 'struct lr_lb_nat_data_record'. */
+};
+
+struct ed_type_lr_lb_nat_data {
+ struct lr_lb_nat_data_table lr_lbnats;
+
+ bool tracked;
+ struct lr_lb_nat_data_tracked_data tracked_data;
+};
+
+struct lr_lb_nat_data_input {
+ const struct ovn_datapaths *lr_datapaths;
+ const struct hmap *lb_datapaths_map;
+ const struct hmap *lbgrp_datapaths_map;
+ const struct lr_nat_table *lr_nats;
+};
+
+void *en_lr_lb_nat_data_init(struct engine_node *, struct engine_arg *);
+void en_lr_lb_nat_data_cleanup(void *data);
+void en_lr_lb_nat_data_clear_tracked_data(void *data);
+void en_lr_lb_nat_data_run(struct engine_node *, void *data);
+
+bool lr_lb_nat_data_northd_handler(struct engine_node *, void *data);
+bool lr_lb_nat_data_lr_nat_handler(struct engine_node *, void *data);
+bool lr_lb_nat_data_lb_data_handler(struct engine_node *, void *data);
+
+const struct lr_lb_nat_data_record *lr_lb_nat_data_table_find(
+ const struct lr_lb_nat_data_table *, const struct nbrec_logical_router *);
+
+#endif /* EN_LR_LB_NAT_DATA_H */
\ No newline at end of file
@@ -83,6 +83,9 @@ struct lr_nat_table {
struct hmap entries; /* Stores struct lr_nat_record. */
};
+#define LR_NAT_TABLE_FOR_EACH(LR_NAT_REC, TABLE) \
+ HMAP_FOR_EACH (LR_NAT_REC, key_node, &(TABLE)->entries)
+
const struct lr_nat_record * lr_nat_table_find(const struct lr_nat_table *,
const struct nbrec_logical_router *);
@@ -22,6 +22,7 @@
#include "openvswitch/util.h"
#include "en-lr-nat.h"
+#include "en-lr-lb-nat-data.h"
#include "en-sync-sb.h"
#include "lib/inc-proc-eng.h"
#include "lib/lb.h"
@@ -41,7 +42,7 @@ static void sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
const struct nbrec_address_set_table *,
const struct nbrec_port_group_table *,
const struct sbrec_address_set_table *,
- const struct ovn_datapaths *lr_datapaths);
+ const struct lr_lb_nat_data_table *);
static const struct sbrec_address_set *sb_address_set_lookup_by_name(
struct ovsdb_idl_index *, const char *name);
static void update_sb_addr_set(struct sorted_array *,
@@ -87,11 +88,11 @@ en_sync_to_sb_addr_set_run(struct engine_node *node, void *data OVS_UNUSED)
EN_OVSDB_GET(engine_get_input("SB_address_set", node));
const struct engine_context *eng_ctx = engine_get_context();
- struct northd_data *northd_data = engine_get_input_data("northd", node);
-
+ const struct ed_type_lr_lb_nat_data *lr_lb_nat_data =
+ engine_get_input_data("lr_lb_nat_data", node);
sync_addr_sets(eng_ctx->ovnsb_idl_txn, nb_address_set_table,
nb_port_group_table, sb_address_set_table,
- &northd_data->lr_datapaths);
+ &lr_lb_nat_data->lr_lbnats);
engine_set_node_state(node, EN_UPDATED);
}
@@ -288,10 +289,12 @@ en_sync_to_sb_pb_run(struct engine_node *node, void *data OVS_UNUSED)
{
const struct engine_context *eng_ctx = engine_get_context();
struct northd_data *northd_data = engine_get_input_data("northd", node);
- struct ed_type_lr_nat_data *lr_nat_data =
- engine_get_input_data("lr_nat", node);
+ struct ed_type_lr_lb_nat_data *lr_lb_nat_data =
+ engine_get_input_data("lr_lb_nat_data", node);
+
sync_pbs(eng_ctx->ovnsb_idl_txn, &northd_data->ls_ports,
- &northd_data->lr_ports, &lr_nat_data->lr_nats);
+ &northd_data->lr_ports,
+ &lr_lb_nat_data->lr_lbnats);
engine_set_node_state(node, EN_UPDATED);
}
@@ -316,11 +319,12 @@ sync_to_sb_pb_northd_handler(struct engine_node *node, void *data OVS_UNUSED)
return false;
}
- struct ed_type_lr_nat_data *lr_nat_data =
- engine_get_input_data("lr_nat", node);
+ struct ed_type_lr_lb_nat_data *lr_lb_nat_data =
+ engine_get_input_data("lr_lb_nat_data", node);
if (!sync_pbs_for_northd_changed_ovn_ports(
- &nd->trk_northd_changes.trk_ovn_ports, &lr_nat_data->lr_nats)) {
+ &nd->trk_northd_changes.trk_ovn_ports,
+ &lr_lb_nat_data->lr_lbnats)) {
return false;
}
@@ -366,7 +370,7 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
const struct nbrec_address_set_table *nb_address_set_table,
const struct nbrec_port_group_table *nb_port_group_table,
const struct sbrec_address_set_table *sb_address_set_table,
- const struct ovn_datapaths *lr_datapaths)
+ const struct lr_lb_nat_data_table *lr_lbnats)
{
struct shash sb_address_sets = SHASH_INITIALIZER(&sb_address_sets);
@@ -410,16 +414,14 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
}
/* Sync router load balancer VIP generated address sets. */
- struct ovn_datapath *od;
- HMAP_FOR_EACH (od, key_node, &lr_datapaths->datapaths) {
- ovs_assert(od->nbr);
-
- if (sset_count(&od->lb_ips->ips_v4_reachable)) {
- char *ipv4_addrs_name = lr_lb_address_set_name(od->tunnel_key,
- AF_INET);
+ const struct lr_lb_nat_data_record *lrlb_rec;
+ LR_LB_NAT_DATA_TABLE_FOR_EACH (lrlb_rec, lr_lbnats) {
+ if (sset_count(&lrlb_rec->lb_ips->ips_v4_reachable)) {
+ char *ipv4_addrs_name =
+ lr_lb_address_set_name(lrlb_rec->od->tunnel_key, AF_INET);
struct sorted_array ipv4_addrs_sorted =
- sorted_array_from_sset(&od->lb_ips->ips_v4_reachable);
+ sorted_array_from_sset(&lrlb_rec->lb_ips->ips_v4_reachable);
sync_addr_set(ovnsb_txn, ipv4_addrs_name,
&ipv4_addrs_sorted, &sb_address_sets);
@@ -427,11 +429,11 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
free(ipv4_addrs_name);
}
- if (sset_count(&od->lb_ips->ips_v6_reachable)) {
- char *ipv6_addrs_name = lr_lb_address_set_name(od->tunnel_key,
- AF_INET6);
- struct sorted_array ipv6_addrs_sorted =
- sorted_array_from_sset(&od->lb_ips->ips_v6_reachable);
+ if (sset_count(&lrlb_rec->lb_ips->ips_v6_reachable)) {
+ char *ipv6_addrs_name =
+ lr_lb_address_set_name(lrlb_rec->od->tunnel_key, AF_INET6);
+ struct sorted_array ipv6_addrs_sorted = sorted_array_from_sset(
+ &lrlb_rec->lb_ips->ips_v6_reachable);
sync_addr_set(ovnsb_txn, ipv6_addrs_name,
&ipv6_addrs_sorted, &sb_address_sets);
@@ -31,6 +31,7 @@
#include "openvswitch/vlog.h"
#include "inc-proc-northd.h"
#include "en-lb-data.h"
+#include "en-lr-lb-nat-data.h"
#include "en-lr-nat.h"
#include "en-northd.h"
#include "en-lflow.h"
@@ -148,6 +149,7 @@ static ENGINE_NODE(sync_to_sb_lb, "sync_to_sb_lb");
static ENGINE_NODE(sync_to_sb_pb, "sync_to_sb_pb");
static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lb_data, "lb_data");
static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lr_nat, "lr_nat");
+static ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lr_lb_nat_data, "lr_lb_nat_data");
void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
struct ovsdb_idl_loop *sb)
@@ -196,6 +198,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_lr_nat, &en_nb_logical_router,
lr_nat_logical_router_handler);
+ engine_add_input(&en_lr_lb_nat_data, &en_northd,
+ lr_lb_nat_data_northd_handler);
+ engine_add_input(&en_lr_lb_nat_data, &en_lr_nat,
+ lr_lb_nat_data_lr_nat_handler);
+ engine_add_input(&en_lr_lb_nat_data, &en_lb_data,
+ lr_lb_nat_data_lb_data_handler);
+
engine_add_input(&en_mac_binding_aging, &en_nb_nb_global, NULL);
engine_add_input(&en_mac_binding_aging, &en_sb_mac_binding, NULL);
engine_add_input(&en_mac_binding_aging, &en_northd, NULL);
@@ -220,12 +229,14 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_lflow, &en_northd, lflow_northd_handler);
engine_add_input(&en_lflow, &en_port_group, lflow_port_group_handler);
engine_add_input(&en_lflow, &en_lr_nat, NULL);
+ engine_add_input(&en_lflow, &en_lr_lb_nat_data, NULL);
engine_add_input(&en_sync_to_sb_addr_set, &en_nb_address_set,
sync_to_sb_addr_set_nb_address_set_handler);
engine_add_input(&en_sync_to_sb_addr_set, &en_nb_port_group,
sync_to_sb_addr_set_nb_port_group_handler);
engine_add_input(&en_sync_to_sb_addr_set, &en_northd, NULL);
+ engine_add_input(&en_sync_to_sb_addr_set, &en_lr_lb_nat_data, NULL);
engine_add_input(&en_sync_to_sb_addr_set, &en_sb_address_set, NULL);
engine_add_input(&en_port_group, &en_nb_port_group,
@@ -243,7 +254,7 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_sync_to_sb_pb, &en_northd,
sync_to_sb_pb_northd_handler);
- engine_add_input(&en_sync_to_sb_pb, &en_lr_nat, NULL);
+ engine_add_input(&en_sync_to_sb_pb, &en_lr_lb_nat_data, NULL);
/* en_sync_to_sb engine node syncs the SB database tables from
* the NB database tables.
@@ -44,6 +44,7 @@
#include "northd.h"
#include "en-lb-data.h"
#include "en-lr-nat.h"
+#include "en-lr-lb-nat-data.h"
#include "lib/ovn-parallel-hmap.h"
#include "ovn/actions.h"
#include "ovn/features.h"
@@ -617,13 +618,6 @@ init_lb_for_datapath(struct ovn_datapath *od)
}
}
-static void
-destroy_lb_for_datapath(struct ovn_datapath *od)
-{
- ovn_lb_ip_set_destroy(od->lb_ips);
- od->lb_ips = NULL;
-}
-
/* A group of logical router datapaths which are connected - either
* directly or indirectly.
* Each logical router can belong to only one group. */
@@ -676,7 +670,6 @@ ovn_datapath_destroy(struct hmap *datapaths, struct ovn_datapath *od)
destroy_ipam_info(&od->ipam_info);
free(od->router_ports);
free(od->ls_peers);
- destroy_lb_for_datapath(od);
free(od->localnet_ports);
free(od->l3dgw_ports);
destroy_mcast_info_for_datapath(od);
@@ -1179,12 +1172,6 @@ ovn_datapath_assign_requested_tnl_id(
}
}
-static inline size_t
-ods_size(const struct ovn_datapaths *datapaths)
-{
- return hmap_count(&datapaths->datapaths);
-}
-
static void
ods_build_array_index(struct ovn_datapaths *datapaths)
{
@@ -1317,121 +1304,6 @@ struct lflow_ref_node {
struct ovn_lflow *lflow;
};
-/* A logical switch port or logical router port.
- *
- * In steady state, an ovn_port points to a northbound Logical_Switch_Port
- * record (via 'nbsp') *or* a Logical_Router_Port record (via 'nbrp'), and to a
- * southbound Port_Binding record (via 'sb'). As the state of the system
- * changes, join_logical_ports() may determine that there is a new LSP or LRP
- * that has no corresponding Port_Binding record (in which case build_ports())
- * will create the missing Port_Binding) or that a Port_Binding record exists
- * that has no coresponding LSP (in which case build_ports() will delete the
- * spurious Port_Binding). Thus, after build_ports() runs, any given ovn_port
- * will have 'sb' nonnull, and 'nbsp' xor 'nbrp' nonnull.
- *
- * Ordinarily there is only one ovn_port that points to a given LSP or LRP (but
- * distributed gateway ports point a "derived" ovn_port to a duplicate LRP).
- */
-struct ovn_port {
- /* Port name aka key.
- *
- * This is ordinarily the same as nbsp->name or nbrp->name and
- * sb->logical_port. (A distributed gateway port creates a "derived"
- * ovn_port with key "cr-%s" % nbrp->name.) */
- struct hmap_node key_node; /* Index on 'key'. */
- char *key; /* nbsp->name, nbrp->name, sb->logical_port. */
- char *json_key; /* 'key', quoted for use in JSON. */
-
- const struct sbrec_port_binding *sb; /* May be NULL. */
-
- uint32_t tunnel_key;
-
- /* Logical switch port data. */
- const struct nbrec_logical_switch_port *nbsp; /* May be NULL. */
-
- struct lport_addresses *lsp_addrs; /* Logical switch port addresses. */
- unsigned int n_lsp_addrs; /* Total length of lsp_addrs. */
- unsigned int n_lsp_non_router_addrs; /* Number of elements from the
- * beginning of 'lsp_addrs' extracted
- * directly from LSP 'addresses'. */
-
- struct lport_addresses *ps_addrs; /* Port security addresses. */
- unsigned int n_ps_addrs;
-
- bool lsp_can_be_inc_processed; /* If it can be incrementally processed when
- the port changes. */
-
- /* Logical router port data. */
- const struct nbrec_logical_router_port *nbrp; /* May be NULL. */
-
- struct lport_addresses lrp_networks;
-
- struct ovn_port_routable_addresses routables;
-
- /* Logical port multicast data. */
- struct mcast_port_info mcast_info;
-
- /* At most one of l3dgw_port and cr_port can be not NULL. */
-
- /* This is set to a distributed gateway port if and only if this ovn_port
- * is "derived" from it. Otherwise this is set to NULL. The derived
- * ovn_port represents the instance of distributed gateway port on the
- * gateway chassis.*/
- struct ovn_port *l3dgw_port;
-
- /* This is set to the "derived" chassis-redirect port of this port if and
- * only if this port is a distributed gateway port. Otherwise this is set
- * to NULL. */
- struct ovn_port *cr_port;
-
- bool has_unknown; /* If the addresses have 'unknown' defined. */
-
- bool has_bfd;
-
- /* The port's peer:
- *
- * - A switch port S of type "router" has a router port R as a peer,
- * and R in turn has S has its peer.
- *
- * - Two connected logical router ports have each other as peer.
- *
- * - Other kinds of ports have no peer. */
- struct ovn_port *peer;
-
- struct ovn_datapath *od;
-
- struct ovs_list list; /* In list of similar records. */
-
- struct hmap_node dp_node; /* Node in od->ports. */
-
- struct lport_addresses proxy_arp_addrs;
-
- /* Temporarily used for traversing a list (or hmap) of ports. */
- bool visited;
-
- /* List of struct lflow_ref_node that points to the lflows generated by
- * this ovn_port.
- *
- * This data is initialized and destroyed by the en_northd node, but
- * populated and used only by the en_lflow node. Ideally this data should
- * be maintained as part of en_lflow's data (struct lflow_data): a hash
- * index from ovn_port key to lflows. However, it would be less efficient
- * and more complex:
- *
- * 1. It would require an extra search (using the index) to find the
- * lflows.
- *
- * 2. Building the index needs to be thread-safe, using either a global
- * lock which is obviously less efficient, or hash-based lock array which
- * is more complex.
- *
- * Adding the list here is more straightforward. The drawback is that we
- * need to keep in mind that this data belongs to en_lflow node, so never
- * access it from any other nodes.
- */
- struct ovs_list lflows;
-};
-
static bool lsp_can_be_inc_processed(const struct nbrec_logical_switch_port *);
static bool
@@ -1456,16 +1328,21 @@ destroy_routable_addresses(struct ovn_port_routable_addresses *ra)
}
static char **get_nat_addresses(const struct ovn_port *op, size_t *n,
- bool routable_only, bool include_lb_ips);
+ bool routable_only, bool include_lb_ips,
+ const struct lr_lb_nat_data_record *);
-static void
-assign_routable_addresses(struct ovn_port *op)
+static struct ovn_port_routable_addresses
+get_op_routable_addresses(struct ovn_port *op,
+ const struct lr_lb_nat_data_record *lr_lbnat_rec)
{
size_t n;
- char **nats = get_nat_addresses(op, &n, true, true);
+ char **nats = get_nat_addresses(op, &n, true, true, lr_lbnat_rec);
if (!nats) {
- return;
+ return (struct ovn_port_routable_addresses) {
+ .laddrs = NULL,
+ .n_addrs = 0,
+ };
}
struct lport_addresses *laddrs = xcalloc(n, sizeof(*laddrs));
@@ -1481,9 +1358,15 @@ assign_routable_addresses(struct ovn_port *op)
}
free(nats);
- /* Everything seems to have worked out */
- op->routables.laddrs = laddrs;
- op->routables.n_addrs = n_addrs;
+ if (!n_addrs) {
+ free(laddrs);
+ laddrs = NULL;
+ }
+
+ return (struct ovn_port_routable_addresses) {
+ .laddrs = laddrs,
+ .n_addrs = n_addrs,
+ };
}
@@ -1543,8 +1426,6 @@ ovn_port_destroy_orphan(struct ovn_port *port)
}
free(port->ps_addrs);
- destroy_routable_addresses(&port->routables);
-
destroy_lport_addresses(&port->lrp_networks);
destroy_lport_addresses(&port->proxy_arp_addrs);
free(port->json_key);
@@ -2586,9 +2467,7 @@ join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
sizeof *od->l3dgw_ports);
}
od->l3dgw_ports[od->n_l3dgw_ports++] = op;
-
- assign_routable_addresses(op);
- }
+ }
}
}
@@ -2685,7 +2564,8 @@ join_logical_ports(const struct sbrec_port_binding_table *sbrec_pb_table,
* and must free the returned array when it is no longer needed. */
static char **
get_nat_addresses(const struct ovn_port *op, size_t *n, bool routable_only,
- bool include_lb_ips)
+ bool include_lb_ips,
+ const struct lr_lb_nat_data_record *lr_lbnat_rec)
{
size_t n_nats = 0;
struct eth_addr mac;
@@ -2770,23 +2650,25 @@ get_nat_addresses(const struct ovn_port *op, size_t *n, bool routable_only,
}
}
- if (include_lb_ips) {
+ if (include_lb_ips && lr_lbnat_rec) {
const char *ip_address;
if (routable_only) {
- SSET_FOR_EACH (ip_address, &op->od->lb_ips->ips_v4_routable) {
+ SSET_FOR_EACH (ip_address,
+ &lr_lbnat_rec->lb_ips->ips_v4_routable) {
ds_put_format(&c_addresses, " %s", ip_address);
central_ip_address = true;
}
- SSET_FOR_EACH (ip_address, &op->od->lb_ips->ips_v6_routable) {
+ SSET_FOR_EACH (ip_address,
+ &lr_lbnat_rec->lb_ips->ips_v6_routable) {
ds_put_format(&c_addresses, " %s", ip_address);
central_ip_address = true;
}
} else {
- SSET_FOR_EACH (ip_address, &op->od->lb_ips->ips_v4) {
+ SSET_FOR_EACH (ip_address, &lr_lbnat_rec->lb_ips->ips_v4) {
ds_put_format(&c_addresses, " %s", ip_address);
central_ip_address = true;
}
- SSET_FOR_EACH (ip_address, &op->od->lb_ips->ips_v6) {
+ SSET_FOR_EACH (ip_address, &lr_lbnat_rec->lb_ips->ips_v6) {
ds_put_format(&c_addresses, " %s", ip_address);
central_ip_address = true;
}
@@ -3857,21 +3739,8 @@ build_lb_datapaths(const struct hmap *lbs, const struct hmap *lb_groups,
HMAP_FOR_EACH (od, key_node, &lr_datapaths->datapaths) {
ovs_assert(od->nbr);
- /* Checking load balancer groups first, starting from the largest one,
- * to more efficiently copy IP sets. */
- size_t largest_group = 0;
-
- for (size_t i = 1; i < od->nbr->n_load_balancer_group; i++) {
- if (od->nbr->load_balancer_group[i]->n_load_balancer >
- od->nbr->load_balancer_group[largest_group]->n_load_balancer) {
- largest_group = i;
- }
- }
-
for (size_t i = 0; i < od->nbr->n_load_balancer_group; i++) {
- size_t idx = (i + largest_group) % od->nbr->n_load_balancer_group;
-
- nbrec_lb_group = od->nbr->load_balancer_group[idx];
+ nbrec_lb_group = od->nbr->load_balancer_group[i];
const struct uuid *lb_group_uuid = &nbrec_lb_group->header_.uuid;
lb_group_dps =
@@ -3879,20 +3748,6 @@ build_lb_datapaths(const struct hmap *lbs, const struct hmap *lb_groups,
lb_group_uuid);
ovs_assert(lb_group_dps);
ovn_lb_group_datapaths_add_lr(lb_group_dps, od);
-
- if (!od->lb_ips) {
- od->lb_ips =
- ovn_lb_ip_set_clone(lb_group_dps->lb_group->lb_ips);
- } else {
- for (size_t j = 0; j < lb_group_dps->lb_group->n_lbs; j++) {
- build_lrouter_lb_ips(od->lb_ips,
- lb_group_dps->lb_group->lbs[j]);
- }
- }
- }
-
- if (!od->lb_ips) {
- od->lb_ips = ovn_lb_ip_set_create();
}
for (size_t i = 0; i < od->nbr->n_load_balancer; i++) {
@@ -3901,7 +3756,6 @@ build_lb_datapaths(const struct hmap *lbs, const struct hmap *lb_groups,
lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid);
ovs_assert(lb_dps);
ovn_lb_datapaths_add_lr(lb_dps, 1, &od);
- build_lrouter_lb_ips(od->lb_ips, lb_dps->lb);
}
}
@@ -3955,102 +3809,6 @@ build_lb_svcs(
}
}
-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,
- const struct in6_addr *addr);
-
-static void
-add_neigh_ips_to_lrouter(struct ovn_datapath *od,
- enum lb_neighbor_responder_mode neigh_mode,
- const struct sset *lb_ips_v4,
- const struct sset *lb_ips_v6)
-{
- /* If configured to not reply to any neighbor requests for all VIPs
- * return early.
- */
- if (neigh_mode == LB_NEIGH_RESPOND_NONE) {
- return;
- }
-
- const char *ip_address;
-
- /* If configured to reply to neighbor requests for all VIPs force them
- * all to be considered "reachable".
- */
- if (neigh_mode == LB_NEIGH_RESPOND_ALL) {
- SSET_FOR_EACH (ip_address, lb_ips_v4) {
- sset_add(&od->lb_ips->ips_v4_reachable, ip_address);
- }
- SSET_FOR_EACH (ip_address, lb_ips_v6) {
- sset_add(&od->lb_ips->ips_v6_reachable, ip_address);
- }
-
- return;
- }
-
- /* Otherwise, a VIP is reachable if there's at least one router
- * subnet that includes it.
- */
- ovs_assert(neigh_mode == LB_NEIGH_RESPOND_REACHABLE);
-
- SSET_FOR_EACH (ip_address, lb_ips_v4) {
- struct ovn_port *op;
- ovs_be32 vip_ip4;
- if (ip_parse(ip_address, &vip_ip4)) {
- HMAP_FOR_EACH (op, dp_node, &od->ports) {
- if (lrouter_port_ipv4_reachable(op, vip_ip4)) {
- sset_add(&od->lb_ips->ips_v4_reachable,
- ip_address);
- break;
- }
- }
- }
- }
-
- SSET_FOR_EACH (ip_address, lb_ips_v6) {
- struct ovn_port *op;
- struct in6_addr vip;
- if (ipv6_parse(ip_address, &vip)) {
- HMAP_FOR_EACH (op, dp_node, &od->ports) {
- if (lrouter_port_ipv6_reachable(op, &vip)) {
- sset_add(&od->lb_ips->ips_v6_reachable,
- ip_address);
- break;
- }
- }
- }
- }
-}
-
-static void
-remove_lrouter_lb_reachable_ips(struct ovn_datapath *od,
- enum lb_neighbor_responder_mode neigh_mode,
- const struct sset *lb_ips_v4,
- const struct sset *lb_ips_v6)
-{
- if (neigh_mode == LB_NEIGH_RESPOND_NONE) {
- return;
- }
-
- const char *ip_address;
- SSET_FOR_EACH (ip_address, lb_ips_v4) {
- sset_find_and_delete(&od->lb_ips->ips_v4_reachable, ip_address);
- }
- SSET_FOR_EACH (ip_address, lb_ips_v6) {
- sset_find_and_delete(&od->lb_ips->ips_v6_reachable, ip_address);
- }
-}
-
-static void
-build_lrouter_lb_reachable_ips(struct ovn_datapath *od,
- const struct ovn_northd_lb *lb)
-{
- add_neigh_ips_to_lrouter(od, lb->neigh_mode, &lb->ips_v4,
- &lb->ips_v6);
-}
-
-
static void
build_lrouter_lbs_check(const struct ovn_datapaths *lr_datapaths)
{
@@ -4072,43 +3830,6 @@ build_lrouter_lbs_check(const struct ovn_datapaths *lr_datapaths)
}
}
-static void
-build_lrouter_lbs_reachable_ips(struct ovn_datapaths *lr_datapaths,
- struct hmap *lb_dps_map,
- struct hmap *lb_group_dps_map)
-{
- struct ovn_datapath *od;
-
- HMAP_FOR_EACH (od, key_node, &lr_datapaths->datapaths) {
- if (!od->nbr) {
- continue;
- }
-
- for (size_t i = 0; i < od->nbr->n_load_balancer; i++) {
- struct ovn_lb_datapaths *lb_dps =
- ovn_lb_datapaths_find(lb_dps_map,
- &od->nbr->load_balancer[i]->header_.uuid);
- ovs_assert(lb_dps);
- build_lrouter_lb_reachable_ips(od, lb_dps->lb);
- }
-
- for (size_t i = 0; i < od->nbr->n_load_balancer_group; i++) {
- const struct nbrec_load_balancer_group *nbrec_lb_group =
- od->nbr->load_balancer_group[i];
- struct ovn_lb_group_datapaths *lb_group_dps;
-
- lb_group_dps =
- ovn_lb_group_datapaths_find(lb_group_dps_map,
- &nbrec_lb_group->header_.uuid);
- ovs_assert(lb_group_dps);
- for (size_t j = 0; j < lb_group_dps->lb_group->n_lbs; j++) {
- build_lrouter_lb_reachable_ips(od,
- lb_group_dps->lb_group->lbs[j]);
- }
- }
- }
-}
-
static void
build_lswitch_lbs_from_lrouter(struct ovn_datapaths *lr_datapaths,
struct hmap *lb_dps_map,
@@ -4172,8 +3893,6 @@ build_lb_port_related_data(
struct hmap *svc_monitor_map)
{
build_lrouter_lbs_check(lr_datapaths);
- build_lrouter_lbs_reachable_ips(lr_datapaths, lb_dps_map,
- lb_group_dps_map);
build_lb_svcs(ovnsb_txn, sbrec_service_monitor_table, ls_ports, lb_dps_map,
svc_monitor_lsps, svc_monitor_map);
build_lswitch_lbs_from_lrouter(lr_datapaths, lb_dps_map, lb_group_dps_map);
@@ -4539,7 +4258,8 @@ check_sb_lb_duplicates(const struct sbrec_load_balancer_table *table)
* Caller should make sure that the OVN SB IDL txn is not NULL. Presently it
* only syncs the nat column of port binding corresponding to the 'op->nbsp' */
static void
-sync_pb_for_lsp(struct ovn_port *op)
+sync_pb_for_lsp(struct ovn_port *op,
+ const struct lr_lb_nat_data_table *lr_lbnats)
{
ovs_assert(op->nbsp);
@@ -4558,10 +4278,17 @@ sync_pb_for_lsp(struct ovn_port *op)
if (nat_addresses && !strcmp(nat_addresses, "router")) {
if (op->peer && op->peer->od
&& (chassis || op->peer->od->n_l3dgw_ports)) {
- bool exclude_lb_vips = smap_get_bool(&op->nbsp->options,
+ bool include_lb_vips = !smap_get_bool(&op->nbsp->options,
"exclude-lb-vips-from-garp", false);
+
+ const struct lr_lb_nat_data_record *lr_lbnat_rec = NULL;
+
+ if (include_lb_vips) {
+ lr_lbnat_rec = lr_lb_nat_data_table_find(lr_lbnats,
+ op->peer->od->nbr);
+ }
nats = get_nat_addresses(op->peer, &n_nats, false,
- !exclude_lb_vips);
+ include_lb_vips, lr_lbnat_rec);
}
} else if (nat_addresses && (chassis || l3dgw_ports)) {
struct lport_addresses laddrs;
@@ -4668,7 +4395,8 @@ sync_pb_for_lsp(struct ovn_port *op)
* Caller should make sure that the OVN SB IDL txn is not NULL. Presently it
* only sets the port binding options column for the router ports */
static void
-sync_pb_for_lrp(struct ovn_port *op, const struct lr_nat_table *lr_nats)
+sync_pb_for_lrp(struct ovn_port *op,
+ const struct lr_lb_nat_data_table *lr_lbnats)
{
ovs_assert(op->nbrp);
@@ -4677,14 +4405,14 @@ sync_pb_for_lrp(struct ovn_port *op, const struct lr_nat_table *lr_nats)
const char *chassis_name = smap_get(&op->od->nbr->options, "chassis");
if (is_cr_port(op)) {
- const struct lr_nat_record *lrnat_rec =
- lr_nat_table_find(lr_nats, op->od->nbr);
- ovs_assert(lrnat_rec);
+ const struct lr_lb_nat_data_record *lr_lbnat_rec =
+ lr_lb_nat_data_table_find(lr_lbnats, op->od->nbr);
+ ovs_assert(lr_lbnat_rec);
smap_add(&new, "distributed-port", op->nbrp->name);
bool always_redirect =
- !lrnat_rec->has_distributed_nat &&
+ !lr_lbnat_rec->lrnat_rec->has_distributed_nat &&
!l3dgw_port_has_associated_vtep_lports(op->l3dgw_port);
const char *redirect_type = smap_get(&op->nbrp->options,
@@ -4735,17 +4463,18 @@ static void ovn_update_ipv6_opt_for_op(struct ovn_port *op);
* the logical switch ports. */
void
sync_pbs(struct ovsdb_idl_txn *ovnsb_idl_txn, struct hmap *ls_ports,
- struct hmap *lr_ports, const struct lr_nat_table *lr_nats)
+ struct hmap *lr_ports,
+ const struct lr_lb_nat_data_table *lr_lbnats)
{
ovs_assert(ovnsb_idl_txn);
struct ovn_port *op;
HMAP_FOR_EACH (op, key_node, ls_ports) {
- sync_pb_for_lsp(op);
+ sync_pb_for_lsp(op, lr_lbnats);
}
HMAP_FOR_EACH (op, key_node, lr_ports) {
- sync_pb_for_lrp(op, lr_nats);
+ sync_pb_for_lrp(op, lr_lbnats);
}
ovn_update_ipv6_options(lr_ports);
@@ -4754,17 +4483,18 @@ sync_pbs(struct ovsdb_idl_txn *ovnsb_idl_txn, struct hmap *ls_ports,
/* Sync the SB Port bindings for the added and updated logical switch ports
* of the tracked northd engine data. */
bool
-sync_pbs_for_northd_changed_ovn_ports(struct tracked_ovn_ports *trk_ovn_ports,
- const struct lr_nat_table *lr_nats)
+sync_pbs_for_northd_changed_ovn_ports(
+ struct tracked_ovn_ports *trk_ovn_ports,
+ const struct lr_lb_nat_data_table *lr_lbnats)
{
struct hmapx_node *hmapx_node;
struct ovn_port *op;
HMAPX_FOR_EACH (hmapx_node, &trk_ovn_ports->created) {
op = hmapx_node->data;
if (op->nbsp) {
- sync_pb_for_lsp(op);
+ sync_pb_for_lsp(op, lr_lbnats);
} else {
- sync_pb_for_lrp(op, lr_nats);
+ sync_pb_for_lrp(op, lr_lbnats);
ovn_update_ipv6_opt_for_op(op);
}
}
@@ -4772,9 +4502,9 @@ sync_pbs_for_northd_changed_ovn_ports(struct tracked_ovn_ports *trk_ovn_ports,
HMAPX_FOR_EACH (hmapx_node, &trk_ovn_ports->updated) {
op = hmapx_node->data;
if (op->nbsp) {
- sync_pb_for_lsp(op);
+ sync_pb_for_lsp(op, lr_lbnats);
} else {
- sync_pb_for_lrp(op, lr_nats);
+ sync_pb_for_lrp(op, lr_lbnats);
ovn_update_ipv6_opt_for_op(op);
}
}
@@ -5481,20 +5211,24 @@ fail:
}
/* Returns true if the logical router has changes which can be
- * incrementally handled.
+ * incrementally handled or the changes can be ignored.
* Presently supports i-p for the below changes:
* - load balancers and load balancer groups.
+ *
+ * Presently below changes are ignored:
+ * - router NAT changes - as the engine node lr-nat handles it.
*/
static bool
-lr_changes_can_be_handled(
+lr_changes_can_be_handled_or_ignored(
const struct nbrec_logical_router *lr)
{
/* Check if the columns are changed in this row. */
enum nbrec_logical_router_column_id col;
for (col = 0; col < NBREC_LOGICAL_ROUTER_N_COLUMNS; col++) {
if (nbrec_logical_router_is_updated(lr, col)) {
- if (col == NBREC_LOGICAL_ROUTER_COL_LOAD_BALANCER ||
- col == NBREC_LOGICAL_ROUTER_COL_LOAD_BALANCER_GROUP) {
+ if (col == NBREC_LOGICAL_ROUTER_COL_LOAD_BALANCER
+ || col == NBREC_LOGICAL_ROUTER_COL_LOAD_BALANCER_GROUP
+ || col == NBREC_LOGICAL_ROUTER_COL_NAT) {
continue;
}
return false;
@@ -5513,12 +5247,6 @@ lr_changes_can_be_handled(
OVSDB_IDL_CHANGE_MODIFY) > 0) {
return false;
}
- for (size_t i = 0; i < lr->n_nat; i++) {
- if (nbrec_nat_row_get_seqno(lr->nat[i],
- OVSDB_IDL_CHANGE_MODIFY) > 0) {
- return false;
- }
- }
for (size_t i = 0; i < lr->n_policies; i++) {
if (nbrec_logical_router_policy_row_get_seqno(lr->policies[i],
OVSDB_IDL_CHANGE_MODIFY) > 0) {
@@ -5534,14 +5262,15 @@ lr_changes_can_be_handled(
return true;
}
-/* Return true if changes are handled incrementally, false otherwise.
+/* Return true if changes are handled incrementally or can be safely
+ * ignored (because those changes are handled by other engine nodes),
+ * false otherwise.
* When there are any changes, try to track what's exactly changed and set
* northd_data->change_tracked accordingly: change tracked - true, otherwise,
* false.
* Note: Changes to load balancer and load balancer groups associated with
* the logical routers are handled separately in the lb_data change
- * handlers (northd_handle_lb_data_changes_pre_od and
- * northd_handle_lb_data_changes_post_od).
+ * handler (northd_handle_lb_data_changes).
* */
bool
northd_handle_lr_changes(const struct northd_input *ni,
@@ -5556,9 +5285,11 @@ northd_handle_lr_changes(const struct northd_input *ni,
goto fail;
}
- /* Presently only able to handle load balancer and
- * load balancer group changes. */
- if (!lr_changes_can_be_handled(changed_lr)) {
+ /* Presently
+ * - only able to handle load balancer and load balancer group
+ changes.
+ * - and ignore NAT changes */
+ if (!lr_changes_can_be_handled_or_ignored(changed_lr)) {
goto fail;
}
}
@@ -5810,10 +5541,6 @@ northd_handle_lb_data_changes(struct tracked_lb_data *trk_lb_data,
ovs_assert(lb_dps);
ovn_lb_datapaths_add_lr(lb_dps, 1, &od);
- /* Add the lb_ips of lb_dps to the od. */
- build_lrouter_lb_ips(od->lb_ips, lb_dps->lb);
- build_lrouter_lb_reachable_ips(od, lb_dps->lb);
-
/* Add the lb to the northd tracked data. */
hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
}
@@ -5832,10 +5559,6 @@ northd_handle_lb_data_changes(struct tracked_lb_data *trk_lb_data,
ovs_assert(lb_dps);
ovn_lb_datapaths_add_lr(lb_dps, 1, &od);
- /* Add the lb_ips of lb_dps to the od. */
- build_lrouter_lb_ips(od->lb_ips, lb_dps->lb);
- build_lrouter_lb_reachable_ips(od, lb_dps->lb);
-
/* Add the lb to the northd tracked data. */
hmapx_add(&nd_changes->trk_lbs.crupdated, lb_dps);
}
@@ -5871,22 +5594,6 @@ northd_handle_lb_data_changes(struct tracked_lb_data *trk_lb_data,
/* Re-evaluate 'od->has_lb_vip' */
init_lb_for_datapath(od);
- /* Update the od->lb_ips with the deleted and inserted
- * vips (if any). */
- remove_ips_from_lb_ip_set(od->lb_ips, lb->routable,
- &clb->deleted_vips_v4,
- &clb->deleted_vips_v6);
- add_ips_to_lb_ip_set(od->lb_ips, lb->routable,
- &clb->inserted_vips_v4,
- &clb->inserted_vips_v6);
-
- remove_lrouter_lb_reachable_ips(od, lb->neigh_mode,
- &clb->deleted_vips_v4,
- &clb->deleted_vips_v6);
- add_neigh_ips_to_lrouter(od, lb->neigh_mode,
- &clb->inserted_vips_v4,
- &clb->inserted_vips_v6);
-
/* Add the lr datapath to the northd tracked data. */
hmapx_add(&nd_changes->lr_with_changed_lbs.crupdated, od);
}
@@ -5914,9 +5621,6 @@ northd_handle_lb_data_changes(struct tracked_lb_data *trk_lb_data,
/* Re-evaluate 'od->has_lb_vip' */
init_lb_for_datapath(od);
- /* Add the lb_ips of lb_dps to the od. */
- build_lrouter_lb_ips(od->lb_ips, lb_dps->lb);
-
/* Add the lr datapath to the northd tracked data. */
hmapx_add(&nd_changes->lr_with_changed_lbs.crupdated, od);
}
@@ -9208,7 +8912,7 @@ arp_nd_ns_match(const char *ips, int addr_family, struct ds *match)
/* Returns 'true' if the IPv4 'addr' is on the same subnet with one of the
* IPs configured on the router port.
*/
-static bool
+bool
lrouter_port_ipv4_reachable(const struct ovn_port *op, ovs_be32 addr)
{
for (size_t i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
@@ -9224,7 +8928,7 @@ lrouter_port_ipv4_reachable(const struct ovn_port *op, ovs_be32 addr)
/* Returns 'true' if the IPv6 'addr' is on the same subnet with one of the
* IPs configured on the router port.
*/
-static bool
+bool
lrouter_port_ipv6_reachable(const struct ovn_port *op,
const struct in6_addr *addr)
{
@@ -9290,6 +8994,7 @@ build_lswitch_rport_arp_req_flows(struct ovn_port *op,
struct ovn_datapath *sw_od,
struct ovn_port *sw_op,
const struct lr_nat_table *lr_nats,
+ const struct lr_lb_nat_data_table *lr_lbnats,
struct hmap *lflows,
const struct ovsdb_idl_row *stage_hint)
{
@@ -9305,32 +9010,37 @@ build_lswitch_rport_arp_req_flows(struct ovn_port *op,
* router port.
* Priority: 80.
*/
-
- const char *ip_addr;
- SSET_FOR_EACH (ip_addr, &op->od->lb_ips->ips_v4_reachable) {
- ovs_be32 ipv4_addr;
-
- /* Check if the ovn port has a network configured on which we could
- * expect ARP requests for the LB VIP.
- */
- if (ip_parse(ip_addr, &ipv4_addr) &&
- lrouter_port_ipv4_reachable(op, ipv4_addr)) {
- build_lswitch_rport_arp_req_flow(
- ip_addr, AF_INET, sw_op, sw_od, 80, lflows,
- stage_hint);
+ const struct lr_lb_nat_data_record *lr_lbnat_rec = NULL;
+ if (op->od->nbr->n_load_balancer || op->od->nbr->n_load_balancer_group) {
+ lr_lbnat_rec = lr_lb_nat_data_table_find(lr_lbnats, op->od->nbr);
+ ovs_assert(lr_lbnat_rec);
+
+ const char *ip_addr;
+ SSET_FOR_EACH (ip_addr, &lr_lbnat_rec->lb_ips->ips_v4_reachable) {
+ ovs_be32 ipv4_addr;
+
+ /* Check if the ovn port has a network configured on which we could
+ * expect ARP requests for the LB VIP.
+ */
+ if (ip_parse(ip_addr, &ipv4_addr) &&
+ lrouter_port_ipv4_reachable(op, ipv4_addr)) {
+ build_lswitch_rport_arp_req_flow(
+ ip_addr, AF_INET, sw_op, sw_od, 80, lflows,
+ stage_hint);
+ }
}
- }
- SSET_FOR_EACH (ip_addr, &op->od->lb_ips->ips_v6_reachable) {
- struct in6_addr ipv6_addr;
+ SSET_FOR_EACH (ip_addr, &lr_lbnat_rec->lb_ips->ips_v6_reachable) {
+ struct in6_addr ipv6_addr;
- /* Check if the ovn port has a network configured on which we could
- * expect NS requests for the LB VIP.
- */
- if (ipv6_parse(ip_addr, &ipv6_addr) &&
- lrouter_port_ipv6_reachable(op, &ipv6_addr)) {
- build_lswitch_rport_arp_req_flow(
- ip_addr, AF_INET6, sw_op, sw_od, 80, lflows,
- stage_hint);
+ /* Check if the ovn port has a network configured on which we could
+ * expect NS requests for the LB VIP.
+ */
+ if (ipv6_parse(ip_addr, &ipv6_addr) &&
+ lrouter_port_ipv6_reachable(op, &ipv6_addr)) {
+ build_lswitch_rport_arp_req_flow(
+ ip_addr, AF_INET6, sw_op, sw_od, 80, lflows,
+ stage_hint);
+ }
}
}
@@ -9380,13 +9090,15 @@ build_lswitch_rport_arp_req_flows(struct ovn_port *op,
* expect ARP requests/NS for the DNAT external_ip.
*/
if (nat_entry_is_v6(nat_entry)) {
- if (!sset_contains(&op->od->lb_ips->ips_v6, nat->external_ip)) {
+ if (!lr_lbnat_rec || !sset_contains(&lr_lbnat_rec->lb_ips->ips_v6,
+ nat->external_ip)) {
build_lswitch_rport_arp_req_flow(
nat->external_ip, AF_INET6, sw_op, sw_od, 80, lflows,
stage_hint);
}
} else {
- if (!sset_contains(&op->od->lb_ips->ips_v4, nat->external_ip)) {
+ if (!lr_lbnat_rec || !sset_contains(&lr_lbnat_rec->lb_ips->ips_v4,
+ nat->external_ip)) {
build_lswitch_rport_arp_req_flow(
nat->external_ip, AF_INET, sw_op, sw_od, 80, lflows,
stage_hint);
@@ -10447,6 +10159,7 @@ build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group,
static void
build_lswitch_ip_unicast_lookup(struct ovn_port *op,
const struct lr_nat_table *lr_nats,
+ const struct lr_lb_nat_data_table *lr_lbnats,
struct hmap *lflows,
struct ds *actions,
struct ds *match)
@@ -10462,7 +10175,8 @@ build_lswitch_ip_unicast_lookup(struct ovn_port *op,
*/
if (lsp_is_router(op->nbsp)) {
build_lswitch_rport_arp_req_flows(op->peer, op->od, op, lr_nats,
- lflows, &op->nbsp->header_);
+ lr_lbnats, lflows,
+ &op->nbsp->header_);
}
for (size_t i = 0; i < op->nbsp->n_addresses; i++) {
@@ -12652,6 +12366,7 @@ build_lrouter_port_nat_arp_nd_flow(struct ovn_port *op,
static void
build_lrouter_drop_own_dest(struct ovn_port *op,
const struct lr_nat_record *lrnat_rec,
+ const struct lr_lb_nat_data_record *lr_lbnat_rec,
enum ovn_stage stage,
uint16_t priority, bool drop_snat_ip,
struct hmap *lflows)
@@ -12664,8 +12379,9 @@ build_lrouter_drop_own_dest(struct ovn_port *op,
bool router_ip_in_snat_ips = !!shash_find(&lrnat_rec->snat_ips,
ip);
- bool router_ip_in_lb_ips =
- !!sset_find(&op->od->lb_ips->ips_v4, ip);
+ bool router_ip_in_lb_ips = (lr_lbnat_rec &&
+ !!sset_find(&lr_lbnat_rec->lb_ips->ips_v4,
+ ip));
bool drop_router_ip = (drop_snat_ip == (router_ip_in_snat_ips ||
router_ip_in_lb_ips));
@@ -12694,8 +12410,9 @@ build_lrouter_drop_own_dest(struct ovn_port *op,
bool router_ip_in_snat_ips = !!shash_find(&lrnat_rec->snat_ips,
ip);
- bool router_ip_in_lb_ips =
- !!sset_find(&op->od->lb_ips->ips_v6, ip);
+ bool router_ip_in_lb_ips = (lr_lbnat_rec &&
+ !!sset_find(&lr_lbnat_rec->lb_ips->ips_v6,
+ ip));
bool drop_router_ip = (drop_snat_ip == (router_ip_in_snat_ips ||
router_ip_in_lb_ips));
@@ -13407,7 +13124,8 @@ build_ip_routing_flows_for_lrp(
*/
static void
build_ip_routing_flows_for_router_type_lsp(
- struct ovn_port *op, const struct hmap *lr_ports, struct hmap *lflows)
+ struct ovn_port *op, const struct lr_lb_nat_data_table *lr_lbnats,
+ const struct hmap *lr_ports, struct hmap *lflows)
{
ovs_assert(op->nbsp);
if (!lsp_is_router(op->nbsp)) {
@@ -13415,7 +13133,8 @@ build_ip_routing_flows_for_router_type_lsp(
}
struct ovn_port *peer = ovn_port_get_peer(lr_ports, op);
- if (!peer || !peer->nbrp || !peer->lrp_networks.n_ipv4_addrs) {
+ if (!peer || !peer->nbrp || !peer->lrp_networks.n_ipv4_addrs
+ || !op->od->n_router_ports) {
return;
}
@@ -13426,19 +13145,28 @@ build_ip_routing_flows_for_router_type_lsp(
continue;
}
- struct ovn_port_routable_addresses *ra = &router_port->routables;
- for (size_t j = 0; j < ra->n_addrs; j++) {
- struct lport_addresses *laddrs = &ra->laddrs[j];
- for (size_t k = 0; k < laddrs->n_ipv4_addrs; k++) {
- add_route(lflows, peer->od, peer,
- peer->lrp_networks.ipv4_addrs[0].addr_s,
- laddrs->ipv4_addrs[k].network_s,
- laddrs->ipv4_addrs[k].plen, NULL, false, 0,
- &peer->nbrp->header_, false,
- ROUTE_PRIO_OFFSET_CONNECTED);
+ const struct lr_lb_nat_data_record *lr_lbnat_rec =
+ lr_lb_nat_data_table_find(lr_lbnats, router_port->od->nbr);
+
+ if (router_port->nbrp->ha_chassis_group ||
+ router_port->nbrp->n_gateway_chassis) {
+ struct ovn_port_routable_addresses ra =
+ get_op_routable_addresses(router_port, lr_lbnat_rec);
+ for (size_t j = 0; j < ra.n_addrs; j++) {
+ struct lport_addresses *laddrs = &ra.laddrs[j];
+ for (size_t k = 0; k < laddrs->n_ipv4_addrs; k++) {
+ add_route(lflows, peer->od, peer,
+ peer->lrp_networks.ipv4_addrs[0].addr_s,
+ laddrs->ipv4_addrs[k].network_s,
+ laddrs->ipv4_addrs[k].plen, NULL, false, 0,
+ &peer->nbrp->header_, false,
+ ROUTE_PRIO_OFFSET_CONNECTED);
+ }
}
+ destroy_routable_addresses(&ra);
}
}
+
}
static void
@@ -13662,33 +13390,36 @@ build_arp_resolve_flows_for_lrouter(
static void
routable_addresses_to_lflows(struct hmap *lflows, struct ovn_port *router_port,
- struct ovn_port *peer, struct ds *match,
- struct ds *actions)
+ struct ovn_port *peer,
+ const struct lr_lb_nat_data_record *lr_lbnat_rec,
+ struct ds *match, struct ds *actions)
{
- struct ovn_port_routable_addresses *ra = &router_port->routables;
- if (!ra->n_addrs) {
+ struct ovn_port_routable_addresses ra =
+ get_op_routable_addresses(router_port, lr_lbnat_rec);
+ if (!ra.n_addrs) {
return;
}
- for (size_t i = 0; i < ra->n_addrs; i++) {
+ for (size_t i = 0; i < ra.n_addrs; i++) {
ds_clear(match);
ds_put_format(match, "outport == %s && "REG_NEXT_HOP_IPV4" == {",
peer->json_key);
bool first = true;
- for (size_t j = 0; j < ra->laddrs[i].n_ipv4_addrs; j++) {
+ for (size_t j = 0; j < ra.laddrs[i].n_ipv4_addrs; j++) {
if (!first) {
ds_put_cstr(match, ", ");
}
- ds_put_cstr(match, ra->laddrs[i].ipv4_addrs[j].addr_s);
+ ds_put_cstr(match, ra.laddrs[i].ipv4_addrs[j].addr_s);
first = false;
}
ds_put_cstr(match, "}");
ds_clear(actions);
- ds_put_format(actions, "eth.dst = %s; next;", ra->laddrs[i].ea_s);
+ ds_put_format(actions, "eth.dst = %s; next;", ra.laddrs[i].ea_s);
ovn_lflow_add(lflows, peer->od, S_ROUTER_IN_ARP_RESOLVE, 100,
ds_cstr(match), ds_cstr(actions));
}
+ destroy_routable_addresses(&ra);
}
/* Local router ingress table ARP_RESOLVE: ARP Resolution.
@@ -13705,6 +13436,7 @@ routable_addresses_to_lflows(struct hmap *lflows, struct ovn_port *router_port,
static void
build_arp_resolve_flows_for_lrp(
struct ovn_port *op, const struct lr_nat_record *lrnat_rec,
+ const struct lr_lb_nat_data_record *lr_lbnat_rec,
struct hmap *lflows, struct ds *match, struct ds *actions)
{
ovs_assert(op->nbrp);
@@ -13781,8 +13513,8 @@ build_arp_resolve_flows_for_lrp(
*
* Priority 2.
*/
- build_lrouter_drop_own_dest(op, lrnat_rec, S_ROUTER_IN_ARP_RESOLVE, 2,
- true, lflows);
+ build_lrouter_drop_own_dest(op, lrnat_rec, lr_lbnat_rec,
+ S_ROUTER_IN_ARP_RESOLVE, 2, true, lflows);
}
/* This function adds ARP resolve flows related to a LSP. */
@@ -13790,6 +13522,7 @@ static void
build_arp_resolve_flows_for_lsp(
struct ovn_port *op, struct hmap *lflows,
const struct hmap *lr_ports,
+ const struct lr_lb_nat_data_table *lr_lbnats,
struct ds *match, struct ds *actions)
{
ovs_assert(op->nbsp);
@@ -13933,8 +13666,11 @@ build_arp_resolve_flows_for_lsp(
if (smap_get(&peer->od->nbr->options, "chassis")
|| peer->cr_port) {
+ const struct lr_lb_nat_data_record *lr_lbnat_rec;
+ lr_lbnat_rec = lr_lb_nat_data_table_find(lr_lbnats,
+ router_port->od->nbr);
routable_addresses_to_lflows(lflows, router_port, peer,
- match, actions);
+ lr_lbnat_rec, match, actions);
}
}
}
@@ -14654,6 +14390,7 @@ static void
build_lrouter_ipv4_ip_input(struct ovn_port *op,
struct hmap *lflows,
const struct lr_nat_record *lrnat_rec,
+ const struct lr_lb_nat_data_record *lr_lbnat_rec,
struct ds *match, struct ds *actions,
const struct shash *meter_groups)
{
@@ -14778,7 +14515,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
&op->nbrp->header_, lflows);
}
- if (sset_count(&op->od->lb_ips->ips_v4_reachable)) {
+ if (lr_lbnat_rec && sset_count(&lr_lbnat_rec->lb_ips->ips_v4_reachable)) {
ds_clear(match);
if (is_l3dgw_port(op)) {
ds_put_format(match, "is_chassis_resident(%s)",
@@ -14794,7 +14531,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
free(lb_ips_v4_as);
}
- if (sset_count(&op->od->lb_ips->ips_v6_reachable)) {
+ if (lr_lbnat_rec && sset_count(&lr_lbnat_rec->lb_ips->ips_v6_reachable)) {
ds_clear(match);
if (is_l3dgw_port(op)) {
@@ -14896,8 +14633,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
* Priority 60.
*/
if (!lrnat_rec->lb_force_snat_router_ip) {
- build_lrouter_drop_own_dest(op, lrnat_rec, S_ROUTER_IN_IP_INPUT, 60,
- false, lflows);
+ build_lrouter_drop_own_dest(op, lrnat_rec, lr_lbnat_rec,
+ S_ROUTER_IN_IP_INPUT, 60, false, lflows);
}
/* ARP / ND handling for external IP addresses.
*
@@ -16036,6 +15773,7 @@ struct lswitch_flow_build_info {
const struct hmap *lr_ports;
const struct ls_port_group_table *ls_port_groups;
const struct lr_nat_table *lr_nats;
+ const struct lr_lb_nat_data_table *lr_lbnats;
struct hmap *lflows;
struct hmap *igmp_groups;
const struct shash *meter_groups;
@@ -16119,14 +15857,15 @@ build_lswitch_and_lrouter_iterate_by_lr(struct ovn_datapath *od,
* switch port.
*/
static void
-build_lswitch_and_lrouter_iterate_by_lsp(struct ovn_port *op,
- const struct hmap *ls_ports,
- const struct hmap *lr_ports,
- const struct lr_nat_table *lr_nats,
- const struct shash *meter_groups,
- struct ds *match,
- struct ds *actions,
- struct hmap *lflows)
+build_lswitch_and_lrouter_iterate_by_lsp(
+ struct ovn_port *op, const struct hmap *ls_ports,
+ const struct hmap *lr_ports,
+ const struct lr_nat_table *lr_nats,
+ const struct lr_lb_nat_data_table *lr_lbnats,
+ const struct shash *meter_groups,
+ struct ds *match,
+ struct ds *actions,
+ struct hmap *lflows)
{
ovs_assert(op->nbsp);
start_collecting_lflows();
@@ -16139,11 +15878,14 @@ build_lswitch_and_lrouter_iterate_by_lsp(struct ovn_port *op,
meter_groups, actions, match);
build_lswitch_dhcp_options_and_response(op, lflows, meter_groups);
build_lswitch_external_port(op, lflows);
- build_lswitch_ip_unicast_lookup(op, lr_nats, lflows, actions, match);
+ build_lswitch_ip_unicast_lookup(op, lr_nats, lr_lbnats, lflows, actions,
+ match);
/* Build Logical Router Flows. */
- build_ip_routing_flows_for_router_type_lsp(op, lr_ports, lflows);
- build_arp_resolve_flows_for_lsp(op, lflows, lr_ports, match, actions);
+ build_ip_routing_flows_for_router_type_lsp(op, lr_lbnats, lr_ports,
+ lflows);
+ build_arp_resolve_flows_for_lsp(op, lflows, lr_ports, lr_lbnats,
+ match, actions);
link_ovn_port_to_lflows(op, &collected_lflows);
end_collecting_lflows();
@@ -16162,6 +15904,8 @@ build_lswitch_and_lrouter_iterate_by_lrp(struct ovn_port *op,
op->od->nbr);
ovs_assert(lrnet_rec);
+ const struct lr_lb_nat_data_record *lr_lbnat_rec =
+ lr_lb_nat_data_table_find(lsi->lr_lbnats, op->od->nbr);
build_adm_ctrl_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
&lsi->actions);
build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
@@ -16169,15 +15913,15 @@ build_lswitch_and_lrouter_iterate_by_lrp(struct ovn_port *op,
build_ip_routing_flows_for_lrp(op, lsi->lflows);
build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
&lsi->actions, lsi->meter_groups);
- build_arp_resolve_flows_for_lrp(op, lrnet_rec, lsi->lflows, &lsi->match,
- &lsi->actions);
+ build_arp_resolve_flows_for_lrp(op, lrnet_rec, lr_lbnat_rec, lsi->lflows,
+ &lsi->match, &lsi->actions);
build_egress_delivery_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
&lsi->actions);
build_dhcpv6_reply_flows_for_lrouter_port(op, lsi->lflows, &lsi->match);
build_ipv6_input_flows_for_lrouter_port(op, lsi->lflows,
&lsi->match, &lsi->actions,
lsi->meter_groups);
- build_lrouter_ipv4_ip_input(op, lsi->lflows, lrnet_rec,
+ build_lrouter_ipv4_ip_input(op, lsi->lflows, lrnet_rec, lr_lbnat_rec,
&lsi->match, &lsi->actions, lsi->meter_groups);
build_lrouter_force_snat_flows_op(op, lrnet_rec, lsi->lflows, &lsi->match,
&lsi->actions);
@@ -16240,6 +15984,7 @@ build_lflows_thread(void *arg)
build_lswitch_and_lrouter_iterate_by_lsp(op, lsi->ls_ports,
lsi->lr_ports,
lsi->lr_nats,
+ lsi->lr_lbnats,
lsi->meter_groups,
&lsi->match,
&lsi->actions,
@@ -16350,6 +16095,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths,
const struct hmap *lr_ports,
const struct ls_port_group_table *ls_pgs,
const struct lr_nat_table *lr_nats,
+ const struct lr_lb_nat_data_table *lr_lbnats,
struct hmap *lflows,
struct hmap *igmp_groups,
const struct shash *meter_groups,
@@ -16380,6 +16126,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths,
lsiv[index].lr_ports = lr_ports;
lsiv[index].ls_port_groups = ls_pgs;
lsiv[index].lr_nats = lr_nats;
+ lsiv[index].lr_lbnats = lr_lbnats;
lsiv[index].igmp_groups = igmp_groups;
lsiv[index].meter_groups = meter_groups;
lsiv[index].lb_dps_map = lb_dps_map;
@@ -16415,6 +16162,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths,
.lr_ports = lr_ports,
.ls_port_groups = ls_pgs,
.lr_nats = lr_nats,
+ .lr_lbnats = lr_lbnats,
.lflows = lflows,
.igmp_groups = igmp_groups,
.meter_groups = meter_groups,
@@ -16443,6 +16191,7 @@ build_lswitch_and_lrouter_flows(const struct ovn_datapaths *ls_datapaths,
build_lswitch_and_lrouter_iterate_by_lsp(op, lsi.ls_ports,
lsi.lr_ports,
lsi.lr_nats,
+ lsi.lr_lbnats,
lsi.meter_groups,
&lsi.match, &lsi.actions,
lsi.lflows);
@@ -16564,6 +16313,7 @@ void build_lflows(struct ovsdb_idl_txn *ovnsb_txn,
input_data->lr_ports,
input_data->ls_port_groups,
input_data->lr_nats,
+ input_data->lr_lbnats,
lflows,
&igmp_groups,
input_data->meter_groups,
@@ -17044,6 +16794,7 @@ lflow_handle_northd_port_changes(struct ovsdb_idl_txn *ovnsb_txn,
build_lswitch_and_lrouter_iterate_by_lsp(op, lflow_input->ls_ports,
lflow_input->lr_ports,
lflow_input->lr_nats,
+ lflow_input->lr_lbnats,
lflow_input->meter_groups,
&match, &actions,
lflows);
@@ -17082,6 +16833,7 @@ lflow_handle_northd_port_changes(struct ovsdb_idl_txn *ovnsb_txn,
build_lswitch_and_lrouter_iterate_by_lsp(op, lflow_input->ls_ports,
lflow_input->lr_ports,
lflow_input->lr_nats,
+ lflow_input->lr_lbnats,
lflow_input->meter_groups,
&match, &actions,
lflows);
@@ -173,6 +173,7 @@ struct lflow_input {
const struct hmap *lr_ports;
const struct ls_port_group_table *ls_port_groups;
const struct lr_nat_table *lr_nats;
+ const struct lr_lb_nat_data_table *lr_lbnats;
const struct shash *meter_groups;
const struct hmap *lb_datapaths_map;
const struct hmap *bfd_connections;
@@ -312,9 +313,6 @@ struct ovn_datapath {
/* router datapath has a logical port with redirect-type set to bridged. */
bool redirect_bridged;
- /* Load Balancer vIPs relevant for this datapath. */
- struct ovn_lb_ip_set *lb_ips;
-
struct ovn_port **localnet_ports;
size_t n_localnet_ports;
@@ -331,6 +329,125 @@ struct ovn_datapath {
const struct ovn_datapath *ovn_datapath_find(const struct hmap *datapaths,
const struct uuid *uuid);
+static inline size_t
+ods_size(const struct ovn_datapaths *datapaths)
+{
+ return hmap_count(&datapaths->datapaths);
+}
+
+/* A logical switch port or logical router port.
+ *
+ * In steady state, an ovn_port points to a northbound Logical_Switch_Port
+ * record (via 'nbsp') *or* a Logical_Router_Port record (via 'nbrp'), and to a
+ * southbound Port_Binding record (via 'sb'). As the state of the system
+ * changes, join_logical_ports() may determine that there is a new LSP or LRP
+ * that has no corresponding Port_Binding record (in which case build_ports())
+ * will create the missing Port_Binding) or that a Port_Binding record exists
+ * that has no coresponding LSP (in which case build_ports() will delete the
+ * spurious Port_Binding). Thus, after build_ports() runs, any given ovn_port
+ * will have 'sb' nonnull, and 'nbsp' xor 'nbrp' nonnull.
+ *
+ * Ordinarily there is only one ovn_port that points to a given LSP or LRP (but
+ * distributed gateway ports point a "derived" ovn_port to a duplicate LRP).
+ */
+struct ovn_port {
+ /* Port name aka key.
+ *
+ * This is ordinarily the same as nbsp->name or nbrp->name and
+ * sb->logical_port. (A distributed gateway port creates a "derived"
+ * ovn_port with key "cr-%s" % nbrp->name.) */
+ struct hmap_node key_node; /* Index on 'key'. */
+ char *key; /* nbsp->name, nbrp->name, sb->logical_port. */
+ char *json_key; /* 'key', quoted for use in JSON. */
+
+ const struct sbrec_port_binding *sb; /* May be NULL. */
+
+ uint32_t tunnel_key;
+
+ /* Logical switch port data. */
+ const struct nbrec_logical_switch_port *nbsp; /* May be NULL. */
+
+ struct lport_addresses *lsp_addrs; /* Logical switch port addresses. */
+ unsigned int n_lsp_addrs; /* Total length of lsp_addrs. */
+ unsigned int n_lsp_non_router_addrs; /* Number of elements from the
+ * beginning of 'lsp_addrs' extracted
+ * directly from LSP 'addresses'. */
+
+ struct lport_addresses *ps_addrs; /* Port security addresses. */
+ unsigned int n_ps_addrs;
+
+ bool lsp_can_be_inc_processed; /* If it can be incrementally processed when
+ the port changes. */
+
+ /* Logical router port data. */
+ const struct nbrec_logical_router_port *nbrp; /* May be NULL. */
+
+ struct lport_addresses lrp_networks;
+
+ /* Logical port multicast data. */
+ struct mcast_port_info mcast_info;
+
+ /* At most one of l3dgw_port and cr_port can be not NULL. */
+
+ /* This is set to a distributed gateway port if and only if this ovn_port
+ * is "derived" from it. Otherwise this is set to NULL. The derived
+ * ovn_port represents the instance of distributed gateway port on the
+ * gateway chassis.*/
+ struct ovn_port *l3dgw_port;
+
+ /* This is set to the "derived" chassis-redirect port of this port if and
+ * only if this port is a distributed gateway port. Otherwise this is set
+ * to NULL. */
+ struct ovn_port *cr_port;
+
+ bool has_unknown; /* If the addresses have 'unknown' defined. */
+
+ bool has_bfd;
+
+ /* The port's peer:
+ *
+ * - A switch port S of type "router" has a router port R as a peer,
+ * and R in turn has S has its peer.
+ *
+ * - Two connected logical router ports have each other as peer.
+ *
+ * - Other kinds of ports have no peer. */
+ struct ovn_port *peer;
+
+ struct ovn_datapath *od;
+
+ struct ovs_list list; /* In list of similar records. */
+
+ struct hmap_node dp_node; /* Node in od->ports. */
+
+ struct lport_addresses proxy_arp_addrs;
+
+ /* Temporarily used for traversing a list (or hmap) of ports. */
+ bool visited;
+
+ /* List of struct lflow_ref_node that points to the lflows generated by
+ * this ovn_port.
+ *
+ * This data is initialized and destroyed by the en_northd node, but
+ * populated and used only by the en_lflow node. Ideally this data should
+ * be maintained as part of en_lflow's data (struct lflow_data): a hash
+ * index from ovn_port key to lflows. However, it would be less efficient
+ * and more complex:
+ *
+ * 1. It would require an extra search (using the index) to find the
+ * lflows.
+ *
+ * 2. Building the index needs to be thread-safe, using either a global
+ * lock which is obviously less efficient, or hash-based lock array which
+ * is more complex.
+ *
+ * Adding the list here is more straightforward. The drawback is that we
+ * need to keep in mind that this data belongs to en_lflow node, so never
+ * access it from any other nodes.
+ */
+ struct ovs_list lflows;
+};
+
void ovnnb_db_run(struct northd_input *input_data,
struct northd_data *data,
struct ovsdb_idl_txn *ovnnb_txn,
@@ -390,13 +507,27 @@ void sync_lbs(struct ovsdb_idl_txn *, const struct sbrec_load_balancer_table *,
struct chassis_features *chassis_features);
bool check_sb_lb_duplicates(const struct sbrec_load_balancer_table *);
+struct lr_lb_nat_data_table;
void sync_pbs(struct ovsdb_idl_txn *, struct hmap *ls_ports,
- struct hmap *lr_ports, const struct lr_nat_table *);
-bool sync_pbs_for_northd_changed_ovn_ports(struct tracked_ovn_ports *,
- const struct lr_nat_table *);
+ struct hmap *lr_ports,
+ const struct lr_lb_nat_data_table *);
+bool sync_pbs_for_northd_changed_ovn_ports(
+ struct tracked_ovn_ports *,
+ const struct lr_lb_nat_data_table *);
bool northd_has_tracked_data(struct northd_tracked_data *);
bool northd_has_only_ports_in_tracked_data(struct northd_tracked_data *);
bool northd_has_lbs_in_tracked_data(struct northd_tracked_data *);
+/* Returns 'true' if the IPv4 'addr' is on the same subnet with one of the
+ * IPs configured on the router port.
+ */
+bool lrouter_port_ipv4_reachable(const struct ovn_port *, ovs_be32 addr);
+
+/* Returns 'true' if the IPv6 'addr' is on the same subnet with one of the
+ * IPs configured on the router port.
+ */
+bool lrouter_port_ipv6_reachable(const struct ovn_port *,
+ const struct in6_addr *);
+
#endif /* NORTHD_H */
@@ -10416,18 +10416,21 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set load_balancer . ip_port_mappings:10.0.0.3=sw0-p1:10.0.0.2
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
check ovn-nbctl --wait=sb set load_balancer . options:foo=bar
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
check ovn-nbctl --wait=sb -- lb-add lb2 20.0.0.10:80 20.0.0.20:80 -- lb-add lb3 30.0.0.10:80 30.0.0.20:80
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10437,6 +10440,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb -- lb-del lb2 -- lb-del lb3
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10450,6 +10454,7 @@ AT_CHECK([ovn-nbctl --wait=sb \
])
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10467,6 +10472,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear Load_Balancer . health_check
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10481,6 +10487,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
ovn-nbctl --wait=sb lsp-set-options sw0-lr0 router-port=lr0-sw0
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10489,6 +10496,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb ls-lb-add sw0 lb1
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
# A LB applied to a switch/router triggers:
# - a recompute in the first iteration (handling northd change)
@@ -10501,6 +10509,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set load_balancer lb1 vips:'"10.0.0.10:80"'='"10.0.0.100:80"'
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10510,6 +10519,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear load_Balancer lb1 vips
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10519,6 +10529,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.10:80 10.0.0.3:80
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10528,6 +10539,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.20:80 10.0.0.30:8080
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10537,6 +10549,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb ls-lb-del sw0 lb1
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10547,6 +10560,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb ls-lb-add sw0 lb1 -- lsp-add sw0 sw0p1
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
@@ -10567,6 +10581,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-lb-add lr0 lb1
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10576,6 +10591,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set load_balancer lb1 vips:'"10.0.0.10:80"'='"10.0.0.100:80"'
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10585,6 +10601,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear load_Balancer lb1 vips
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10594,6 +10611,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.10:80 10.0.0.3:80
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10603,6 +10621,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.20:80 10.0.0.30:8080
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10632,6 +10651,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb add load_balancer_group . load_Balancer $lb1_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10639,6 +10659,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear load_balancer_group . load_Balancer
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10655,6 +10676,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb add logical_switch sw0 load_balancer_group $lbg1_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
@@ -10671,6 +10693,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set load_balancer lb1 vips:'"10.0.0.10:80"'='"10.0.0.100:80"'
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10680,6 +10703,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear load_Balancer lb1 vips
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10689,6 +10713,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.10:80 10.0.0.3:80
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10698,6 +10723,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.20:80 10.0.0.30:8080
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10713,6 +10739,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl add logical_router lr0 load_balancer_group $lbg1_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10722,6 +10749,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set load_balancer lb1 vips:'"10.0.0.10:80"'='"10.0.0.100:80"'
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10731,6 +10759,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear load_Balancer lb1 vips
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10740,6 +10769,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.10:80 10.0.0.3:80
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10749,6 +10779,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-add lb1 10.0.0.20:80 10.0.0.30:8080
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10757,6 +10788,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear logical_router lr0 load_balancer_group
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
@@ -10765,6 +10797,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb add logical_switch sw0 load_balancer_group $lbg1_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
@@ -10773,6 +10806,7 @@ check ovn-nbctl --wait=sb clear logical_switch sw0 load_balancer_group -- \
destroy load_balancer_group $lbg1_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb compute compute
@@ -10796,6 +10830,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
lbg1_uuid=$(ovn-nbctl --wait=sb create load_balancer_group name=lbg1)
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow norecompute nocompute
check_engine_stats sync_to_sb_lb norecompute nocompute
@@ -10803,6 +10838,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set load_balancer_group . load_balancer="$lb2_uuid,$lb3_uuid,$lb4_uuid"
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
@@ -10810,6 +10846,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set logical_switch sw0 load_balancer_group=$lbg1_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10818,6 +10855,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set logical_router lr1 load_balancer_group=$lbg1_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10826,6 +10864,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb ls-lb-add sw0 lb2
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10834,6 +10873,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb ls-lb-add sw0 lb3
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10843,6 +10883,7 @@ check ovn-nbctl --wait=sb lr-lb-add lr1 lb1
check ovn-nbctl --wait=sb lr-lb-add lr1 lb2
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10851,6 +10892,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb ls-lb-del sw0 lb2
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10859,6 +10901,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-lb-del lr1 lb2
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10869,6 +10912,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-del lb4
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10879,6 +10923,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lb-del lb2
check_engine_stats lb_data norecompute compute
check_engine_stats northd norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -10887,6 +10932,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb remove load_balancer_group . load_balancer $lb3_uuid
check_engine_stats lb_data norecompute compute
check_engine_stats northd recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_lb recompute compute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11019,6 +11065,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-add lr0
check_engine_stats northd recompute nocompute
check_engine_stats lr_nat recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11031,6 +11078,7 @@ check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.1/24
# for the SB port binding change.
check_engine_stats northd recompute compute
check_engine_stats lr_nat recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11042,6 +11090,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lsp-set-options sw0-lr0 router-port=lr0-sw0
check_engine_stats northd recompute nocompute
check_engine_stats lr_nat recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11067,6 +11116,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl set logical_router_port lr0-sw0 options:foo=bar
check_engine_stats northd recompute nocompute
check_engine_stats lr_nat recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11076,8 +11126,8 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
# engine nodes.
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-nat-add lr0 dnat_and_snat 172.168.0.110 10.0.0.4
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11085,8 +11135,8 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
# Update the NAT options column
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set NAT . options:foo=bar
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11094,8 +11144,9 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
# Update the NAT external_ip column
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set NAT . external_ip=172.168.0.120
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11103,8 +11154,9 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
# Update the NAT logical_ip column
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set NAT . logical_ip=10.0.0.10
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11112,8 +11164,9 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
# Update the NAT type
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set NAT . type=snat
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11121,8 +11174,9 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
# Create a dnat_and_snat NAT with external_mac and logical_port
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-nat-add lr0 dnat_and_snat 172.168.0.110 10.0.0.4 sw0p1 30:54:00:00:00:03
-check_engine_stats northd recompute compute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11131,8 +11185,9 @@ nat2_uuid=$(ovn-nbctl --bare --columns _uuid find nat logical_ip=10.0.0.4)
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb set NAT $nat2_uuid external_mac='"30:54:00:00:00:04"'
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11147,32 +11202,36 @@ check ovn-nbctl lr-lb-add lr0 lb2
# is a lb vip.
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-nat-add lr0 dnat_and_snat 172.168.0.140 10.0.0.20
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-nat-add lr0 dnat_and_snat 172.168.0.150 10.0.0.41
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-nat-del lr0 dnat_and_snat 172.168.0.150
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-nat-del lr0 dnat_and_snat 172.168.0.140
-check_engine_stats northd recompute nocompute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11180,8 +11239,9 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
# Delete the NAT
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb clear logical_router lr0 nat
-check_engine_stats northd recompute compute
-check_engine_stats lr_nat recompute nocompute
+check_engine_stats northd norecompute compute
+check_engine_stats lr_nat norecompute compute
+check_engine_stats lr_lb_nat_data norecompute compute
check_engine_stats lflow recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11191,6 +11251,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-policy-add lr0 10 "ip4.src == 10.0.0.3" reroute 172.168.0.101,172.168.0.102
check_engine_stats northd recompute nocompute
check_engine_stats lr_nat recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE
@@ -11199,6 +11260,7 @@ check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats
check ovn-nbctl --wait=sb lr-policy-del lr0 10 "ip4.src == 10.0.0.3"
check_engine_stats northd recompute nocompute
check_engine_stats lr_nat recompute nocompute
+check_engine_stats lr_lb_nat_data recompute nocompute
check_engine_stats sync_to_sb_pb recompute nocompute
check_engine_stats lflow recompute nocompute
CHECK_NO_CHANGE_AFTER_RECOMPUTE