In order to reuse parsed data keep hash map
of 'struct ovn_controller_lb', that is local for the
controller, in separate engine node called 'lb_data'.
Those data will be later on used to determine if we need
to flush CT for changed/removed LB backends.
Reported-at: https://bugzilla.redhat.com/1839103
Signed-off-by: Ales Musil <[email protected]>
---
v2: Rebase on top of current main.
Address comments from Dumitru:
- Fix the memory leak.
- Fix the find function.
Address comments from Mark:
- Make the function lb_is_local more ergonomic.
---
controller/lflow.c | 244 ++++++-------------
controller/lflow.h | 14 +-
controller/local_data.c | 26 ++
controller/local_data.h | 3 +
controller/ovn-controller.c | 460 +++++++++++++++++++++++++++++++-----
lib/lb.c | 34 +++
lib/lb.h | 8 +
7 files changed, 547 insertions(+), 242 deletions(-)
diff --git a/controller/lflow.c b/controller/lflow.c
index 08ce0386f..a0a26460c 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -98,10 +98,7 @@ consider_logical_flow(const struct sbrec_logical_flow *lflow,
struct lflow_ctx_out *l_ctx_out);
static void
-consider_lb_hairpin_flows(struct objdep_mgr *mgr,
- const struct sbrec_load_balancer *sbrec_lb,
- const struct hmap *local_datapaths,
- const struct smap *template_vars,
+consider_lb_hairpin_flows(const struct ovn_controller_lb *lb,
bool use_ct_mark,
struct ovn_desired_flow_table *flow_table,
struct simap *ids);
@@ -801,43 +798,6 @@ lflow_handle_changed_ref(enum objdep_type type, const char
*res_name,
return true;
}
-bool
-lb_handle_changed_ref(enum objdep_type type, const char *res_name,
- struct ovs_list *objs_todo,
- const void *in_arg, void *out_arg)
-{
- struct lflow_ctx_in *l_ctx_in = CONST_CAST(struct lflow_ctx_in *, in_arg);
- struct lflow_ctx_out *l_ctx_out = out_arg;
-
- struct object_to_resources_list_node *resource_lb_uuid;
- LIST_FOR_EACH_POP (resource_lb_uuid, list_node, objs_todo) {
- VLOG_DBG("Reprocess LB "UUID_FMT" for resource type: %s, name: %s",
- UUID_ARGS(&resource_lb_uuid->obj_uuid),
- objdep_type_name(type), res_name);
-
- const struct sbrec_load_balancer *lb =
- sbrec_load_balancer_table_get_for_uuid(
- l_ctx_in->lb_table, &resource_lb_uuid->obj_uuid);
- if (!lb) {
- VLOG_DBG("Failed to find LB "UUID_FMT" referred by: %s",
- UUID_ARGS(&resource_lb_uuid->obj_uuid), res_name);
- } else {
- ofctrl_remove_flows(l_ctx_out->flow_table,
- &resource_lb_uuid->obj_uuid);
-
- consider_lb_hairpin_flows(l_ctx_out->lb_deps_mgr, lb,
- l_ctx_in->local_datapaths,
- l_ctx_in->template_vars,
- l_ctx_in->lb_hairpin_use_ct_mark,
- l_ctx_out->flow_table,
- l_ctx_out->hairpin_lb_ids);
- }
-
- free(resource_lb_uuid);
- }
- return true;
-}
-
static void
lflow_parse_ctrl_meter(const struct sbrec_logical_flow *lflow,
struct ovn_extend_table *meter_table,
@@ -1647,10 +1607,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)
{
@@ -1689,7 +1648,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);
@@ -1714,17 +1673,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,
@@ -1784,7 +1743,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)
{
@@ -1877,10 +1836,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];
@@ -1973,10 +1931,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,
@@ -2007,9 +1965,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
@@ -2046,102 +2003,47 @@ 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(struct objdep_mgr *mgr,
- const struct sbrec_load_balancer *sbrec_lb,
- const struct hmap *local_datapaths,
- const struct smap *template_vars,
+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);
- VLOG_DBG("Load Balancer %s has conjunctive flow id %u",
- sbrec_lb->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 sset template_vars_ref = SSET_INITIALIZER(&template_vars_ref);
- struct ovn_controller_lb *lb =
- ovn_controller_lb_create(sbrec_lb, template_vars, &template_vars_ref);
- 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;
- }
- }
+ int id = simap_get(ids, lb->slb->name);
+ VLOG_DBG("Load Balancer %s has conjunctive flow id %u", lb->slb->name, id);
- const char *tv_name;
- SSET_FOR_EACH (tv_name, &template_vars_ref) {
- objdep_mgr_add(mgr, OBJDEP_TYPE_TEMPLATE, tv_name,
- &sbrec_lb->header_.uuid);
- }
- for (i = 0; i < lb->n_vips; i++) {
+ for (size_t 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);
- sset_destroy(&template_vars_ref);
+ 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(struct objdep_mgr *mgr,
- const struct sbrec_load_balancer_table *lb_table,
- const struct hmap *local_datapaths,
- const struct smap *template_vars,
+add_lb_hairpin_flows(const struct hmap *local_lbs,
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, local_lbs) {
/* 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.
@@ -2152,13 +2054,12 @@ add_lb_hairpin_flows(struct objdep_mgr *mgr,
* "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(mgr, lb, local_datapaths, template_vars,
- use_ct_mark, flow_table, ids);
+ consider_lb_hairpin_flows(lb, use_ct_mark, flow_table, ids);
}
}
@@ -2294,9 +2195,7 @@ 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_out->lb_deps_mgr, l_ctx_in->lb_table,
- l_ctx_in->local_datapaths,
- l_ctx_in->template_vars,
+ add_lb_hairpin_flows(l_ctx_in->local_lbs,
l_ctx_in->lb_hairpin_use_ct_mark,
l_ctx_out->flow_table,
l_ctx_out->hairpin_lb_ids,
@@ -2333,8 +2232,6 @@ lflow_destroy(void)
bool
lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *dp,
- const struct sbrec_load_balancer **dp_lbs,
- size_t n_dp_lbs,
struct lflow_ctx_in *l_ctx_in,
struct lflow_ctx_out *l_ctx_out)
{
@@ -2424,17 +2321,6 @@ lflow_add_flows_for_datapath(const struct
sbrec_datapath_binding *dp,
}
sbrec_static_mac_binding_index_destroy_row(smb_index_row);
- /* Add load balancer hairpin flows if the datapath has any load balancers
- * associated. */
- for (size_t i = 0; i < n_dp_lbs; i++) {
- consider_lb_hairpin_flows(l_ctx_out->lb_deps_mgr, dp_lbs[i],
- l_ctx_in->local_datapaths,
- l_ctx_in->template_vars,
- l_ctx_in->lb_hairpin_use_ct_mark,
- l_ctx_out->flow_table,
- l_ctx_out->hairpin_lb_ids);
- }
-
return handled;
}
@@ -2529,52 +2415,58 @@ lflow_handle_changed_mc_groups(struct lflow_ctx_in *l_ctx_in,
bool
lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in,
- struct lflow_ctx_out *l_ctx_out)
+ struct lflow_ctx_out *l_ctx_out,
+ const struct uuidset *deleted_lbs,
+ const struct uuidset *updated_lbs,
+ const struct uuidset *new_lbs,
+ const struct hmap *old_lbs)
{
- const struct sbrec_load_balancer *lb;
+ const struct ovn_controller_lb *lb;
+
struct id_pool *pool = l_ctx_out->hairpin_id_pool;
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,
- 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);
- }
+ struct uuidset_node *uuid_node;
+ UUIDSET_FOR_EACH (uuid_node, deleted_lbs) {
+ lb = ovn_controller_lb_find(old_lbs, &uuid_node->uuid);
+
+ VLOG_DBG("Remove hairpin flows for deleted load balancer "UUID_FMT,
+ UUID_ARGS(&uuid_node->uuid));
+ ofctrl_remove_flows(l_ctx_out->flow_table, &uuid_node->uuid);
+ id_pool_free_id(pool, simap_get(ids, lb->slb->name));
+ simap_find_and_delete(ids, lb->slb->name);
}
- SBREC_LOAD_BALANCER_TABLE_FOR_EACH_TRACKED (lb, l_ctx_in->lb_table) {
- if (sbrec_load_balancer_is_deleted(lb)) {
- continue;
- }
+ UUIDSET_FOR_EACH (uuid_node, updated_lbs) {
+ lb = ovn_controller_lb_find(l_ctx_in->local_lbs, &uuid_node->uuid);
- 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 {
- /* 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.
- *
- * If we are unable to allocate a unique ID then we have run out of
- * ids. As this is unrecoverable then we abort. However, this is
- * unlikely to happen as it would be mean that we have created
- * "UINT32_MAX" load-balancers.
- */
- uint32_t id;
- ovs_assert(id_pool_alloc_id(pool, &id));
- simap_put(ids, lb->name, id);
- }
+ VLOG_DBG("Remove and add hairpin flows for updated load balancer "
+ UUID_FMT, UUID_ARGS(&uuid_node->uuid));
+ ofctrl_remove_flows(l_ctx_out->flow_table, &uuid_node->uuid);
+ consider_lb_hairpin_flows(lb, l_ctx_in->lb_hairpin_use_ct_mark,
+ l_ctx_out->flow_table,
+ l_ctx_out->hairpin_lb_ids);
+ }
+
+ UUIDSET_FOR_EACH (uuid_node, new_lbs) {
+ lb = ovn_controller_lb_find(l_ctx_in->local_lbs, &uuid_node->uuid);
+
+ /* 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.
+ *
+ * If we are unable to allocate a unique ID then we have run out of
+ * ids. As this is unrecoverable then we abort. However, this is
+ * unlikely to happen as it would be mean that we have created
+ * "UINT32_MAX" load-balancers.
+ */
+ uint32_t id;
+ ovs_assert(id_pool_alloc_id(pool, &id));
+ simap_put(ids, lb->slb->name, id);
VLOG_DBG("Add load balancer hairpin flows for "UUID_FMT,
- UUID_ARGS(&lb->header_.uuid));
- consider_lb_hairpin_flows(l_ctx_out->lb_deps_mgr, lb,
- l_ctx_in->local_datapaths,
- l_ctx_in->template_vars,
- l_ctx_in->lb_hairpin_use_ct_mark,
+ UUID_ARGS(&uuid_node->uuid));
+ consider_lb_hairpin_flows(lb, l_ctx_in->lb_hairpin_use_ct_mark,
l_ctx_out->flow_table,
l_ctx_out->hairpin_lb_ids);
}
diff --git a/controller/lflow.h b/controller/lflow.h
index 9bb61c039..44e534696 100644
--- a/controller/lflow.h
+++ b/controller/lflow.h
@@ -101,7 +101,6 @@ struct lflow_ctx_in {
const struct sbrec_multicast_group_table *mc_group_table;
const struct sbrec_fdb_table *fdb_table;
const struct sbrec_chassis *chassis;
- const struct sbrec_load_balancer_table *lb_table;
const struct sbrec_static_mac_binding_table *static_mac_binding_table;
const struct hmap *local_datapaths;
const struct shash *addr_sets;
@@ -116,6 +115,7 @@ struct lflow_ctx_in {
const struct controller_event_options *controller_event_opts;
const struct smap *template_vars;
const struct flow_collector_ids *collector_ids;
+ const struct hmap *local_lbs;
bool lb_hairpin_use_ct_mark;
};
@@ -161,13 +161,16 @@ void lflow_handle_changed_static_mac_bindings(
const struct sbrec_static_mac_binding_table *smb_table,
const struct hmap *local_datapaths,
struct ovn_desired_flow_table *);
-bool lflow_handle_changed_lbs(struct lflow_ctx_in *, struct lflow_ctx_out *);
+bool lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in,
+ struct lflow_ctx_out *l_ctx_out,
+ const struct uuidset *deleted_lbs,
+ const struct uuidset *updated_lbs,
+ const struct uuidset *new_lbs,
+ const struct hmap *old_lbs);
bool lflow_handle_changed_fdbs(struct lflow_ctx_in *, struct lflow_ctx_out *);
void lflow_destroy(void);
bool lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *,
- const struct sbrec_load_balancer **dp_lbs,
- size_t n_dp_lbs,
struct lflow_ctx_in *,
struct lflow_ctx_out *);
bool lflow_handle_flows_for_lport(const struct sbrec_port_binding *,
@@ -178,7 +181,4 @@ bool lflow_handle_changed_mc_groups(struct lflow_ctx_in *,
bool lflow_handle_changed_port_bindings(struct lflow_ctx_in *,
struct lflow_ctx_out *);
-bool lb_handle_changed_ref(enum objdep_type type, const char *res_name,
- struct ovs_list *objs_todo,
- const void *in_arg, void *out_arg);
#endif /* controller/lflow.h */
diff --git a/controller/local_data.c b/controller/local_data.c
index 035f10fff..abd372172 100644
--- a/controller/local_data.c
+++ b/controller/local_data.c
@@ -645,3 +645,29 @@ 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. It is enough to find one datapath
+ * in "local_datapaths" to consider the LB to be local. */
+ size_t i;
+ for (i = 0; i < sbrec_lb->n_datapaths; i++) {
+ if (get_local_datapath(local_datapaths,
+ sbrec_lb->datapaths[i]->tunnel_key)) {
+ return true;
+ }
+ }
+
+ 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)) {
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/controller/local_data.h b/controller/local_data.h
index b5429eb58..748f009aa 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:
@@ -161,5 +162,7 @@ void add_local_datapath_multichassis_port(struct
local_datapath *ld,
const void *data);
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 6ea96e2dd..d96f16cc2 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -38,6 +38,7 @@
#include "if-status.h"
#include "ip-mcast.h"
#include "openvswitch/hmap.h"
+#include "lb.h"
#include "lflow.h"
#include "lflow-cache.h"
#include "lflow-conj-ids.h"
@@ -2661,6 +2662,377 @@ load_balancers_by_dp_cleanup(struct hmap *lbs)
free(lbs);
}
+/* Engine node which is used to handle runtime related data to
+ * load balancers. */
+struct ed_type_lb_data {
+ /* Locally installed 'struct ovn_controller_lb' by UUID. */
+ struct hmap local_lbs;
+ /* Load balancer <-> resource cross reference */
+ struct objdep_mgr deps_mgr;
+ /* Objects processed in the current engine execution.
+ * Cleared by 'en_lb_data_clear_tracked_data' before each engine
+ * execution. */
+ struct uuidset objs_processed;
+
+ bool change_tracked;
+ /* Load balancers removed/updated during last run. */
+ struct hmap old_lbs;
+ /* uuids of load balancers removed during last run. */
+ struct uuidset deleted;
+ /* uuids of load balancers updated during last run. */
+ struct uuidset updated;
+ /* uuids of load balancers added during last run. */
+ struct uuidset new;
+};
+
+struct lb_data_ctx_in {
+ const struct sbrec_load_balancer_table *lb_table;
+ const struct hmap *local_datapths;
+ const struct smap *template_vars;
+};
+
+static void
+lb_data_local_lb_add(struct ed_type_lb_data *lb_data,
+ const struct sbrec_load_balancer *sbrec_lb,
+ const struct smap *template_vars, bool tracked)
+{
+ struct sset template_vars_ref = SSET_INITIALIZER(&template_vars_ref);
+ const struct uuid *uuid = &sbrec_lb->header_.uuid;
+
+ struct ovn_controller_lb *lb =
+ ovn_controller_lb_create(sbrec_lb, template_vars, &template_vars_ref);
+ hmap_insert(&lb_data->local_lbs, &lb->hmap_node, uuid_hash(uuid));
+
+ const char *tv_name;
+ SSET_FOR_EACH (tv_name, &template_vars_ref) {
+ objdep_mgr_add(&lb_data->deps_mgr, OBJDEP_TYPE_TEMPLATE, tv_name,
+ uuid);
+ }
+
+ sset_destroy(&template_vars_ref);
+
+ if (!tracked) {
+ return;
+ }
+
+ if (ovn_controller_lb_find(&lb_data->old_lbs, uuid)) {
+ uuidset_insert(&lb_data->updated, uuid);
+ uuidset_find_and_delete(&lb_data->deleted, uuid);
+ } else {
+ uuidset_insert(&lb_data->new, uuid);
+ }
+}
+
+static void
+lb_data_local_lb_remove(struct ed_type_lb_data *lb_data,
+ struct ovn_controller_lb *lb, bool tracked)
+{
+ const struct uuid *uuid = &lb->slb->header_.uuid;
+
+ objdep_mgr_remove_obj(&lb_data->deps_mgr, uuid);
+ hmap_remove(&lb_data->local_lbs, &lb->hmap_node);
+
+ if (tracked) {
+ hmap_insert(&lb_data->old_lbs, &lb->hmap_node, uuid_hash(uuid));
+ uuidset_insert(&lb_data->deleted, uuid);
+ } else {
+ ovn_controller_lb_destroy(lb);
+ }
+}
+
+static bool
+lb_data_handle_changed_ref(enum objdep_type type, const char *res_name,
+ struct ovs_list *objs_todo, const void *in_arg,
+ void *out_arg)
+{
+ const struct lb_data_ctx_in *ctx_in = in_arg;
+ struct ed_type_lb_data *lb_data = out_arg;
+
+ struct object_to_resources_list_node *resource_lb_uuid;
+ LIST_FOR_EACH_POP (resource_lb_uuid, list_node, objs_todo) {
+ struct uuid *uuid = &resource_lb_uuid->obj_uuid;
+
+ VLOG_DBG("Reprocess LB "UUID_FMT" for resource type: %s, name: %s",
+ UUID_ARGS(uuid), objdep_type_name(type), res_name);
+
+ struct ovn_controller_lb *lb =
+ ovn_controller_lb_find(&lb_data->local_lbs, uuid);
+ if (!lb) {
+ free(resource_lb_uuid);
+ continue;
+ }
+
+ lb_data_local_lb_remove(lb_data, lb, true);
+
+ const struct sbrec_load_balancer *sbrec_lb =
+ sbrec_load_balancer_table_get_for_uuid(ctx_in->lb_table, uuid);
+ if (!lb_is_local(sbrec_lb, ctx_in->local_datapths)) {
+ free(resource_lb_uuid);
+ continue;
+ }
+
+ lb_data_local_lb_add(lb_data, sbrec_lb, ctx_in->template_vars, true);
+
+ free(resource_lb_uuid);
+ }
+ return true;
+}
+
+static void *
+en_lb_data_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+ struct ed_type_lb_data *lb_data = xzalloc(sizeof *lb_data);
+
+ hmap_init(&lb_data->local_lbs);
+ objdep_mgr_init(&lb_data->deps_mgr);
+ uuidset_init(&lb_data->objs_processed);
+ lb_data->change_tracked = false;
+ hmap_init(&lb_data->old_lbs);
+ uuidset_init(&lb_data->deleted);
+ uuidset_init(&lb_data->updated);
+ uuidset_init(&lb_data->new);
+
+ return lb_data;
+}
+
+static void
+en_lb_data_run(struct engine_node *node, void *data)
+{
+ struct ed_type_lb_data *lb_data = data;
+ struct ed_type_runtime_data *rt_data =
+ engine_get_input_data("runtime_data", node);
+ struct ed_type_template_vars *tv_data =
+ engine_get_input_data("template_vars", node);
+ const struct sbrec_load_balancer_table *lb_table =
+ EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
+
+ struct ovn_controller_lb *lb;
+ HMAP_FOR_EACH_SAFE (lb, hmap_node, &lb_data->local_lbs) {
+ lb_data_local_lb_remove(lb_data, lb, false);
+ }
+
+ const struct sbrec_load_balancer *sbrec_lb;
+ SBREC_LOAD_BALANCER_TABLE_FOR_EACH (sbrec_lb, lb_table) {
+ if (!lb_is_local(sbrec_lb, &rt_data->local_datapaths)) {
+ continue;
+ }
+
+ lb_data_local_lb_add(lb_data, sbrec_lb,
+ &tv_data->local_templates, false);
+ }
+
+ engine_set_node_state(node, EN_UPDATED);
+}
+
+static bool
+lb_data_sb_load_balancer_handler(struct engine_node *node, void *data)
+{
+ struct ed_type_lb_data *lb_data = data;
+ struct ed_type_runtime_data *rt_data =
+ engine_get_input_data("runtime_data", node);
+ struct ed_type_template_vars *tv_data =
+ engine_get_input_data("template_vars", node);
+ const struct sbrec_load_balancer_table *lb_table =
+ EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
+
+ const struct sbrec_load_balancer *sbrec_lb;
+ SBREC_LOAD_BALANCER_TABLE_FOR_EACH_TRACKED (sbrec_lb, lb_table) {
+ struct ovn_controller_lb *lb;
+
+ if (!sbrec_load_balancer_is_new(sbrec_lb)) {
+ lb = ovn_controller_lb_find(&lb_data->local_lbs,
+ &sbrec_lb->header_.uuid);
+ if (!lb) {
+ continue;
+ }
+
+ lb_data_local_lb_remove(lb_data, lb, true);
+ }
+
+ if (sbrec_load_balancer_is_deleted(sbrec_lb) ||
+ !lb_is_local(sbrec_lb, &rt_data->local_datapaths)) {
+ continue;
+ }
+
+ lb_data_local_lb_add(lb_data, sbrec_lb,
+ &tv_data->local_templates, true);
+ }
+
+ lb_data->change_tracked = true;
+ if (!uuidset_is_empty(&lb_data->deleted) ||
+ !uuidset_is_empty(&lb_data->updated) ||
+ !uuidset_is_empty(&lb_data->new)) {
+ engine_set_node_state(node, EN_UPDATED);
+ }
+
+ return true;
+}
+
+static bool
+lb_data_template_var_handler(struct engine_node *node, void *data)
+{
+ struct ed_type_lb_data *lb_data = data;
+ struct ed_type_runtime_data *rt_data =
+ engine_get_input_data("runtime_data", node);
+ struct ed_type_template_vars *tv_data =
+ engine_get_input_data("template_vars", node);
+ const struct sbrec_load_balancer_table *lb_table =
+ EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
+
+ if (!tv_data->change_tracked) {
+ return false;
+ }
+
+ const struct lb_data_ctx_in ctx_in = {
+ .lb_table = lb_table,
+ .local_datapths = &rt_data->local_datapaths,
+ .template_vars = &tv_data->local_templates
+ };
+
+ const char *res_name;
+ bool changed;
+
+ SSET_FOR_EACH (res_name, &tv_data->deleted) {
+ if (!objdep_mgr_handle_change(&lb_data->deps_mgr,
+ OBJDEP_TYPE_TEMPLATE,
+ res_name, lb_data_handle_changed_ref,
+ &lb_data->objs_processed,
+ &ctx_in, lb_data, &changed)) {
+ return false;
+ }
+ if (changed) {
+ engine_set_node_state(node, EN_UPDATED);
+ }
+ }
+ SSET_FOR_EACH (res_name, &tv_data->updated) {
+ if (!objdep_mgr_handle_change(&lb_data->deps_mgr,
+ OBJDEP_TYPE_TEMPLATE,
+ res_name, lb_data_handle_changed_ref,
+ &lb_data->objs_processed,
+ &ctx_in, lb_data, &changed)) {
+ return false;
+ }
+ if (changed) {
+ engine_set_node_state(node, EN_UPDATED);
+ }
+ }
+ SSET_FOR_EACH (res_name, &tv_data->new) {
+ if (!objdep_mgr_handle_change(&lb_data->deps_mgr,
+ OBJDEP_TYPE_TEMPLATE,
+ res_name, lb_data_handle_changed_ref,
+ &lb_data->objs_processed,
+ &ctx_in, lb_data, &changed)) {
+ return false;
+ }
+ if (changed) {
+ engine_set_node_state(node, EN_UPDATED);
+ }
+ }
+
+ lb_data->change_tracked = true;
+
+ return true;
+}
+
+static bool
+lb_data_runtime_data_handler(struct engine_node *node, void *data OVS_UNUSED)
+{
+ struct ed_type_lb_data *lb_data = data;
+ struct ed_type_runtime_data *rt_data =
+ engine_get_input_data("runtime_data", node);
+ struct ed_type_template_vars *tv_data =
+ engine_get_input_data("template_vars", node);
+ const struct sbrec_load_balancer_table *lb_table =
+ EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
+
+ /* There are no tracked data. Fall back to full recompute of
+ * lb_ct_tuple. */
+ if (!rt_data->tracked) {
+ return false;
+ }
+
+ struct hmap *tracked_dp_bindings = &rt_data->tracked_dp_bindings;
+ if (hmap_is_empty(tracked_dp_bindings)) {
+ return true;
+ }
+
+ struct hmap *lbs = NULL;
+
+ struct tracked_datapath *tdp;
+ HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) {
+ if (tdp->tracked_type != TRACKED_RESOURCE_NEW) {
+ continue;
+ }
+
+ if (!lbs) {
+ lbs = load_balancers_by_dp_init(&rt_data->local_datapaths,
+ lb_table);
+ }
+
+ struct load_balancers_by_dp *lbs_by_dp =
+ load_balancers_by_dp_find(lbs, tdp->dp);
+ if (!lbs_by_dp) {
+ continue;
+ }
+
+ for (size_t i = 0; i < lbs_by_dp->n_dp_lbs; i++) {
+ const struct sbrec_load_balancer *sbrec_lb = lbs_by_dp->dp_lbs[i];
+ struct ovn_controller_lb *lb =
+ ovn_controller_lb_find(&lb_data->local_lbs,
+ &sbrec_lb->header_.uuid);
+
+ if (!lb && lb_is_local(sbrec_lb, &rt_data->local_datapaths)) {
+ lb_data_local_lb_add(lb_data, sbrec_lb,
+ &tv_data->local_templates, true);
+ }
+ }
+ }
+
+ load_balancers_by_dp_cleanup(lbs);
+
+ lb_data->change_tracked = true;
+ if (!uuidset_is_empty(&lb_data->deleted) ||
+ !uuidset_is_empty(&lb_data->updated) ||
+ !uuidset_is_empty(&lb_data->new)) {
+ engine_set_node_state(node, EN_UPDATED);
+ }
+
+ return true;
+}
+
+static void
+en_lb_data_clear_tracked_data(void *data)
+{
+ struct ed_type_lb_data *lb_data = data;
+
+ struct ovn_controller_lb *lb;
+ HMAP_FOR_EACH_POP (lb, hmap_node, &lb_data->old_lbs) {
+ ovn_controller_lb_destroy(lb);
+ }
+
+ hmap_clear(&lb_data->old_lbs);
+ uuidset_clear(&lb_data->objs_processed);
+ uuidset_clear(&lb_data->deleted);
+ uuidset_clear(&lb_data->updated);
+ uuidset_clear(&lb_data->new);
+ lb_data->change_tracked = false;
+}
+
+static void
+en_lb_data_cleanup(void *data)
+{
+ struct ed_type_lb_data *lb_data = data;
+
+ ovn_controller_lbs_destroy(&lb_data->local_lbs);
+ objdep_mgr_destroy(&lb_data->deps_mgr);
+ uuidset_destroy(&lb_data->objs_processed);
+ ovn_controller_lbs_destroy(&lb_data->old_lbs);
+ uuidset_destroy(&lb_data->deleted);
+ uuidset_destroy(&lb_data->updated);
+ uuidset_destroy(&lb_data->new);
+}
+
/* Engine node which is used to handle the Non VIF data like
* - OVS patch ports
* - Tunnel ports and the related chassis information.
@@ -2858,12 +3230,10 @@ struct ed_type_lflow_output {
struct ovn_extend_table meter_table;
/* lflow <-> resource cross reference */
struct objdep_mgr lflow_deps_mgr;;
- /* load balancer <-> resource cross reference */
- struct objdep_mgr lb_deps_mgr;
/* conjunciton ID usage information of lflows */
struct conj_ids conj_ids;
- /* objects (lflows and lbs) processed in the current engine execution.
+ /* objects (lflows) processed in the current engine execution.
* Cleared by en_lflow_output_clear_tracked_data before each engine
* execution. */
struct uuidset objs_processed;
@@ -2941,9 +3311,6 @@ init_lflow_ctx(struct engine_node *node,
const struct sbrec_multicast_group_table *multicast_group_table =
EN_OVSDB_GET(engine_get_input("SB_multicast_group", node));
- const struct sbrec_load_balancer_table *lb_table =
- EN_OVSDB_GET(engine_get_input("SB_load_balancer", node));
-
const struct sbrec_fdb_table *fdb_table =
EN_OVSDB_GET(engine_get_input("SB_fdb", node));
@@ -2988,6 +3355,9 @@ init_lflow_ctx(struct engine_node *node,
struct ed_type_template_vars *template_vars =
engine_get_input_data("template_vars", node);
+ struct ed_type_lb_data *lb_data =
+ engine_get_input_data("lb_data", node);
+
l_ctx_in->sbrec_multicast_group_by_name_datapath =
sbrec_mc_group_by_name_dp;
l_ctx_in->sbrec_logical_flow_by_logical_datapath =
@@ -3006,7 +3376,6 @@ init_lflow_ctx(struct engine_node *node,
l_ctx_in->mc_group_table = multicast_group_table;
l_ctx_in->fdb_table = fdb_table,
l_ctx_in->chassis = chassis;
- l_ctx_in->lb_table = lb_table;
l_ctx_in->static_mac_binding_table = smb_table;
l_ctx_in->local_datapaths = &rt_data->local_datapaths;
l_ctx_in->addr_sets = addr_sets;
@@ -3022,12 +3391,12 @@ init_lflow_ctx(struct engine_node *node,
l_ctx_in->controller_event_opts = &fo->controller_event_opts;
l_ctx_in->template_vars = &template_vars->local_templates;
l_ctx_in->collector_ids = &fo->collector_ids;
+ l_ctx_in->local_lbs = &lb_data->local_lbs;
l_ctx_out->flow_table = &fo->flow_table;
l_ctx_out->group_table = &fo->group_table;
l_ctx_out->meter_table = &fo->meter_table;
l_ctx_out->lflow_deps_mgr = &fo->lflow_deps_mgr;
- l_ctx_out->lb_deps_mgr = &fo->lb_deps_mgr;
l_ctx_out->conj_ids = &fo->conj_ids;
l_ctx_out->objs_processed = &fo->objs_processed;
l_ctx_out->lflow_cache = fo->pd.lflow_cache;
@@ -3044,7 +3413,6 @@ en_lflow_output_init(struct engine_node *node OVS_UNUSED,
ovn_extend_table_init(&data->group_table);
ovn_extend_table_init(&data->meter_table);
objdep_mgr_init(&data->lflow_deps_mgr);
- objdep_mgr_init(&data->lb_deps_mgr);
lflow_conj_ids_init(&data->conj_ids);
uuidset_init(&data->objs_processed);
simap_init(&data->hd.ids);
@@ -3070,7 +3438,6 @@ en_lflow_output_cleanup(void *data)
ovn_extend_table_destroy(&flow_output_data->group_table);
ovn_extend_table_destroy(&flow_output_data->meter_table);
objdep_mgr_destroy(&flow_output_data->lflow_deps_mgr);
- objdep_mgr_destroy(&flow_output_data->lb_deps_mgr);
lflow_conj_ids_destroy(&flow_output_data->conj_ids);
uuidset_destroy(&flow_output_data->objs_processed);
lflow_cache_destroy(flow_output_data->pd.lflow_cache);
@@ -3108,7 +3475,6 @@ en_lflow_output_run(struct engine_node *node, void *data)
struct ovn_extend_table *group_table = &fo->group_table;
struct ovn_extend_table *meter_table = &fo->meter_table;
struct objdep_mgr *lflow_deps_mgr = &fo->lflow_deps_mgr;
- struct objdep_mgr *lb_deps_mgr = &fo->lb_deps_mgr;
static bool first_run = true;
if (first_run) {
@@ -3118,7 +3484,6 @@ en_lflow_output_run(struct engine_node *node, void *data)
ovn_extend_table_clear(group_table, false /* desired */);
ovn_extend_table_clear(meter_table, false /* desired */);
objdep_mgr_clear(lflow_deps_mgr);
- objdep_mgr_clear(lb_deps_mgr);
lflow_conj_ids_clear(&fo->conj_ids);
}
@@ -3481,16 +3846,6 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data)
if (changed) {
engine_set_node_state(node, EN_UPDATED);
}
- if (!objdep_mgr_handle_change(l_ctx_out.lb_deps_mgr,
- OBJDEP_TYPE_TEMPLATE,
- res_name, lb_handle_changed_ref,
- l_ctx_out.objs_processed,
- &l_ctx_in, &l_ctx_out, &changed)) {
- return false;
- }
- if (changed) {
- engine_set_node_state(node, EN_UPDATED);
- }
}
SSET_FOR_EACH (res_name, &tv_data->updated) {
if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr,
@@ -3503,16 +3858,6 @@ lflow_output_template_vars_handler(struct engine_node
*node, void *data)
if (changed) {
engine_set_node_state(node, EN_UPDATED);
}
- if (!objdep_mgr_handle_change(l_ctx_out.lb_deps_mgr,
- OBJDEP_TYPE_TEMPLATE,
- res_name, lb_handle_changed_ref,
- l_ctx_out.objs_processed,
- &l_ctx_in, &l_ctx_out, &changed)) {
- return false;
- }
- if (changed) {
- engine_set_node_state(node, EN_UPDATED);
- }
}
SSET_FOR_EACH (res_name, &tv_data->new) {
if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr,
@@ -3525,16 +3870,6 @@ lflow_output_template_vars_handler(struct engine_node
*node, void *data)
if (changed) {
engine_set_node_state(node, EN_UPDATED);
}
- if (!objdep_mgr_handle_change(l_ctx_out.lb_deps_mgr,
- OBJDEP_TYPE_TEMPLATE,
- res_name, lb_handle_changed_ref,
- l_ctx_out.objs_processed,
- &l_ctx_in, &l_ctx_out, &changed)) {
- return false;
- }
- if (changed) {
- engine_set_node_state(node, EN_UPDATED);
- }
}
return true;
@@ -3564,23 +3899,13 @@ lflow_output_runtime_data_handler(struct engine_node
*node,
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
struct ed_type_lflow_output *fo = data;
- struct hmap *lbs = NULL;
init_lflow_ctx(node, fo, &l_ctx_in, &l_ctx_out);
struct tracked_datapath *tdp;
HMAP_FOR_EACH (tdp, node, tracked_dp_bindings) {
if (tdp->tracked_type == TRACKED_RESOURCE_NEW) {
- if (!lbs) {
- lbs = load_balancers_by_dp_init(&rt_data->local_datapaths,
- l_ctx_in.lb_table);
- }
-
- struct load_balancers_by_dp *lbs_by_dp =
- load_balancers_by_dp_find(lbs, tdp->dp);
- if (!lflow_add_flows_for_datapath(
- tdp->dp, lbs_by_dp ? lbs_by_dp->dp_lbs : NULL,
- lbs_by_dp ? lbs_by_dp->n_dp_lbs : 0,
- &l_ctx_in, &l_ctx_out)) {
+ if (!lflow_add_flows_for_datapath(tdp->dp, &l_ctx_in,
+ &l_ctx_out)) {
return false;
}
}
@@ -3594,20 +3919,29 @@ lflow_output_runtime_data_handler(struct engine_node
*node,
}
}
- load_balancers_by_dp_cleanup(lbs);
engine_set_node_state(node, EN_UPDATED);
return true;
}
static bool
-lflow_output_sb_load_balancer_handler(struct engine_node *node, void *data)
+lflow_output_lb_data_handler(struct engine_node *node, void *data)
{
struct ed_type_lflow_output *fo = data;
+ struct ed_type_lb_data *lb_data = engine_get_input_data("lb_data", node);
+
+ if (!lb_data->change_tracked) {
+ return false;
+ }
+
struct lflow_ctx_in l_ctx_in;
struct lflow_ctx_out l_ctx_out;
init_lflow_ctx(node, fo, &l_ctx_in, &l_ctx_out);
- bool handled = lflow_handle_changed_lbs(&l_ctx_in, &l_ctx_out);
+ bool handled = lflow_handle_changed_lbs(&l_ctx_in, &l_ctx_out,
+ &lb_data->deleted,
+ &lb_data->updated,
+ &lb_data->new,
+ &lb_data->old_lbs);
engine_set_node_state(node, EN_UPDATED);
return handled;
@@ -4243,6 +4577,7 @@ main(int argc, char *argv[])
ENGINE_NODE_WITH_CLEAR_TRACK_DATA(port_groups, "port_groups");
ENGINE_NODE(northd_options, "northd_options");
ENGINE_NODE(dhcp_options, "dhcp_options");
+ ENGINE_NODE_WITH_CLEAR_TRACK_DATA(lb_data, "lb_data");
#define SB_NODE(NAME, NAME_STR) ENGINE_NODE_SB(NAME, NAME_STR);
SB_NODES
@@ -4258,6 +4593,13 @@ main(int argc, char *argv[])
engine_add_input(&en_template_vars, &en_sb_chassis_template_var,
template_vars_sb_chassis_template_var_handler);
+ engine_add_input(&en_lb_data, &en_sb_load_balancer,
+ lb_data_sb_load_balancer_handler);
+ engine_add_input(&en_lb_data, &en_template_vars,
+ lb_data_template_var_handler);
+ engine_add_input(&en_lb_data, &en_runtime_data,
+ lb_data_runtime_data_handler);
+
engine_add_input(&en_addr_sets, &en_sb_address_set,
addr_sets_sb_address_set_handler);
engine_add_input(&en_port_groups, &en_sb_port_group,
@@ -4362,8 +4704,8 @@ main(int argc, char *argv[])
engine_add_input(&en_lflow_output, &en_sb_logical_dp_group,
engine_noop_handler);
engine_add_input(&en_lflow_output, &en_sb_dns, NULL);
- engine_add_input(&en_lflow_output, &en_sb_load_balancer,
- lflow_output_sb_load_balancer_handler);
+ engine_add_input(&en_lflow_output, &en_lb_data,
+ lflow_output_lb_data_handler);
engine_add_input(&en_lflow_output, &en_sb_fdb,
lflow_output_sb_fdb_handler);
engine_add_input(&en_lflow_output, &en_sb_meter,
diff --git a/lib/lb.c b/lib/lb.c
index e0e97572f..de25c68c0 100644
--- a/lib/lb.c
+++ b/lib/lb.c
@@ -741,6 +741,15 @@ ovn_controller_lb_create(const struct sbrec_load_balancer
*sbrec_lb,
lex_str_free(&value_s);
}
+ 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.
*/
@@ -764,3 +773,28 @@ 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 ovn_controller_lb *lb;
+ size_t hash = uuid_hash(uuid);
+ HMAP_FOR_EACH_WITH_HASH (lb, hmap_node, hash, ovn_controller_lbs) {
+ if (uuid_equals(&lb->slb->header_.uuid, uuid)) {
+ return lb;
+ }
+ }
+ return NULL;
+}
diff --git a/lib/lb.h b/lib/lb.h
index 7594553d5..f32891ea6 100644
--- a/lib/lb.h
+++ b/lib/lb.h
@@ -172,8 +172,12 @@ 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. */
+ uint8_t proto;
+
struct ovn_lb_vip *vips;
size_t n_vips;
bool hairpin_orig_tuple; /* True if ovn-northd stores the original
@@ -191,6 +195,10 @@ struct ovn_controller_lb *ovn_controller_lb_create(
const struct smap *template_vars,
struct sset *template_vars_ref);
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);
char *ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key,
const char *lb_value, bool template, int
address_family);