@@ -1091,7 +1091,22 @@ ovn_lb_datapaths_add_ls(struct ovn_lb_datapaths *lb_dps, size_t n,
struct ovn_datapath **ods)
{
for (size_t i = 0; i < n; i++) {
- bitmap_set1(lb_dps->nb_ls_map, ods[i]->index);
+ if (!bitmap_is_set(lb_dps->nb_ls_map, ods[i]->index)) {
+ bitmap_set1(lb_dps->nb_ls_map, ods[i]->index);
+ lb_dps->n_nb_ls++;
+ }
+ }
+}
+
+void
+ovn_lb_datapaths_remove_ls(struct ovn_lb_datapaths *lb_dps, size_t n,
+ struct ovn_datapath **ods)
+{
+ for (size_t i = 0; i < n; i++) {
+ if (bitmap_is_set(lb_dps->nb_ls_map, ods[i]->index)) {
+ bitmap_set0(lb_dps->nb_ls_map, ods[i]->index);
+ lb_dps->n_nb_ls--;
+ }
}
}
@@ -179,6 +179,8 @@ void ovn_lb_datapaths_add_lr(struct ovn_lb_datapaths *, size_t n,
struct ovn_datapath **);
void ovn_lb_datapaths_add_ls(struct ovn_lb_datapaths *, size_t n,
struct ovn_datapath **);
+void ovn_lb_datapaths_remove_ls(struct ovn_lb_datapaths *, size_t n,
+ struct ovn_datapath **);
struct ovn_lb_group_datapaths {
struct hmap_node hmap_node;
@@ -853,7 +853,8 @@ ovn_datapath_destroy(struct hmap *datapaths, struct ovn_datapath *od)
ovn_ls_port_group_destroy(&od->nb_pgs);
destroy_mcast_info_for_datapath(od);
destroy_ports_for_datapath(od);
-
+ free(od->lb_uuids);
+ free(od->lb_group_uuids);
free(od);
}
}
@@ -4036,6 +4037,48 @@ build_lb_vip_actions(const struct ovn_northd_lb *lb,
return reject;
}
+static void
+associate_ls_lbs(struct ovn_datapath *ls_od, struct hmap *lb_datapaths_map)
+{
+ struct ovn_lb_datapaths *lb_dps;
+
+ free(ls_od->lb_uuids);
+ ls_od->lb_uuids = xcalloc(ls_od->nbs->n_load_balancer,
+ sizeof *ls_od->lb_uuids);
+ ls_od->n_lb_uuids = ls_od->nbs->n_load_balancer;
+ for (size_t i = 0; i < ls_od->nbs->n_load_balancer; i++) {
+ const struct uuid *lb_uuid =
+ &ls_od->nbs->load_balancer[i]->header_.uuid;
+ lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid);
+ ovs_assert(lb_dps);
+ ovn_lb_datapaths_add_ls(lb_dps, 1, &ls_od);
+ ls_od->lb_uuids[i] = *lb_uuid;
+ }
+}
+
+static void
+associate_ls_lb_groups(struct ovn_datapath *ls_od,
+ struct hmap *lb_group_datapaths_map)
+{
+ const struct nbrec_load_balancer_group *nbrec_lb_group;
+ struct ovn_lb_group_datapaths *lb_group_dps;
+
+ free(ls_od->lb_group_uuids);
+ ls_od->lb_group_uuids = xcalloc(ls_od->nbs->n_load_balancer_group,
+ sizeof *ls_od->lb_group_uuids);
+ ls_od->n_lb_group_uuids = ls_od->nbs->n_load_balancer_group;
+ for (size_t i = 0; i < ls_od->nbs->n_load_balancer_group; i++) {
+ nbrec_lb_group = ls_od->nbs->load_balancer_group[i];
+ const struct uuid *lb_group_uuid = &nbrec_lb_group->header_.uuid;
+ lb_group_dps =
+ ovn_lb_group_datapaths_find(lb_group_datapaths_map,
+ lb_group_uuid);
+ ovs_assert(lb_group_dps);
+ ovn_lb_group_datapaths_add_ls(lb_group_dps, 1, &ls_od);
+ ls_od->lb_group_uuids[i] = *lb_group_uuid;
+ }
+}
+
static void
build_lb_datapaths(const struct hmap *lbs, const struct hmap *lb_groups,
struct ovn_datapaths *ls_datapaths,
@@ -4071,24 +4114,8 @@ build_lb_datapaths(const struct hmap *lbs, const struct hmap *lb_groups,
if (!od->nbs) {
continue;
}
-
- for (size_t i = 0; i < od->nbs->n_load_balancer; i++) {
- const struct uuid *lb_uuid =
- &od->nbs->load_balancer[i]->header_.uuid;
- lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, lb_uuid);
- ovs_assert(lb_dps);
- ovn_lb_datapaths_add_ls(lb_dps, 1, &od);
- }
-
- for (size_t i = 0; i < od->nbs->n_load_balancer_group; i++) {
- nbrec_lb_group = od->nbs->load_balancer_group[i];
- const struct uuid *lb_group_uuid = &nbrec_lb_group->header_.uuid;
- lb_group_dps =
- ovn_lb_group_datapaths_find(lb_group_datapaths_map,
- lb_group_uuid);
- ovs_assert(lb_group_dps);
- ovn_lb_group_datapaths_add_ls(lb_group_dps, 1, &od);
- }
+ associate_ls_lbs(od, lb_datapaths_map);
+ associate_ls_lb_groups(od, lb_group_datapaths_map);
}
HMAP_FOR_EACH (od, key_node, &lr_datapaths->datapaths) {
@@ -4847,23 +4874,29 @@ build_ports(struct ovsdb_idl_txn *ovnsb_txn,
sset_destroy(&active_ha_chassis_grps);
}
+static void
+destroy_tracked_ls_change(struct ls_change *ls_change)
+{
+ struct ovn_port *op;
+ LIST_FOR_EACH (op, list, &ls_change->added_ports) {
+ ovs_list_remove(&op->list);
+ }
+ LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
+ ovs_list_remove(&op->list);
+ }
+ LIST_FOR_EACH_SAFE (op, list, &ls_change->deleted_ports) {
+ ovs_list_remove(&op->list);
+ ovn_port_destroy_orphan(op);
+ }
+}
+
void
destroy_northd_data_tracked_changes(struct northd_data *nd)
{
struct ls_change *ls_change;
LIST_FOR_EACH_SAFE (ls_change, list_node,
&nd->tracked_ls_changes.updated) {
- struct ovn_port *op;
- LIST_FOR_EACH (op, list, &ls_change->added_ports) {
- ovs_list_remove(&op->list);
- }
- LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
- ovs_list_remove(&op->list);
- }
- LIST_FOR_EACH_SAFE (op, list, &ls_change->deleted_ports) {
- ovs_list_remove(&op->list);
- ovn_port_destroy_orphan(op);
- }
+ destroy_tracked_ls_change(ls_change);
ovs_list_remove(&ls_change->list_node);
free(ls_change);
}
@@ -4980,6 +5013,7 @@ ls_port_create(struct ovsdb_idl_txn *ovnsb_txn, struct hmap *ls_ports,
* incrementally handled.
* Presently supports i-p for the below changes:
* - logical switch ports.
+ * - load balancers.
*/
static bool
check_unsupported_inc_proc_for_ls_changes(
@@ -4988,8 +5022,11 @@ check_unsupported_inc_proc_for_ls_changes(
/* Check if the columns are changed in this row. */
enum nbrec_logical_switch_column_id col;
for (col = 0; col < NBREC_LOGICAL_SWITCH_N_COLUMNS; col++) {
- if (nbrec_logical_switch_is_updated(ls, col) &&
- col != NBREC_LOGICAL_SWITCH_COL_PORTS) {
+ if (nbrec_logical_switch_is_updated(ls, col)) {
+ if (col == NBREC_LOGICAL_SWITCH_COL_PORTS ||
+ col == NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER) {
+ continue;
+ }
return true;
}
}
@@ -5018,12 +5055,6 @@ check_unsupported_inc_proc_for_ls_changes(
return true;
}
}
- for (size_t i = 0; i < ls->n_load_balancer; i++) {
- if (nbrec_load_balancer_row_get_seqno(ls->load_balancer[i],
- OVSDB_IDL_CHANGE_MODIFY) > 0) {
- return true;
- }
- }
for (size_t i = 0; i < ls->n_load_balancer_group; i++) {
if (nbrec_load_balancer_group_row_get_seqno(ls->load_balancer_group[i],
OVSDB_IDL_CHANGE_MODIFY) > 0) {
@@ -5082,7 +5113,9 @@ ls_check_and_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
const struct nbrec_logical_switch *changed_ls,
const struct northd_input *ni,
struct northd_data *nd,
- struct ovn_datapath *od)
+ struct ovn_datapath *od,
+ struct ls_change *ls_change,
+ bool *updated)
{
bool ls_ports_changed = false;
if (!nbrec_logical_switch_is_updated(changed_ls,
@@ -5103,12 +5136,6 @@ ls_check_and_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
return true;
}
- struct ls_change *ls_change = xzalloc(sizeof *ls_change);
- ls_change->od = od;
- ovs_list_init(&ls_change->added_ports);
- ovs_list_init(&ls_change->deleted_ports);
- ovs_list_init(&ls_change->updated_ports);
-
struct ovn_port *op;
HMAP_FOR_EACH (op, dp_node, &od->ports) {
op->visited = false;
@@ -5195,19 +5222,66 @@ ls_check_and_handle_lsp_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
if (!ovs_list_is_empty(&ls_change->added_ports) ||
!ovs_list_is_empty(&ls_change->updated_ports) ||
!ovs_list_is_empty(&ls_change->deleted_ports)) {
- ovs_list_push_back(&nd->tracked_ls_changes.updated,
- &ls_change->list_node);
- } else {
- free(ls_change);
+ *updated = true;
}
return true;
fail:
- free(ls_change);
+
+ LIST_FOR_EACH (op, list, &ls_change->added_ports) {
+ ovs_list_remove(&op->list);
+ }
+ LIST_FOR_EACH (op, list, &ls_change->updated_ports) {
+ ovs_list_remove(&op->list);
+ }
+ LIST_FOR_EACH_SAFE (op, list, &ls_change->deleted_ports) {
+ ovs_list_remove(&op->list);
+ ovn_port_destroy_orphan(op);
+ }
return false;
}
+static bool
+ls_check_and_handle_lb_changes(const struct nbrec_logical_switch *changed_ls,
+ struct hmap *lb_datapaths_map,
+ struct ovn_datapath *od,
+ struct ls_change *ls_change,
+ bool *updated)
+{
+
+ if (!nbrec_logical_switch_is_updated(changed_ls,
+ NBREC_LOGICAL_SWITCH_COL_LOAD_BALANCER)) {
+ for (size_t i = 0; i < changed_ls->n_load_balancer; i++) {
+ if (nbrec_load_balancer_row_get_seqno(changed_ls->load_balancer[i],
+ OVSDB_IDL_CHANGE_MODIFY) > 0) {
+ ls_change->lbs_changed = true;
+ *updated = true;
+ /* Re-evaluate 'od->has_lb_vip' */
+ init_lb_for_datapath(od);
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ struct ovn_lb_datapaths *lb_dps;
+ for (size_t i = 0; i < od->n_lb_uuids; i++) {
+ lb_dps = ovn_lb_datapaths_find(lb_datapaths_map, &od->lb_uuids[i]);
+ if (lb_dps) {
+ ovn_lb_datapaths_remove_ls(lb_dps, 1, &od);
+ }
+ }
+
+ associate_ls_lbs(od, lb_datapaths_map);
+ ls_change->lbs_changed = true;
+ *updated = true;
+ /* Re-evaluate 'od->has_lb_vip' */
+ init_lb_for_datapath(od);
+ return true;
+}
+
/* Return true if changes are handled incrementally, false otherwise.
* When there are any changes, try to track what's exactly changed and set
@@ -5238,20 +5312,47 @@ northd_handle_ls_changes(struct ovsdb_idl_txn *ovnsb_idl_txn,
goto fail;
}
- /* Now only able to handle lsp changes. */
+ /* Now only able to handle lsp, load balancerload and
+ * load balancer group changes. */
if (check_unsupported_inc_proc_for_ls_changes(changed_ls)) {
goto fail;
}
+ struct ls_change *ls_change = xzalloc(sizeof *ls_change);
+ ls_change->od = od;
+ ovs_list_init(&ls_change->added_ports);
+ ovs_list_init(&ls_change->deleted_ports);
+ ovs_list_init(&ls_change->updated_ports);
+
+ bool updated = false;
if (!ls_check_and_handle_lsp_changes(ovnsb_idl_txn, changed_ls,
- ni, nd, od)) {
+ ni, nd, od, ls_change,
+ &updated)) {
+ destroy_tracked_ls_change(ls_change);
+ free(ls_change);
goto fail;
}
+
+ if (!ls_check_and_handle_lb_changes(changed_ls,
+ &nd->lb_datapaths_map, od,
+ ls_change, &updated)) {
+ destroy_tracked_ls_change(ls_change);
+ free(ls_change);
+ goto fail;
+ }
+
+ if (updated) {
+ ovs_list_push_back(&nd->tracked_ls_changes.updated,
+ &ls_change->list_node);
+ } else {
+ free(ls_change);
+ }
}
if (!ovs_list_is_empty(&nd->tracked_ls_changes.updated)) {
nd->change_tracked = true;
}
+
return true;
fail:
@@ -16422,6 +16523,12 @@ bool lflow_handle_northd_ls_changes(struct ovsdb_idl_txn *ovnsb_txn,
struct hmap *lflows)
{
struct ls_change *ls_change;
+ LIST_FOR_EACH (ls_change, list_node, &ls_changes->updated) {
+ if (ls_change->lbs_changed) {
+ return false;
+ }
+ }
+
LIST_FOR_EACH (ls_change, list_node, &ls_changes->updated) {
ovs_list_init(&temp_lflow_list);
add_lflow_to_temp_list = true;
@@ -94,6 +94,7 @@ struct ls_change {
struct ovs_list added_ports;
struct ovs_list deleted_ports;
struct ovs_list updated_ports;
+ bool lbs_changed;
};
/* Track what's changed for logical switches.
@@ -318,6 +319,14 @@ struct ovn_datapath {
/* Map of ovn_port objects belonging to this datapath.
* This map doesn't include derived ports. */
struct hmap ports;
+
+ /* LB uuids associated with this datapath. */
+ struct uuid *lb_uuids;
+ size_t n_lb_uuids;
+
+ /* LB group uuids associated with this datapath. */
+ struct uuid *lb_group_uuids;
+ size_t n_lb_group_uuids;
};
void ovnnb_db_run(struct northd_input *input_data,
@@ -9677,15 +9677,15 @@ check ovn-nbctl ls-add sw0
check ovn-nbctl --wait=sb lr-add lr0
check_engine_stats recompute recompute
-# Associate lb1 to sw0. There should be a full recompute of northd engine node
+# Associate lb1 to sw0. There should be no recompute of northd engine node
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 recompute recompute
+check_engine_stats norecompute recompute
-# Disassociate lb1 from sw0. There should be a full recompute of northd engine node.
+# Disassociate lb1 from sw0. There should be a no recompute of northd engine node.
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 recompute recompute
+check_engine_stats norecompute recompute
# Test load balancer group now
check as northd ovn-appctl -t NORTHD_TYPE inc-engine/clear-stats