Add a new type of resource reference handling, from Template_Var to Load_Balancer. This is needed to correctly support updating Load_Balancer flows when the Template_Vars they refer to change.
Signed-off-by: Dumitru Ceara <[email protected]> --- controller/lflow.c | 105 +++++++++++++++++++++++++++++++++---------- controller/lflow.h | 7 ++- controller/ovn-controller.c | 67 +++++++++++++++++++++------ lib/lb.c | 7 ++- lib/lb.h | 3 + 5 files changed, 145 insertions(+), 44 deletions(-) diff --git a/controller/lflow.c b/controller/lflow.c index ffc8fdb6e..f59ee69aa 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -97,6 +97,15 @@ consider_logical_flow(const struct sbrec_logical_flow *lflow, struct lflow_ctx_in *l_ctx_in, 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, + bool use_ct_mark, + struct ovn_desired_flow_table *flow_table, + struct simap *ids); + static void add_port_sec_flows(const struct shash *binding_lports, const struct sbrec_chassis *, struct ovn_desired_flow_table *); @@ -223,7 +232,7 @@ lflow_handle_changed_flows(struct lflow_ctx_in *l_ctx_in, UUIDSET_INITIALIZER(&flood_remove_nodes); SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow, l_ctx_in->logical_flow_table) { - if (uuidset_find(l_ctx_out->lflows_processed, &lflow->header_.uuid)) { + if (uuidset_find(l_ctx_out->objs_processed, &lflow->header_.uuid)) { VLOG_DBG("lflow "UUID_FMT"has been processed, skip.", UUID_ARGS(&lflow->header_.uuid)); continue; @@ -252,14 +261,14 @@ lflow_handle_changed_flows(struct lflow_ctx_in *l_ctx_in, VLOG_DBG("re-add lflow "UUID_FMT, UUID_ARGS(&lflow->header_.uuid)); /* For the extra lflows that need to be reprocessed because of the - * flood remove, remove it from lflows_processed. */ + * flood remove, remove it from objs_processed. */ struct uuidset_node *unode = - uuidset_find(l_ctx_out->lflows_processed, + uuidset_find(l_ctx_out->objs_processed, &lflow->header_.uuid); if (unode) { VLOG_DBG("lflow "UUID_FMT"has been processed, now reprocess.", UUID_ARGS(&lflow->header_.uuid)); - uuidset_delete(l_ctx_out->lflows_processed, unode); + uuidset_delete(l_ctx_out->objs_processed, unode); } consider_logical_flow(lflow, false, l_ctx_in, l_ctx_out); @@ -658,7 +667,7 @@ lflow_handle_addr_set_update(const char *as_name, struct object_to_resources_list_node *resource_list_node; RESOURCE_FOR_EACH_OBJ (resource_list_node, resource_node) { const struct uuid *obj_uuid = &resource_list_node->obj_uuid; - if (uuidset_find(l_ctx_out->lflows_processed, obj_uuid)) { + if (uuidset_find(l_ctx_out->objs_processed, obj_uuid)) { VLOG_DBG("lflow "UUID_FMT"has been processed, skip.", UUID_ARGS(obj_uuid)); continue; @@ -748,13 +757,13 @@ lflow_handle_changed_ref(enum objdep_type type, const char *res_name, } /* For the extra lflows that need to be reprocessed because of the - * flood remove, remove it from lflows_processed. */ + * flood remove, remove it from objs_processed. */ struct uuidset_node *unode = - uuidset_find(l_ctx_out->lflows_processed, &lflow->header_.uuid); + uuidset_find(l_ctx_out->objs_processed, &lflow->header_.uuid); if (unode) { VLOG_DBG("lflow "UUID_FMT"has been processed, now reprocess.", UUID_ARGS(&lflow->header_.uuid)); - uuidset_delete(l_ctx_out->lflows_processed, unode); + uuidset_delete(l_ctx_out->objs_processed, unode); } consider_logical_flow(lflow, false, l_ctx_in, l_ctx_out); @@ -762,6 +771,42 @@ lflow_handle_changed_ref(enum objdep_type type, const char *res_name, uuidset_destroy(&flood_remove_nodes); } +void +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); + } +} + static void lflow_parse_ctrl_meter(const struct sbrec_logical_flow *lflow, struct ovn_extend_table *meter_table, @@ -1250,9 +1295,9 @@ consider_logical_flow(const struct sbrec_logical_flow *lflow, COVERAGE_INC(consider_logical_flow); if (!is_recompute) { - ovs_assert(!uuidset_find(l_ctx_out->lflows_processed, + ovs_assert(!uuidset_find(l_ctx_out->objs_processed, &lflow->header_.uuid)); - uuidset_insert(l_ctx_out->lflows_processed, &lflow->header_.uuid); + uuidset_insert(l_ctx_out->objs_processed, &lflow->header_.uuid); } if (dp) { @@ -1992,7 +2037,8 @@ add_lb_ct_snat_hairpin_flows(struct ovn_controller_lb *lb, } static void -consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, +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, bool use_ct_mark, @@ -2031,8 +2077,9 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, return; } - struct ovn_controller_lb *lb = ovn_controller_lb_create(sbrec_lb, - template_vars); + 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")) { @@ -2042,6 +2089,11 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, } } + 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++) { struct ovn_lb_vip *lb_vip = &lb->vips[i]; @@ -2056,12 +2108,14 @@ consider_lb_hairpin_flows(const struct sbrec_load_balancer *sbrec_lb, add_lb_ct_snat_hairpin_flows(lb, id, lb_proto, flow_table); ovn_controller_lb_destroy(lb); + sset_destroy(&template_vars_ref); } /* 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(struct objdep_mgr *mgr, + const struct sbrec_load_balancer_table *lb_table, const struct hmap *local_datapaths, const struct smap *template_vars, bool use_ct_mark, @@ -2087,7 +2141,7 @@ add_lb_hairpin_flows(const struct sbrec_load_balancer_table *lb_table, ovs_assert(id_pool_alloc_id(pool, &id)); simap_put(ids, lb->name, id); } - consider_lb_hairpin_flows(lb, local_datapaths, template_vars, + consider_lb_hairpin_flows(mgr, lb, local_datapaths, template_vars, use_ct_mark, flow_table, ids); } } @@ -2224,7 +2278,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_out->lb_deps_mgr, l_ctx_in->lb_table, + l_ctx_in->local_datapaths, l_ctx_in->template_vars, l_ctx_in->lb_hairpin_use_ct_mark, l_ctx_out->flow_table, @@ -2276,10 +2331,10 @@ lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *dp, const struct sbrec_logical_flow *lflow; SBREC_LOGICAL_FLOW_FOR_EACH_EQUAL ( lflow, lf_row, l_ctx_in->sbrec_logical_flow_by_logical_datapath) { - if (uuidset_find(l_ctx_out->lflows_processed, &lflow->header_.uuid)) { + if (uuidset_find(l_ctx_out->objs_processed, &lflow->header_.uuid)) { continue; } - uuidset_insert(l_ctx_out->lflows_processed, &lflow->header_.uuid); + uuidset_insert(l_ctx_out->objs_processed, &lflow->header_.uuid); consider_logical_flow__(lflow, dp, l_ctx_in, l_ctx_out); } sbrec_logical_flow_index_destroy_row(lf_row); @@ -2304,7 +2359,7 @@ lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *dp, sbrec_logical_flow_index_set_logical_dp_group(lf_row, ldpg); SBREC_LOGICAL_FLOW_FOR_EACH_EQUAL ( lflow, lf_row, l_ctx_in->sbrec_logical_flow_by_logical_dp_group) { - if (uuidset_find(l_ctx_out->lflows_processed, + if (uuidset_find(l_ctx_out->objs_processed, &lflow->header_.uuid)) { continue; } @@ -2356,7 +2411,8 @@ lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *dp, /* 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(dp_lbs[i], l_ctx_in->local_datapaths, + 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, @@ -2379,7 +2435,7 @@ lflow_handle_flows_for_lport(const struct sbrec_port_binding *pb, OBJDEP_TYPE_PORTBINDING, pb->logical_port, lflow_handle_changed_ref, - l_ctx_out->lflows_processed, + l_ctx_out->objs_processed, l_ctx_in, l_ctx_out, &changed)) { return false; } @@ -2418,7 +2474,7 @@ lflow_handle_changed_port_bindings(struct lflow_ctx_in *l_ctx_in, OBJDEP_TYPE_PORTBINDING, pb->logical_port, lflow_handle_changed_ref, - l_ctx_out->lflows_processed, + l_ctx_out->objs_processed, l_ctx_in, l_ctx_out, &changed)) { ret = false; break; @@ -2445,7 +2501,7 @@ lflow_handle_changed_mc_groups(struct lflow_ctx_in *l_ctx_in, if (!objdep_mgr_handle_change(l_ctx_out->lflow_deps_mgr, OBJDEP_TYPE_MC_GROUP, ds_cstr(&mg_key), lflow_handle_changed_ref, - l_ctx_out->lflows_processed, + l_ctx_out->objs_processed, l_ctx_in, l_ctx_out, &changed)) { ret = false; break; @@ -2499,7 +2555,8 @@ lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in, 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, + 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, diff --git a/controller/lflow.h b/controller/lflow.h index 8175bdbea..a1b11a07b 100644 --- a/controller/lflow.h +++ b/controller/lflow.h @@ -121,9 +121,10 @@ struct lflow_ctx_out { struct ovn_extend_table *group_table; struct ovn_extend_table *meter_table; struct objdep_mgr *lflow_deps_mgr; + struct objdep_mgr *lb_deps_mgr; struct lflow_cache *lflow_cache; struct conj_ids *conj_ids; - struct uuidset *lflows_processed; + struct uuidset *objs_processed; struct simap *hairpin_lb_ids; struct id_pool *hairpin_id_pool; }; @@ -173,4 +174,8 @@ bool lflow_handle_changed_mc_groups(struct lflow_ctx_in *, struct lflow_ctx_out *); bool lflow_handle_changed_port_bindings(struct lflow_ctx_in *, struct lflow_ctx_out *); + +void 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/ovn-controller.c b/controller/ovn-controller.c index 40afebf4e..1731e78b4 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -2805,13 +2805,15 @@ 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; - /* lflows processed in the current engine execution. + /* objects (lflows and lbs) processed in the current engine execution. * Cleared by en_lflow_output_clear_tracked_data before each engine * execution. */ - struct uuidset lflows_processed; + struct uuidset objs_processed; /* Data which is persistent and not cleared during * full recompute. */ @@ -2968,8 +2970,9 @@ init_lflow_ctx(struct engine_node *node, 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->lflows_processed = &fo->lflows_processed; + l_ctx_out->objs_processed = &fo->objs_processed; l_ctx_out->lflow_cache = fo->pd.lflow_cache; l_ctx_out->hairpin_id_pool = fo->hd.pool; l_ctx_out->hairpin_lb_ids = &fo->hd.ids; @@ -2984,8 +2987,9 @@ 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->lflows_processed); + uuidset_init(&data->objs_processed); simap_init(&data->hd.ids); data->hd.pool = id_pool_create(1, UINT32_MAX - 1); nd_ra_opts_init(&data->nd_ra_opts); @@ -2997,7 +3001,7 @@ static void en_lflow_output_clear_tracked_data(void *data) { struct ed_type_lflow_output *flow_output_data = data; - uuidset_clear(&flow_output_data->lflows_processed); + uuidset_clear(&flow_output_data->objs_processed); } static void @@ -3008,8 +3012,9 @@ 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->lflows_processed); + uuidset_destroy(&flow_output_data->objs_processed); lflow_cache_destroy(flow_output_data->pd.lflow_cache); simap_destroy(&flow_output_data->hd.ids); id_pool_destroy(flow_output_data->hd.pool); @@ -3044,6 +3049,7 @@ 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) { @@ -3053,6 +3059,7 @@ 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); } @@ -3186,7 +3193,7 @@ lflow_output_addr_sets_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_ADDRSET, ref_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, &l_ctx_in, &l_ctx_out, &changed)) { return false; } @@ -3205,7 +3212,7 @@ lflow_output_addr_sets_handler(struct engine_node *node, void *data) OBJDEP_TYPE_ADDRSET, shash_node->name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, &l_ctx_in, &l_ctx_out, &changed)) { return false; } @@ -3218,7 +3225,7 @@ lflow_output_addr_sets_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_ADDRSET, ref_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, &l_ctx_in, &l_ctx_out, &changed)) { return false; } @@ -3253,7 +3260,7 @@ lflow_output_port_groups_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_PORTGROUP, ref_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, &l_ctx_in, &l_ctx_out, &changed)) { return false; } @@ -3265,7 +3272,7 @@ lflow_output_port_groups_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_PORTGROUP, ref_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, &l_ctx_in, &l_ctx_out, &changed)) { return false; } @@ -3277,7 +3284,7 @@ lflow_output_port_groups_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_PORTGROUP, ref_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, &l_ctx_in, &l_ctx_out, &changed)) { return false; } @@ -3311,7 +3318,17 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_TEMPLATE, res_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, + &l_ctx_in, &l_ctx_out, &changed)) { + return false; + } + 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; } @@ -3323,7 +3340,17 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_TEMPLATE, res_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, + &l_ctx_in, &l_ctx_out, &changed)) { + return false; + } + 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; } @@ -3335,7 +3362,17 @@ lflow_output_template_vars_handler(struct engine_node *node, void *data) if (!objdep_mgr_handle_change(l_ctx_out.lflow_deps_mgr, OBJDEP_TYPE_TEMPLATE, res_name, lflow_handle_changed_ref, - l_ctx_out.lflows_processed, + l_ctx_out.objs_processed, + &l_ctx_in, &l_ctx_out, &changed)) { + return false; + } + 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; } diff --git a/lib/lb.c b/lib/lb.c index 15cbf29ee..97fdbc227 100644 --- a/lib/lb.c +++ b/lib/lb.c @@ -710,7 +710,8 @@ ovn_lb_group_find(const struct hmap *lb_groups, const struct uuid *uuid) struct ovn_controller_lb * ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb, - const struct smap *template_vars) + const struct smap *template_vars, + struct sset *template_vars_ref) { struct ovn_controller_lb *lb = xzalloc(sizeof *lb); @@ -726,10 +727,10 @@ ovn_controller_lb_create(const struct sbrec_load_balancer *sbrec_lb, char *key_s = lexer_parse_template_string(xstrdup(node->key), template_vars, - NULL); + template_vars_ref); char *value_s = lexer_parse_template_string(xstrdup(node->value), template_vars, - NULL); + template_vars_ref); char *error = ovn_lb_vip_init_explicit(lb_vip, key_s, value_s); if (error) { free(error); diff --git a/lib/lb.h b/lib/lb.h index 265a1215a..9fcbc7923 100644 --- a/lib/lb.h +++ b/lib/lb.h @@ -186,7 +186,8 @@ struct ovn_controller_lb { struct ovn_controller_lb *ovn_controller_lb_create( const struct sbrec_load_balancer *, - const struct smap *template_vars); + const struct smap *template_vars, + struct sset *template_vars_ref); void ovn_controller_lb_destroy(struct ovn_controller_lb *); char *ovn_lb_vip_init(struct ovn_lb_vip *lb_vip, const char *lb_key, _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
