To avaoid pasing LB multiple times store the
struct ovn_controller_lb in hmap. This can be
used later on for finding out which backend was
removed for clearing the CT. During I-P store
the "old" LBs between each run. That can be
later on used for the I-P of the LB CT tuple node.

Signed-off-by: Ales Musil <[email protected]>
---
Those patches are preparation for LB CT flush that are standalone
enough. The goal is to get early review and if it's usefull enough 
to merge them in advance.
---
 controller/lflow.c          | 137 +++++++++++++-----------------------
 controller/lflow.h          |   1 +
 controller/local_data.c     |  35 +++++++++
 controller/local_data.h     |   4 ++
 controller/ovn-controller.c |  53 ++++++++++++++
 lib/lb.c                    |  45 +++++++++++-
 lib/lb.h                    |  11 ++-
 7 files changed, 196 insertions(+), 90 deletions(-)

diff --git a/controller/lflow.c b/controller/lflow.c
index 32664b080..107cfb085 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -1793,10 +1793,9 @@ add_lb_vip_hairpin_reply_action(struct in6_addr *vip6, 
ovs_be32 vip,
  * original destination tuple stored by ovn-northd.
  */
 static void
-add_lb_vip_hairpin_flows(struct ovn_controller_lb *lb,
+add_lb_vip_hairpin_flows(const struct ovn_controller_lb *lb,
                          struct ovn_lb_vip *lb_vip,
                          struct ovn_lb_backend *lb_backend,
-                         uint8_t lb_proto,
                          bool use_ct_mark,
                          struct ovn_desired_flow_table *flow_table)
 {
@@ -1835,7 +1834,7 @@ add_lb_vip_hairpin_flows(struct ovn_controller_lb *lb,
                           ntohl(vip4));
         }
 
-        add_lb_vip_hairpin_reply_action(NULL, snat_vip4, lb_proto,
+        add_lb_vip_hairpin_reply_action(NULL, snat_vip4, lb->proto,
                                         lb_backend->port,
                                         lb->slb->header_.uuid.parts[0],
                                         &ofpacts);
@@ -1860,17 +1859,17 @@ add_lb_vip_hairpin_flows(struct ovn_controller_lb *lb,
                             ntoh128(vip6_value));
         }
 
-        add_lb_vip_hairpin_reply_action(snat_vip6, 0, lb_proto,
+        add_lb_vip_hairpin_reply_action(snat_vip6, 0, lb->proto,
                                         lb_backend->port,
                                         lb->slb->header_.uuid.parts[0],
                                         &ofpacts);
     }
 
     if (lb_backend->port) {
-        match_set_nw_proto(&hairpin_match, lb_proto);
+        match_set_nw_proto(&hairpin_match, lb->proto);
         match_set_tp_dst(&hairpin_match, htons(lb_backend->port));
         if (!lb->hairpin_orig_tuple) {
-            match_set_ct_nw_proto(&hairpin_match, lb_proto);
+            match_set_ct_nw_proto(&hairpin_match, lb->proto);
             match_set_ct_tp_dst(&hairpin_match, htons(lb_vip->vip_port));
         } else {
             match_set_reg_masked(&hairpin_match,
@@ -1930,7 +1929,7 @@ add_lb_ct_snat_hairpin_for_dp(const struct 
ovn_controller_lb *lb,
 }
 
 static void
-add_lb_ct_snat_hairpin_dp_flows(struct ovn_controller_lb *lb,
+add_lb_ct_snat_hairpin_dp_flows(const struct ovn_controller_lb *lb,
                                 uint32_t id,
                                 struct ovn_desired_flow_table *flow_table)
 {
@@ -2023,10 +2022,9 @@ add_lb_ct_snat_hairpin_dp_flows(struct ovn_controller_lb 
*lb,
  * that this LB belongs to. These flows (and the actual SNAT flow) get added
  * by add_lb_ct_snat_hairpin_dp_flows(). */
 static void
-add_lb_ct_snat_hairpin_vip_flow(struct ovn_controller_lb *lb,
+add_lb_ct_snat_hairpin_vip_flow(const struct ovn_controller_lb *lb,
                                 uint32_t id,
                                 struct ovn_lb_vip *lb_vip,
-                                uint8_t lb_proto,
                                 struct ovn_desired_flow_table *flow_table)
 {
     uint64_t stub[1024 / 8];
@@ -2119,10 +2117,10 @@ add_lb_ct_snat_hairpin_vip_flow(struct 
ovn_controller_lb *lb,
         }
     }
 
-    match_set_nw_proto(&match, lb_proto);
+    match_set_nw_proto(&match, lb->proto);
     if (lb_vip->vip_port) {
         if (!lb->hairpin_orig_tuple) {
-            match_set_ct_nw_proto(&match, lb_proto);
+            match_set_ct_nw_proto(&match, lb->proto);
             match_set_ct_tp_dst(&match, htons(lb_vip->vip_port));
         } else {
             match_set_reg_masked(&match, MFF_LOG_LB_ORIG_TP_DPORT - MFF_REG0,
@@ -2153,9 +2151,8 @@ add_lb_ct_snat_hairpin_vip_flow(struct ovn_controller_lb 
*lb,
  * Note: 'conjunctive_id' must be a unique identifier for each LB as it is used
  * as a conjunctive flow id. */
 static void
-add_lb_ct_snat_hairpin_flows(struct ovn_controller_lb *lb,
+add_lb_ct_snat_hairpin_flows(const struct ovn_controller_lb *lb,
                              uint32_t conjunctive_id,
-                             uint8_t lb_proto,
                              struct ovn_desired_flow_table *flow_table)
 {
     /* We must add a flow for each LB VIP. In the general case, this flow
@@ -2192,89 +2189,53 @@ add_lb_ct_snat_hairpin_flows(struct ovn_controller_lb 
*lb,
     for (int i = 0; i < lb->n_vips; i++) {
         struct ovn_lb_vip *lb_vip = &lb->vips[i];
         add_lb_ct_snat_hairpin_vip_flow(lb, conjunctive_id,
-                                        lb_vip, lb_proto, flow_table);
+                                        lb_vip, flow_table);
     }
 
     add_lb_ct_snat_hairpin_dp_flows(lb, conjunctive_id, flow_table);
 }
 
 static void
-consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb,
-                          const struct hmap *local_datapaths,
+consider_lb_hairpin_flows(const struct ovn_controller_lb *lb,
                           bool use_ct_mark,
                           struct ovn_desired_flow_table *flow_table,
                           struct simap *ids)
 {
-    int id = simap_get(ids, sbrec_lb->name);
+    int id = simap_get(ids, lb->slb->name);
     VLOG_DBG("Load Balancer %s has conjunctive flow id %u",
-             sbrec_lb->name, id);
+             lb->slb->name, id);
 
-    /* Check if we need to add flows or not.  If there is one datapath
-     * in the local_datapaths, it means all the datapaths of the lb
-     * will be in the local_datapaths. */
     size_t i;
-    for (i = 0; i < sbrec_lb->n_datapaths; i++) {
-        if (get_local_datapath(local_datapaths,
-                               sbrec_lb->datapaths[i]->tunnel_key)) {
-            break;
-        }
-    }
-
-    if (sbrec_lb->n_datapaths && i == sbrec_lb->n_datapaths) {
-        return;
-    }
-
-    struct sbrec_logical_dp_group *dp_group = sbrec_lb->datapath_group;
-
-    for (i = 0; dp_group && i < dp_group->n_datapaths; i++) {
-        if (get_local_datapath(local_datapaths,
-                               dp_group->datapaths[i]->tunnel_key)) {
-            break;
-        }
-    }
-
-    if (dp_group && i == dp_group->n_datapaths) {
-        return;
-    }
-
-    struct ovn_controller_lb *lb = ovn_controller_lb_create(sbrec_lb);
-    uint8_t lb_proto = IPPROTO_TCP;
-    if (lb->slb->protocol && lb->slb->protocol[0]) {
-        if (!strcmp(lb->slb->protocol, "udp")) {
-            lb_proto = IPPROTO_UDP;
-        } else if (!strcmp(lb->slb->protocol, "sctp")) {
-            lb_proto = IPPROTO_SCTP;
-        }
-    }
-
     for (i = 0; i < lb->n_vips; i++) {
         struct ovn_lb_vip *lb_vip = &lb->vips[i];
 
         for (size_t j = 0; j < lb_vip->n_backends; j++) {
             struct ovn_lb_backend *lb_backend = &lb_vip->backends[j];
 
-            add_lb_vip_hairpin_flows(lb, lb_vip, lb_backend, lb_proto,
+            add_lb_vip_hairpin_flows(lb, lb_vip, lb_backend,
                                      use_ct_mark, flow_table);
         }
     }
 
-    add_lb_ct_snat_hairpin_flows(lb, id, lb_proto, flow_table);
-
-    ovn_controller_lb_destroy(lb);
+    add_lb_ct_snat_hairpin_flows(lb, id, flow_table);
 }
 
 /* Adds OpenFlow flows to flow tables for each Load balancer VIPs and
  * backends to handle the load balanced hairpin traffic. */
 static void
-add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table,
+add_lb_hairpin_flows(const struct hmap *ovn_controller_lbs,
                      const struct hmap *local_datapaths, bool use_ct_mark,
                      struct ovn_desired_flow_table *flow_table,
                      struct simap *ids,
                      struct id_pool *pool)
 {
     uint32_t id;
-    const struct sbrec_load_balancer *lb;
-    SBREC_LOAD_BALANCER_TABLE_FOR_EACH (lb, lb_table) {
+    const struct ovn_controller_lb *lb;
+    HMAP_FOR_EACH (lb, hmap_node, ovn_controller_lbs) {
+        if (!lb_is_local(lb->slb, local_datapaths)) {
+            continue;
+        }
+
         /* Allocate a unique 32-bit integer to this load-balancer. This will
          * be used as a conjunctive flow id in the OFTABLE_CT_SNAT_HAIRPIN
          * table.
@@ -2284,14 +2245,12 @@ add_lb_hairpin_flows(const struct 
sbrec_load_balancer_table *lb_table,
          * unlikely to happen as it would be mean that we have created
          * "UINT32_MAX" load-balancers.
          */
-
-        id = simap_get(ids, lb->name);
+        id = simap_get(ids, lb->slb->name);
         if (!id) {
             ovs_assert(id_pool_alloc_id(pool, &id));
-            simap_put(ids, lb->name, id);
+            simap_put(ids, lb->slb->name, id);
         }
-        consider_lb_hairpin_flows(lb, local_datapaths, use_ct_mark,
-                                  flow_table, ids);
+        consider_lb_hairpin_flows(lb, use_ct_mark, flow_table, ids);
     }
 }
 
@@ -2427,7 +2386,8 @@ lflow_run(struct lflow_ctx_in *l_ctx_in, struct 
lflow_ctx_out *l_ctx_out)
                        l_ctx_in->static_mac_binding_table,
                        l_ctx_in->local_datapaths,
                        l_ctx_out->flow_table);
-    add_lb_hairpin_flows(l_ctx_in->lb_table, l_ctx_in->local_datapaths,
+    add_lb_hairpin_flows(l_ctx_in->ovn_controller_lbs,
+                         l_ctx_in->local_datapaths,
                          l_ctx_in->lb_hairpin_use_ct_mark,
                          l_ctx_out->flow_table,
                          l_ctx_out->hairpin_lb_ids,
@@ -2559,9 +2519,14 @@ lflow_add_flows_for_datapath(const struct 
sbrec_datapath_binding *dp,
 
     /* Add load balancer hairpin flows if the datapath has any load balancers
      * associated. */
+    const struct ovn_controller_lb *lb;
     for (size_t i = 0; i < n_dp_lbs; i++) {
-        consider_lb_hairpin_flows(dp_lbs[i], l_ctx_in->local_datapaths,
-                                  l_ctx_in->lb_hairpin_use_ct_mark,
+        lb = ovn_controller_lb_find(l_ctx_in->ovn_controller_lbs,
+                                    &dp_lbs[i]->header_.uuid);
+        if (!lb_is_local(lb->slb, l_ctx_in->local_datapaths)) {
+            continue;
+        }
+        consider_lb_hairpin_flows(lb, l_ctx_in->lb_hairpin_use_ct_mark,
                                   l_ctx_out->flow_table,
                                   l_ctx_out->hairpin_lb_ids);
     }
@@ -2656,25 +2621,22 @@ lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in,
     struct simap *ids = l_ctx_out->hairpin_lb_ids;
 
     SBREC_LOAD_BALANCER_TABLE_FOR_EACH_TRACKED (lb, l_ctx_in->lb_table) {
-        if (sbrec_load_balancer_is_deleted(lb)) {
-            VLOG_DBG("Remove hairpin flows for deleted load balancer "UUID_FMT,
+        if (!sbrec_load_balancer_is_new(lb)) {
+            VLOG_DBG("Remove hairpin flows for updated load balancer "UUID_FMT,
                      UUID_ARGS(&lb->header_.uuid));
             ofctrl_remove_flows(l_ctx_out->flow_table, &lb->header_.uuid);
-            id_pool_free_id(pool, simap_get(ids, lb->name));
-            simap_find_and_delete(ids, lb->name);
         }
-    }
 
-    SBREC_LOAD_BALANCER_TABLE_FOR_EACH_TRACKED (lb, l_ctx_in->lb_table) {
         if (sbrec_load_balancer_is_deleted(lb)) {
+            id_pool_free_id(pool, simap_get(ids, lb->name));
+            simap_find_and_delete(ids, lb->name);
             continue;
         }
 
-        if (!sbrec_load_balancer_is_new(lb)) {
-            VLOG_DBG("Remove hairpin flows for updated load balancer "UUID_FMT,
-                     UUID_ARGS(&lb->header_.uuid));
-            ofctrl_remove_flows(l_ctx_out->flow_table, &lb->header_.uuid);
-        } else {
+        const struct ovn_controller_lb *clb =
+            ovn_controller_lb_find(l_ctx_in->ovn_controller_lbs,
+                                   &lb->header_.uuid);
+        if (clb && lb_is_local(clb->slb, l_ctx_in->local_datapaths)) {
             /* Allocate a unique 32-bit integer to this load-balancer. This
              * will be used as a conjunctive flow id in the
              * OFTABLE_CT_SNAT_HAIRPIN table.
@@ -2687,14 +2649,13 @@ lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in,
             uint32_t id;
             ovs_assert(id_pool_alloc_id(pool, &id));
             simap_put(ids, lb->name, id);
-        }
 
-        VLOG_DBG("Add load balancer hairpin flows for "UUID_FMT,
-                 UUID_ARGS(&lb->header_.uuid));
-        consider_lb_hairpin_flows(lb, l_ctx_in->local_datapaths,
-                                  l_ctx_in->lb_hairpin_use_ct_mark,
-                                  l_ctx_out->flow_table,
-                                  l_ctx_out->hairpin_lb_ids);
+            VLOG_DBG("Add load balancer hairpin flows for "UUID_FMT,
+                     UUID_ARGS(&lb->header_.uuid));
+            consider_lb_hairpin_flows(clb, l_ctx_in->lb_hairpin_use_ct_mark,
+                                      l_ctx_out->flow_table,
+                                      l_ctx_out->hairpin_lb_ids);
+        }
     }
 
     return true;
diff --git a/controller/lflow.h b/controller/lflow.h
index a25634a88..c5d415261 100644
--- a/controller/lflow.h
+++ b/controller/lflow.h
@@ -162,6 +162,7 @@ struct lflow_ctx_in {
     const struct hmap *dhcp_opts;
     const struct hmap *dhcpv6_opts;
     const struct controller_event_options *controller_event_opts;
+    const struct hmap *ovn_controller_lbs;
     bool lb_hairpin_use_ct_mark;
 };
 
diff --git a/controller/local_data.c b/controller/local_data.c
index 9eee568d1..8b366c25b 100644
--- a/controller/local_data.c
+++ b/controller/local_data.c
@@ -640,3 +640,38 @@ datapath_is_transit_switch(const struct 
sbrec_datapath_binding *ldp)
 {
     return smap_get(&ldp->external_ids, "interconn-ts") != NULL;
 }
+
+bool
+lb_is_local(const struct sbrec_load_balancer *sbrec_lb,
+            const struct hmap *local_datapaths)
+{
+    /* Check if the lb is local or not.  If there is one datapath
+    * in the local_datapaths, it means all the datapaths of the lb
+    * will be in the local_datapaths. */
+    size_t i;
+    for (i = 0; i < sbrec_lb->n_datapaths; i++) {
+        if (get_local_datapath(local_datapaths,
+                               sbrec_lb->datapaths[i]->tunnel_key)) {
+            break;
+        }
+    }
+
+    if (sbrec_lb->n_datapaths && i == sbrec_lb->n_datapaths) {
+        return false;
+    }
+
+    struct sbrec_logical_dp_group *dp_group = sbrec_lb->datapath_group;
+
+    for (i = 0; dp_group && i < dp_group->n_datapaths; i++) {
+        if (get_local_datapath(local_datapaths,
+                               dp_group->datapaths[i]->tunnel_key)) {
+            break;
+        }
+    }
+
+    if (dp_group && i == dp_group->n_datapaths) {
+        return false;
+    }
+
+    return true;
+}
diff --git a/controller/local_data.h b/controller/local_data.h
index d898c8aa5..4d0db8187 100644
--- a/controller/local_data.h
+++ b/controller/local_data.h
@@ -30,6 +30,7 @@ struct sbrec_chassis;
 struct ovsdb_idl_index;
 struct ovsrec_bridge;
 struct ovsrec_interface_table;
+struct sbrec_load_balancer;
 
 /* A logical datapath that has some relevance to this hypervisor.  A logical
  * datapath D is relevant to hypervisor H if:
@@ -162,4 +163,7 @@ void add_local_datapath_multichassis_port(struct 
local_datapath *ld,
 void remove_local_datapath_multichassis_port(struct local_datapath *ld,
                                              char *logical_port);
 
+bool lb_is_local(const struct sbrec_load_balancer *sbrec_lb,
+                 const struct hmap *local_datapaths);
+
 #endif /* controller/local_data.h */
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index e7bcb661e..959f9a842 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -53,6 +53,7 @@
 #include "lib/chassis-index.h"
 #include "lib/extend-table.h"
 #include "lib/ip-mcast-index.h"
+#include "lib/lb.h"
 #include "lib/mac-binding-index.h"
 #include "lib/mcast-group-index.h"
 #include "lib/ovn-sb-idl.h"
@@ -1253,6 +1254,13 @@ struct ed_type_runtime_data {
     struct shash local_active_ports_ras;
 
     struct sset *postponed_ports;
+
+    /* Hash map of "struct ovn_controller_lb" by uuid. */
+    struct hmap ovn_controller_lbs;
+
+    /* Hash map of "struct ovn_controller_lb" by uuid. It contains "old" data
+     * for LBs that were changed/removed during I-P run. */
+    struct hmap old_ovn_controller_lbs;
 };
 
 /* struct ed_type_runtime_data has the below members for tracking the
@@ -1321,6 +1329,8 @@ en_runtime_data_clear_tracked_data(void *data_)
 {
     struct ed_type_runtime_data *data = data_;
 
+    ovn_controller_lbs_destroy(&data->old_ovn_controller_lbs);
+    hmap_init(&data->old_ovn_controller_lbs);
     tracked_datapaths_destroy(&data->tracked_dp_bindings);
     hmap_init(&data->tracked_dp_bindings);
     data->local_lports_changed = false;
@@ -1342,6 +1352,8 @@ en_runtime_data_init(struct engine_node *node OVS_UNUSED,
     local_binding_data_init(&data->lbinding_data);
     shash_init(&data->local_active_ports_ipv6_pd);
     shash_init(&data->local_active_ports_ras);
+    hmap_init(&data->ovn_controller_lbs);
+    hmap_init(&data->old_ovn_controller_lbs);
 
     /* Init the tracked data. */
     hmap_init(&data->tracked_dp_bindings);
@@ -1363,6 +1375,7 @@ en_runtime_data_cleanup(void *data)
     shash_destroy(&rt_data->local_active_ports_ipv6_pd);
     shash_destroy(&rt_data->local_active_ports_ras);
     local_binding_data_destroy(&rt_data->lbinding_data);
+    ovn_controller_lbs_destroy(&rt_data->ovn_controller_lbs);
 }
 
 static void
@@ -1484,6 +1497,8 @@ en_runtime_data_run(struct engine_node *node, void *data)
         sset_init(&rt_data->egress_ifaces);
         smap_init(&rt_data->local_iface_ids);
         local_binding_data_init(&rt_data->lbinding_data);
+        ovn_controller_lbs_destroy(&rt_data->ovn_controller_lbs);
+        hmap_init(&rt_data->ovn_controller_lbs);
     }
 
     struct ed_type_postponed_ports *pp_data =
@@ -1509,6 +1524,11 @@ en_runtime_data_run(struct engine_node *node, void *data)
 
     binding_run(&b_ctx_in, &b_ctx_out);
 
+    const struct sbrec_load_balancer_table *lb_table =
+        EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
+
+    ovn_controller_lbs_create(lb_table, &rt_data->ovn_controller_lbs);
+
     engine_set_node_state(node, EN_UPDATED);
 }
 
@@ -1652,6 +1672,36 @@ runtime_data_sb_datapath_binding_handler(struct 
engine_node *node OVS_UNUSED,
     return true;
 }
 
+static bool
+runtime_data_sb_load_balancer_handler(struct engine_node *node, void *data)
+{
+    struct ed_type_runtime_data *rt_data = data;
+    const struct sbrec_load_balancer_table *lb_table =
+        EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
+
+    const struct sbrec_load_balancer *lb;
+    SBREC_LOAD_BALANCER_TABLE_FOR_EACH_TRACKED (lb, lb_table) {
+        struct ovn_controller_lb *clb;
+        if (!sbrec_load_balancer_is_new(lb)) {
+            clb = ovn_controller_lb_find(&rt_data->ovn_controller_lbs,
+                                         &lb->header_.uuid);
+            hmap_remove(&rt_data->ovn_controller_lbs, &clb->hmap_node);
+            hmap_insert(&rt_data->old_ovn_controller_lbs, &clb->hmap_node,
+                        uuid_hash(&lb->header_.uuid));
+        }
+
+        if (sbrec_load_balancer_is_deleted(lb)) {
+            continue;
+        }
+
+        clb = ovn_controller_lb_create(lb);
+        hmap_insert(&rt_data->ovn_controller_lbs, &clb->hmap_node,
+                    uuid_hash(&lb->header_.uuid));
+    }
+
+    return true;
+}
+
 struct ed_type_addr_sets {
     struct shash addr_sets;
     bool change_tracked;
@@ -2733,6 +2783,7 @@ init_lflow_ctx(struct engine_node *node,
     l_ctx_in->related_lport_ids = &rt_data->related_lports.lport_ids;
     l_ctx_in->binding_lports = &rt_data->lbinding_data.lports;
     l_ctx_in->chassis_tunnels = &non_vif_data->chassis_tunnels;
+    l_ctx_in->ovn_controller_lbs = &rt_data->ovn_controller_lbs;
     l_ctx_in->lb_hairpin_use_ct_mark = n_opts->lb_hairpin_use_ct_mark;
     l_ctx_in->nd_ra_opts = &fo->nd_ra_opts;
     l_ctx_in->dhcp_opts = &dhcp_opts->v4_opts;
@@ -3849,6 +3900,8 @@ main(int argc, char *argv[])
                      runtime_data_sb_port_binding_handler);
     /* Run sb_ro_handler after port_binding_handler in case port get deleted */
     engine_add_input(&en_runtime_data, &en_sb_ro, runtime_data_sb_ro_handler);
+    engine_add_input(&en_runtime_data, &en_sb_load_balancer,
+                     runtime_data_sb_load_balancer_handler);
 
     /* The OVS interface handler for runtime_data changes MUST be executed
      * after the sb_port_binding_handler as port_binding deletes must be
diff --git a/lib/lb.c b/lib/lb.c
index ab5de38a8..adf2ee951 100644
--- a/lib/lb.c
+++ b/lib/lb.c
@@ -391,6 +391,15 @@ ovn_controller_lb_create(const struct sbrec_load_balancer 
*sbrec_lb)
         n_vips++;
     }
 
+    lb->proto = IPPROTO_TCP;
+    if (sbrec_lb->protocol && sbrec_lb->protocol[0]) {
+        if (!strcmp(sbrec_lb->protocol, "udp")) {
+            lb->proto = IPPROTO_UDP;
+        } else if (!strcmp(sbrec_lb->protocol, "sctp")) {
+            lb->proto = IPPROTO_SCTP;
+        }
+    }
+
     /* It's possible that parsing VIPs fails.  Update the lb->n_vips to the
      * correct value.
      */
@@ -404,7 +413,7 @@ ovn_controller_lb_create(const struct sbrec_load_balancer 
*sbrec_lb)
     return lb;
 }
 
-void
+static void
 ovn_controller_lb_destroy(struct ovn_controller_lb *lb)
 {
     for (size_t i = 0; i < lb->n_vips; i++) {
@@ -414,3 +423,37 @@ ovn_controller_lb_destroy(struct ovn_controller_lb *lb)
     destroy_lport_addresses(&lb->hairpin_snat_ips);
     free(lb);
 }
+
+void
+ovn_controller_lbs_destroy(struct hmap *ovn_controller_lbs)
+{
+    struct ovn_controller_lb *lb;
+    HMAP_FOR_EACH_POP (lb, hmap_node, ovn_controller_lbs) {
+        ovn_controller_lb_destroy(lb);
+    }
+    hmap_destroy(ovn_controller_lbs);
+}
+
+struct ovn_controller_lb *
+ovn_controller_lb_find(const struct hmap *ovn_controller_lbs,
+                       const struct uuid *uuid)
+{
+    struct hmap_node *node =
+        hmap_first_with_hash(ovn_controller_lbs, uuid_hash(uuid));
+    return (node
+            ? CONTAINER_OF(node, struct ovn_controller_lb, hmap_node)
+            : NULL);
+}
+
+
+void
+ovn_controller_lbs_create(const struct sbrec_load_balancer_table *lb_table,
+                          struct hmap *ovn_controller_lbs)
+{
+    const struct sbrec_load_balancer *sb_lb;
+    SBREC_LOAD_BALANCER_TABLE_FOR_EACH (sb_lb, lb_table) {
+        struct ovn_controller_lb *lb = ovn_controller_lb_create(sb_lb);
+        hmap_insert(ovn_controller_lbs, &lb->hmap_node,
+                    uuid_hash(&sb_lb->header_.uuid));
+    }
+}
diff --git a/lib/lb.h b/lib/lb.h
index 80ac03399..a2745af90 100644
--- a/lib/lb.h
+++ b/lib/lb.h
@@ -28,6 +28,7 @@ struct nbrec_load_balancer;
 struct nbrec_load_balancer_group;
 struct sbrec_load_balancer;
 struct sbrec_datapath_binding;
+struct sbrec_load_balancer_table;
 struct ovn_datapath;
 struct ovn_port;
 struct uuid;
@@ -156,10 +157,13 @@ ovn_lb_group_add_lr(struct ovn_lb_group *lb_group, struct 
ovn_datapath *lr)
 }
 
 struct ovn_controller_lb {
+    struct hmap_node hmap_node;
+
     const struct sbrec_load_balancer *slb; /* May be NULL. */
 
     struct ovn_lb_vip *vips;
     size_t n_vips;
+    uint8_t proto;
     bool hairpin_orig_tuple; /* True if ovn-northd stores the original
                               * destination tuple in registers.
                               */
@@ -172,6 +176,11 @@ struct ovn_controller_lb {
 
 struct ovn_controller_lb *ovn_controller_lb_create(
     const struct sbrec_load_balancer *);
-void ovn_controller_lb_destroy(struct ovn_controller_lb *);
+void ovn_controller_lbs_destroy(struct hmap *ovn_controller_lbs);
+struct ovn_controller_lb *ovn_controller_lb_find(
+    const struct hmap *ovn_controller_lbs, const struct uuid *uuid);
+void ovn_controller_lbs_create(
+    const struct sbrec_load_balancer_table *lb_table,
+    struct hmap *ovn_controller_lbs);
 
 #endif /* OVN_LIB_LB_H 1 */
-- 
2.37.2

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to