diff options
author | Ilya Maximets <i.maximets@ovn.org> | 2022-09-13 21:08:52 +0200 |
---|---|---|
committer | Ilya Maximets <i.maximets@ovn.org> | 2022-09-16 13:56:17 +0200 |
commit | bae84a232f535652085604f20a5ad69e103dcc1b (patch) | |
tree | b22978fe45d03a4602374d0a9a332eb401b77d9d /ofproto/ofproto-dpif-xlate.c | |
parent | 58e4668a4f83df3f98ee40beeaefd5f07dd64389 (diff) | |
download | openvswitch-bae84a232f535652085604f20a5ad69e103dcc1b.tar.gz |
bond: Avoid deadlock while updating post recirculation rules.
If the PACKET_OUT from controller ends up with sending packet to
a bond interface, the main thread will take locks in the following
order:
handle_openflow
--> take ofproto_mutex
handle_packet_out
packet_xlate
output_normal
bond_update_post_recirc_rules
--> take rwlock in bond.c
If at the same time revalidator thread is processing other packet
with the output to the same bond:
xlate_actions
output_normal
bond_update_post_recirc_rules
--> take rwlock in bond.c
update_recirc_rules
ofproto_dpif_add_internal_flow
ofproto_flow_mod
--> take ofproto_mutex
So, it is possible for these 2 threads to lock each other by
taking one lock and waiting for another thread to release the
second lock.
It is also possible for the main thread to lock itself up by trying
to acquire ofproto_mutex for the second time, if it will actually
proceed with update_recirc_rules() after taking the bond rwlock.
The problem appears to be that bond_update_post_recirc_rules()
is called during the flow translation even if side effects are
prohibited, which is the case for openflow PACKET_OUT handling.
Skipping actual flow updates during the flow translation if
side effects are disabled to avoid the deadlock.
Since flows are not installed now when actions translated for
very first packet, installing initial flows in bond_reconfigure().
This will cover the case of allocating a new recirc_id.
Also checking if we need to update flows in bond_run() to cover
link state changes.
Regression test is added to catch the double lock case.
Reported-at: https://github.com/openvswitch/ovs-issues/issues/259
Reported-by: Daniel Ding <zhihui.ding@easystack.cn>
Fixes: adcf00ba35a0 ("ofproto/bond: Implement bond megaflow using recirculation")
Acked-by: Mike Pattrick <mkp@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'ofproto/ofproto-dpif-xlate.c')
-rw-r--r-- | ofproto/ofproto-dpif-xlate.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index b8886105d..330ef0784 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2466,9 +2466,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle, /* In case recirculation is not actually in use, 'xr.recirc_id' * will be set to '0', since a valid 'recirc_id' can * not be zero. */ - bond_update_post_recirc_rules(out_xbundle->bond, - &xr.recirc_id, - &xr.hash_basis); + if (ctx->xin->allow_side_effects) { + bond_update_post_recirc_rules(out_xbundle->bond, + &xr.recirc_id, + &xr.hash_basis); + } else { + /* If side effects are not allowed, only getting the bond + * configuration. Rule updates will be handled by the + * main thread later. */ + bond_get_recirc_id_and_hash_basis(out_xbundle->bond, + &xr.recirc_id, + &xr.hash_basis); + } if (xr.recirc_id) { /* Use recirculation instead of output. */ use_recirc = true; |