When two chassis claim the same port, if a port is in the MARK_UP state when the other chassis claims it, then ovn-controller was sometimes using 100% cpu, as if-status was fighting to add ovn-install (as in the MARK_UP state) and binding was fighting to remove it (as the port was bound to the other chassis).
Signed-off-by: Xavier Simonart <[email protected]> --- v2: rebase on origin/main for scapy fix. --- controller/binding.c | 15 +++++---------- controller/if-status.c | 27 +++++++++++++++++++++------ controller/if-status.h | 3 +-- tests/ovn.at | 3 +++ 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/controller/binding.c b/controller/binding.c index 3b9bc8620..8c6f5aabe 100644 --- a/controller/binding.c +++ b/controller/binding.c @@ -1608,8 +1608,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, /* Release the lport if there is no lbinding. */ if (lbinding_set && !can_bind) { if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, - b_lport->lbinding->iface->name, - &b_lport->lbinding->iface->header_.uuid); + b_lport->lbinding->iface); } if (!lbinding_set || !can_bind) { @@ -1626,8 +1625,7 @@ consider_vif_lport_(const struct sbrec_port_binding *pb, pb->logical_port)) { update_lport_tracking(pb, b_ctx_out->tracked_dp_bindings, false); if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, - b_lport->lbinding->iface->name, - &b_lport->lbinding->iface->header_.uuid); + b_lport->lbinding->iface); } return true; @@ -2062,8 +2060,7 @@ build_local_bindings(struct binding_ctx_in *b_ctx_in, * This can happen if iface-id was removed as we recompute. */ if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, - iface_rec->name, - &iface_rec->header_.uuid); + iface_rec); } } } @@ -2491,8 +2488,7 @@ consider_iface_release(const struct ovsrec_interface *iface_rec, } if (lbinding->iface && lbinding->iface->name) { if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, - lbinding->iface->name, - &lbinding->iface->header_.uuid); + lbinding->iface); } } else if (b_lport && b_lport->type == LP_LOCALPORT) { @@ -2824,8 +2820,7 @@ handle_deleted_vif_lport(const struct sbrec_port_binding *pb, handle_deleted_lport(pb, b_ctx_in, b_ctx_out); if (lbinding && lbinding->iface && lbinding->iface->name) { if_status_mgr_remove_ovn_installed(b_ctx_out->if_mgr, - lbinding->iface->name, - &lbinding->iface->header_.uuid); + lbinding->iface); } return true; } diff --git a/controller/if-status.c b/controller/if-status.c index ada78a18b..dc7b66ee2 100644 --- a/controller/if-status.c +++ b/controller/if-status.c @@ -71,6 +71,8 @@ enum if_state { * but not yet marked "up" in the binding module (in * SB and OVS databases). */ + OIF_UNINSTALLED, /* Interface from whom ovn-install must be removed + */ OIF_INSTALLED, /* Interface flows programmed in OVS and binding * marked "up" in the binding module. */ @@ -89,6 +91,7 @@ static const char *if_state_names[] = { [OIF_REM_OLD_OVN_INST] = "REM_OLD_OVN_INST", [OIF_MARK_UP] = "MARK_UP", [OIF_MARK_DOWN] = "MARK_DOWN", + [OIF_UNINSTALLED] = "UNINSTALLED", [OIF_INSTALLED] = "INSTALLED", [OIF_UPDATE_PORT] = "UPDATE_PORT", }; @@ -326,6 +329,7 @@ if_status_mgr_claim_iface(struct if_status_mgr *mgr, /* Nothing to do here. */ break; case OIF_INSTALLED: + case OIF_UNINSTALLED: case OIF_MARK_DOWN: case OIF_UPDATE_PORT: ovs_iface_set_state(mgr, iface, OIF_CLAIMED); @@ -362,6 +366,7 @@ if_status_mgr_release_iface(struct if_status_mgr *mgr, const char *iface_id) case OIF_REM_OLD_OVN_INST: case OIF_MARK_UP: case OIF_INSTALLED: + case OIF_UNINSTALLED: /* Properly mark interfaces "down" if their flows were already * programmed in OVS. */ @@ -402,6 +407,7 @@ if_status_mgr_delete_iface(struct if_status_mgr *mgr, const char *iface_id, case OIF_REM_OLD_OVN_INST: case OIF_MARK_UP: case OIF_INSTALLED: + case OIF_UNINSTALLED: /* Properly mark interfaces "down" if their flows were already * programmed in OVS. */ @@ -634,13 +640,22 @@ if_status_mgr_update(struct if_status_mgr *mgr, void if_status_mgr_remove_ovn_installed(struct if_status_mgr *mgr, - const char *name, - const struct uuid *uuid) + const struct ovsrec_interface *iface_rec) { - VLOG_DBG("Adding %s to list of interfaces for which to remove " - "ovn-installed", name); - if (!shash_find_data(&mgr->ovn_uninstall_hash, name)) { - add_to_ovn_uninstall_hash(mgr, name, uuid); + if (!shash_find_data(&mgr->ovn_uninstall_hash, iface_rec->name)) { + VLOG_DBG("Adding %s to list of interfaces for which to remove " + "ovn-installed", iface_rec->name); + add_to_ovn_uninstall_hash(mgr, iface_rec->name, + &iface_rec->header_.uuid); + } + + /* Move out of MARK_UP state which would add ovn-install back. */ + const char *iface_id = smap_get(&iface_rec->external_ids, "iface-id"); + if (iface_id) { + struct ovs_iface *iface = shash_find_data(&mgr->ifaces, iface_id); + if (iface && iface->state == OIF_MARK_UP) { + ovs_iface_set_state(mgr, iface, OIF_UNINSTALLED); + } } } diff --git a/controller/if-status.h b/controller/if-status.h index 4ae5ad481..eb91b62fd 100644 --- a/controller/if-status.h +++ b/controller/if-status.h @@ -61,8 +61,7 @@ bool if_status_handle_claims(struct if_status_mgr *mgr, const struct sbrec_port_binding_table *pb_table, bool sb_readonly); void if_status_mgr_remove_ovn_installed(struct if_status_mgr *mgr, - const char *name, - const struct uuid *uuid); + const struct ovsrec_interface *iface_rec); uint16_t if_status_mgr_iface_get_mtu(const struct if_status_mgr *mgr, const char *iface_id); bool if_status_mgr_iface_update(const struct if_status_mgr *mgr, diff --git a/tests/ovn.at b/tests/ovn.at index 826b52051..f52d7f3e2 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -16552,6 +16552,9 @@ max_claims=20 AT_CHECK([test "${hv1_claims}" -le "${max_claims}"], [0], []) AT_CHECK([test "${hv2_claims}" -le "${max_claims}"], [0], []) +n_uninstalled=$(as hv1 grep -c 'Removing iface vif ovn-installed in' hv1/ovn-controller.log) +echo "$n_uninstalled times 'Removing iface vif ovn-installed'" +AT_CHECK([test "${n_uninstalled}" -le "10"], [0], []) check ovn-nbctl --wait=hv lsp-del lsp0 CHECK_AFTER_RECOMPUTE([hv1], [hv1]) -- 2.31.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
